a companion discussion area for blog.codinghorror.com

The Best Code is No Code At All


#41

Although I agree with most of all people here and I would use String.Empty, I dont think the reason is clarity. s=="" compared to s==String.Empty in terms of clarity comparison is not the same as a single letter named variable versus a clear-purpose named variable. It is not the reasonwhy we should not use “”. The reason depends on the importance of the project and how many times we estimate that this snippet which contains s=="" will appear in our code. The mistake I see in Jeff’s example (and strictly to this specific example) is that does not take advantage of a ‘bonus, free of charge’ abstraction level that the framework offers him. Even if he does not need it now, he may need it in the future.

I would accept Jeff’s opinion if he could guarantee that “”==String.Empty all the time. In his example he assumes this, propably because he has something specific in his mind, like an example code snippet to illustrate an opinion. But in our minds “” may not be equal to String.Empty because of our reasons. If I need a small app to do a simple thing just for once then “”==String.Empty is true, but if I need a bigger app and I have the slightest doubt that I will do that comparison of s with “” or String.Empty only once in my code then I will definitely use the String.Empty abstraction of “” that the framework donates to me. I am thinking that I will be able to redefine String.Empty and change its meaning in one place. I wont have to search for “” and replace it by “0” just because a damn scanner reports “0” instead of “” when it scans a product with no serial number given yet.

I know I could have descrideb my opinion more briefly but I dont know the english language framework so well :slight_smile:


#42

And whats more, If that damned scanner was used after I abandoned the code and someone else was maintaining it, believe me if he saw String.Empty he would understand better what the code wants to do.

:stuck_out_tongue:


#43

My personal coding mantra:

No Code is Good Code

:wink:


#44

“Source code is for humans to read, and only incidentally for machines to run.” - whoever said that (possibly Don Knuth^) knew a thing or two.

^ http://xkcd.com/c163.html

trousercuit : You want it in 17 lines? Does it have to fit in 80 columns ? (with apologies to Larry Wall)


#45

This is true, but it can become a bit of a problem when designing (or not designing) an SDK or library. When you try to make your own code simpler, you can end up making other people do more work and write more code.

I don’t know yet if there’s a solution to that conflict.


#46

Also, simple, easy to work with code does not neccesarily mean fewer lines or fewer bytes.

Reed


#47

Not brevity, clarity. Clarity, clarity, clarity.

Write code whose purpose and operation are clear and readily understood from reading the code.

Brevity makes code clearer nearly always, but not always.


#48

Some of us write code we will see over and over again in the years to come; some of us write code we will never see again. Some of us are on a very strict deadline; some of us have a bit more flexibility. Some of us have to write to strict coding standards; some of us don’t. “Brevity” means different things to each.

Code is communication. Some of us communicate with the compiler; some of us communicate with our future selves; some of us communicate with some unknown future maintainer. We do so because of the environments we are in.

When someone text messages CUL8R, they are being “brief.” To them, it is a recognizible element. When I get it, I have to parse it out… it is not immediately recognizible and, for me, it is not “brief” but tedious.


#49

To be Good Code, it must be brief, beautiful and bountiful. In other words it must be as short as possible, well formed with good variable names (long enough to mean something, short enough to read) and structures, and do something useful.

One of the things that used to kill me was when people would always want to break code into the smallest possible procedures, classes or structures. Sure, your functions were 10 lines long. But to actually debug it I had to dereference 10 times and follow Alice down the rabbit hole to find out what was going on.

Like John P above me said, clear code is usually brief. Brief code is not always clear.


#50

I have noticed that often Jeff writes from the viewpoint of an application developer (and often, very specific kinds of applications).
Indeed, when developing libraries the guiding principle is designing good interfaces, writing robust code, and caring about your user (and the library maintainer). The complexity of your code is simply not important as your clients (users of the library). And since library development and design is hard (it can be very hard), you have to trust that whoever maintains the library code is good enough. Again, clarity of code is really not on top of the list of priorities.

An interesting example is C++ STL. It is VERY easy to use. Incredibly easy, in fact, compared to the power it gives to the library user. But this comes at a price - the STL implementation is very complex.
Yet some of the STL implementations go for brevity, which makes the code even LESS clear.

I say this: always consider the various trade-offs when you write code (or design). Brevity sometimes make the code clearer, but as often as not, it does not. Sometimes clear code is simply not possible given the (time,performance,robustness,code,requirements) constraints.
Write code with your brain turned on. Design with forethought. Don’t over-engineer, or under-engineer. Don’t be tempted to assume that one rule is always true.


#51

I think this is very bad example using “” and String.Empty. Because essentially “” is a magic number of sorts, I am talking totally theoretical here, I know that “” is never going to change from representing a empty string, but what happens when developers start using “\n\r” instead of Environment.NewLine, not only does it cause a problem if you move to Mono it also requires a higher knowledge level to understand what “\n\r” means and you even have to remember what order it goes in.

It is good practice to get developers thinking that magic values such as “” and “\n\r” and any number is not the right way to code. Because if you tell them it is okay to use “” then why is it not okay to use 3.14F for PI instead of using Math.Pi?

It’s all about staying consistent and having the least amount of rules as possible, that is how you keep code simple across your organization.

Also by your same logic a developer should never use VB.NET because the language is way to verbose. I personally am a C# developer, but if a person is more productive in VB.NET and it meets the requirements for the project who am I to tell them they should use C# because it is less verbose.


#52

Agree completely.
In fact, Thomas Kyte, the Oracle (specifically SQL) Guru keeps saying the same thing. One of the best examples that he gives for this is as follows:

A common requirement is update a record in table if it already exists, otherwise add a new record.
Logic as used by many:

SELECT COUNT(*)
INTO l_ctr
FROM MY_TABLE
WHERE key column = key column value;

If l_ctr = 0 THEN
INSERT INTO MY_TABLE (column list)
values (values);
Else
UPDATE MY_TABLE
SET columns = values
WHERE key column = key column value ;
End If;

Ideally, what should be used is a MERGE statement (in Oracle 9i and above and if using data from other table) orfollowing (in oracle 8i and below):

=================================================
UPDATE MY_TABLE
SET columns = values
WHERE key column = key column value ;

IF SQL%ROWCOUNT = 0 THEN
INSERT INTO MY_TABLE (column list)
values (values);

That SELECT is completely unnecessary.


#53

Roddy,

I like your boolean example, it is not because the developers want to be verbose it is just because developers don’t know boolean logic. I still hold my stance that the biggest hurdle in programing for the common developer is boolean logic.


#54

Good post… the code example was a bit weak, tho. Like others, I too, favour the StringUtils.isBlank(str) approach.


#55

You are missing an important distinction.

when you say “less code means less bugs”, we’re already assuming no spelling errors that the compiler can catch, right?

This implies that what you really mean is less unique operations, or less symbols is better.

I seriously doubt you’re saying that x=x+5 is better than increaseOutputBy(STD_INCREASE_RATE).

What you’re really saying is my oldest programming mantra–fully factored code is the only REAL measure of good code (if it does “the job” that is)

Honestly I don’t even care if it has errors, and is poorly documented if it’s fully factored, I can fix them easily. If it’s cut and past garbage that is fully documented and error-free (as though…), a small upgrade can take weeks of hair-pulling.

The new version of my little mantra is “DRY”, Don’t Repeat Yourself.

But get rid of the idea that a language is better because it has 30 ways to save a keystroke, it’s not keystrokes that are the problem by any stretch of the imagination.

Having the choice between:
func(a)
and
func a

is simply a lack of consistency, it doesn’t save a thing except 2 keystrokes–and as we’ve already seen, keystrokes aren’t a measure of anything.

Same with:
s="Bill was $(where)"
over
s="Bill was "+where

not a single bloody advantage (in fact, in some cases, it’s an EXTRA keystroke) but it clutters the language and adds to a significantly screwed up escaping system.

I’m also dealing with horrible code patterns like this now:

@user.attributes = valid_user_attributes.except :last_name
@user.should_not be_valid

Really cute concept, make the tests look readable. The problem is if the language hadn’t tempted them with the ability to leave off parens and override operators, it could have looked like this:

spec(“set user attributes to valid user attributes except last name”,
“user should not be valid”)

Neat, no random underline/dot patterns to get wrong and the code is even clearer. Simply because the library decided not to be tricky.

Your plug-in could even syntax check the above strings–or even use a new file type just for creating the tests. Everything would be easier, everything more straight-forward.

Wow, much easier. Data NEEDS to be data. Letting your language be so flexible that it tempts programmers to show of is just an invitation for disaster.

So stay away from “Brief” and start using “DRY”, because brief without DRY is far worse than DRY without brief.

Hell, in fact I would venture to wager (a LOT) that the optimum solution (out of a set of decent program samples that all accomplish the same thing in the same language) is actually going to be the MOST verbose solution that is still DRY.


#56

I gotta run, but I just wanted to comment on how we stopped focusing so much on machine optimization and more on human readability and maintainability. For many applications, our machines are fast enough. Also, we have come up with enough optimizers and caching systems to take care of stuff automatically for us, leaving us to write code conceptually, which finally liberates us from the silly machine dependency.

Now if only programming languages would get more intuitive, we’ll be on our way toward star trek :slight_smile:


#57

Less code means fewer bugs.

Each statement should do one and only one thing.

No subroutine / method / procedure / function should take up more than a page when printed out. If you can’t see it all at once, how are you going to understand what it does?

Comment extravagantly. One comment per five lines of code is a good average.

Small is beautiful. Keep it simple, stupid!

Test as you write. Five lines at a time is usually OK.

Never try to understand other people’s code, it’s always garbage. :wink: Rewrite it from scratch. It’s quicker and you know it works.

The best programs are written when you have nothing but a pencil and paper to hand.


#58

Wow, programmers are nothing if not pedantic. The example is meaningless and unimportant. Try reading the article again if you think it’s in anyway about proper empty string handling. Or I can highlight the most important sentence for you:

“Every new line of code you willingly bring into the world is code that has to be debugged, code that has to be read and understood, code that has to be supported.”


#59

Aaron asks above whether LINQ queries may be explicitly typed. Provided that the return type of the query does not include an anonymous type, then sure, why not? “var” is only necessary when the type has no name; if the type has a name then using “var” is merely a convenience.

Note also that you could write your routine as an extension method:
public static class MyUsefulExtensions{
static IEnumerableint Square(this IEnumerableint list) {
return from x in list select x*x;
}
}

IEnumerableint squares = mylist.Square();

which is a syntactic sugar for

IEnumerableint squares = MyUsefulExtensions.Square(mylist);

However, in such a simple case one probably would not write the method to return a query. I would be more inclined to write this as

public static class MyUsefulExtensions{
static IEnumerableint Square(this IEnumerableint list) {
foreach(int x in list) yield x*x;
}
}

Either way, it does basically the same thing.


#60

I agree with you, but at the same time it makes me happy to include things in my code that do absolutely nothing…I know this sounds cruel and unusual but I somtimes like to think of all my successors looking at my code and saying WTF?