views:

677

answers:

12

Did you ever find yourself writing terse code in Java, C# or C++?

If so, why? Do you think there are any situations in which this should be acceptable, given the situations in which these languages are used?

+1  A: 

Barring all other concerns, shorter code is better, since you can see more of it at once.

mquander
+4  A: 

Try to always write clear code. Sometimes clear code is terse, but often it's not.

Why? Because in 6 months' time you'll need to understand what you were trying to achieve. The faster you can do that, the better.

j_random_hacker
+18  A: 

It depends on your definition of 'terse'.

If you mean 'short and to the point', it closely matches my vision for good code.

If you mean 'cryptic', then there's a problem.

Joel Coehoorn
+1: Agree 200% on the matches good code.
Richard
+10  A: 

It depends on what exactly you mean by "terse". I certainly like to write concise code which expresses exactly what I want to achieve in the simplest possible manner. For example, I love the way LINQ lets me express a data pipeline rather than the "old" way of writing loops to transform or filter collections, or find the largest value etc. That's just duplicate code which should be in a template method somewhere.

On the other hand, shorter code isn't always more readable than longer code. The conditional operator is the subject of controversy on this front. Is:

Foo x = null;
if (condition)
{
    x = y;
}
else
{
    x = z;
}

more or less readable than:

Foo x = condition ? y : z;

Well, if "condition", "y" and "z" are all fairly simple, the conditional operator wins. If you have to go through hoops to make "y" and "z" single expressions where executing multiple statements would be more readable, then the if/else form is likely to be more readable.

In short, I write the most readable code I can. That's often, but not always, terse code.

Jon Skeet
almost, but not quite, entirely unlike terse code?
Mario Ortegón
/me checks watch... time for a cuppa.
Richard
A: 

Assuming you're using the term "terse" with the "cryptic" connotation:

Unless it's an obfuscated coding contest, I see no point in writing terse code in a compiled language. I might have written terse C++ code only in my own private projects. Never in code that someone else is going to see.

Otherwise, terse (in the "to-the-point" sense) code is better than verbose code.

Ates Goral
+2  A: 

Remember that code is read more often than it's written, and keep your readers in mind when writing (the reader could even be you). Don't write code like you assume the reader is stupid, nor write code that assumes that the less of it there is, the better it is.

Write 'short and to the point' like Joel Coehoorn suggests.

Staale
+1  A: 

@j_random_hacker (can't add comments to a comment yet)

It happened to me that after 6 months I find it hard to decipher a piece of code I wrote. So indeed, this part matters also

Adrian Pascalin
"Who wrote this unreadable piece of crap"...(checks source control)"Upps, it was me...."
Mario Ortegón
true, true... I've heard of a SVN function called 'blame', didn't use it up to now, which does exactly this thing.
Adrian Pascalin
+2  A: 

When writing the actual source code, be as robust as possible (without sacrificing performance). IE:

var result = GetResultFromFoo(GetOtherResult()).DoSomeCalculation(CallAnotherMethod());

could be fun to write, but good luck debuggin that sucker. There's no benefit, just break it down to this;

var result = GetOthereEsult();
var fooResult = GetResultFromFoo(result);
var anotherMethodResult = CallAnotherMethod();
var finalResult = fooResult.DoSomeCalculation(anotherMethodResult);

Much easier to debug.

The only time I can see a reason to write as terse code as possible, is if the size of the source code matters (like in a JavaScript file that's being served up hundreds of times a second) or when purposely trying to obfuscate code, however there are usualy software out there that does that for you. So bottom line, IMO, no there really isn't ever much of a reason for it.

BFree
+8  A: 

Code should be as terse as necessary and no more. :)

Flippant remarks aside there are several factors affecting just how terse (or otherwise) it should be:

  • Lifespan.

    • Often longer than you think :)
  • Probability of bugs.

    • How likely is dependent on many things but the original coder has a big part to play in this.
  • Computers reading (parsing) it.

    • Not just the compiler, think intellisense and the like.
  • Humans reading it

    • sometimes raw, sometimes with the help of programs like diff tools.
    • sometimes not the same person that wrote it.
  • Required performance characteristics.

All these things combine to produce a set of sometimes competing forces which may want more or less verbosity.

Balancing these is the key to effective development. Which are more important is totally dependent on the problem your software is trying to solve.

First off lets take the easy bits:

Computers.

When they read your code they are quite capable of doing so irrespective of the verbosity. They might be a little slower but this is something that is normally hard to measure (it is unlikely you will go beyond 1 or two orders of magnitude of verbosity than the minimum theoretical possibility). Notable exceptions are where you are (ab)using something like meta programming via a preprocessor to do lots of expansion for you. This can take a long time when compiling. Here you must decide if this trade off is worth it.

Humans.

Generally they will be people with similar context to you and they will be reading the source in a similar situation to when you wrote it. By this it means that if the function was in a file/class/module called Foo then there is no need to go putting Foo in front of things, the Foo aspect of it should be quite clear from context. This makes changing this aspect easier in future.

Programmers familiar with the idioms of the language/style of programming you are using will be quite capable of understanding several constructs which are extremely terse. Loop index variables called 'i' for example are as terse as you can get but are normally not a problem until your loop becomes large.
Here you see an interesting dichotomy. The value of terseness is often proportional to the complexity of the block of code within which it resides. As this block becomes more terse the variables within it benefit more from being shrunk. By writing code in functions/classes with limited responsibility it becomes easier and more helpful to keep things terse as there is less scope for confusion on the part of a human. Paradoxically this can lead to the need for the context to be more explicit, thus longer method and class names.

Lifespan

The lifespan and probability of bugs factor into how often you will have to either read the code or debug through it. Many debuggers support break points at multiple points on a line (correctly spotting where there are two statements) but some do not. Therefore care should be taken on if you intend to break point within it a lot to make sure you can place and control these with minimal effort.

If the code has a low probability of bugs but a long lifespan you have another interesting situation. The probability of the code being comprehensible when you come to need to change it is much lower (you will have a worse memory or may not even be there any more). This code therefore will benefit from being slightly less terse than normal.

Performance

On occasion you might have to sacrifice a compact but clear representation of something to satisfy a performance goal, perhaps you must bit pack for example, never a nice thing to read in code but unavoidable if you have to fit in a certain amount of memory. Occasions like these are hopefully rare.

General Concepts

Some language constructs can encourage terse code (automatic properties, anonymous inner classes, lambdas to name but a few). Where these concepts make sense to use use them judiciously. The idea is that they reduce boiler plate and expose intent.

If you do the same thing repeatedly and have a certain amount of code duplication consider a shared function/class/module but remember that if you must make the shared code less clear (say an additional if statement or unused variables in one of the code paths) then you may not have a net win.

Type inference is powerful but remember that the compiler is sometimes much better at it than a human. If you are saying flibble x = new flibble() then var x = new flibble() is no stretch at all (and gets better as flibble gets bigger). Compare with var flibble = SomeMethodWhoseReturnTypeIsNotClear(). Common sense helps here, if you would never have to use intellisense to work it out you certainly should consider using it.

Some other useful (and terse) rules of thumb:

  • Multiple actions on a single line often confuse humans.
  • Side effects often confuse humans (++x or x++ don't matter at all conceptually unless part of a wider expression for example)
  • Indentation helps most humans to infer structure far more than brackets do
  • Precedence rules are often 'internalized' by humans rather than remembered as a set of rules. This means that needless (to the compiler) bracketing can be harmful for readability where the idiom is common but useful where the usage is not so common.
  • Logical not is often a single character. When using this in an if statement consider whether it can be restructured to not require it. This may not be possible (if the resulting contortions to variable/method name or ordering of code outweigh the removal leave it in)
ShuggyCoUk
+1 for not being terse.
David Berger
vote++ and accepted, great answer :)
Yuval A
@David Good point :)
ShuggyCoUk
It was as long as it needed to be :-P
TofuBeer
A: 

There is one mechanical disadvantage to verbose code and naming in java: Memory footprint under certain JVMs. This may only be a perception issue around process virtual size and memory mapped jar files, but it does exist. Big jar files == big (perceived) memory usage.

You probably have to take things to extremes for this to be measurable in regards to terseness, but it is an interesting "real" effect.

In terms of actual advice, like others have said, write good code first, and worry about optimization later.

TREE
Are there implementations where writing verbose source code will translate into significantly larger .jar files than terse code doing the same thing?
David Thornley
Significantly? probably not, as I tried to imply. Measurably? sure.
TREE
A: 

I'm a huge fan of code that I can read. I've seen some "terse" code that looks like:

int af = yb; 
while(af<ex){af++;af*=4;}

It's easy to see what is being done programatically, but WHAT is actually being done in terms of meaning is obscure. I'd much rather have variable names that I can read later, than trying to save a couple characters of code and going with terse names. Good code does not always mean shortest. Good code is about good algorithms, good documentation, good maintainability. I don't care how long the code is, if it has all those properties, it's good code.

Perchik
A: 

I have found that readability to a human is the most important feature for code in the LONG run.

Readability includes being concise, accurate and clearminded. If you mix things together, you confuse your reader. If your code is clear to read you don't need many comments. If you break complex things together in local, well named variables, you help the reader immensely while implicitly documenting what you do.

Well-written code will survive you. Strive for perfection :)

Thorbjørn Ravn Andersen