The Elements of Style

Brevity is the soul of wit

Kevlin Henney

I have made this letter longer than usual, only because I have not had the time to make it shorter.

Blaise Pascal

Note, that when a sentence is made stronger, it usually becomes shorter. Thus brevity is a by-product of vigour.

William Strunk Jr and E B White

The first thing to note is that brief is not the same as too short. For this the International Obfuscated C Coding Competition is a playful forum for WORN (Write Once Read Never) programs, including outrageous one-liners and LISP interpreters cunningly crammed into less than a page of C code. Brevity is also not about leaving out white space or using one letter variable names, in the same way that brevity in spoken language is not about forgetting to pause, breathe or use words of more than one syllable: Sensitivity to the listener or reader is most important: Say what needs to be said: brevity is not achieved at the expense of clarity, completeness or correctness.

For identifier naming, the one-letter wonders above do not help anybody, but it is easy to get carried away: a C++ string class member function that returns length should be called length rather than get_string_length. Repeating the class name in the method is of no use to anyone. For a side-effect-free query function returning something that is notionally an attribute we shouldn't care whether such a result is derived or in a variable, so just name it after the attribute and drop the get. This is often termed attribute-style naming.

"Replace repetitive expressions by calls to a common function" is an old piece of advice, quoted here from Kernighan and Plauger's The Elements of Programming Style. Hunting out duplicate or nearly duplicate code and putting it into functions is a standard technique for decreasing code complexity. This is like algebraic factorisation but on a larger scale. It allows you to see what is going on and regain control of the code.

A few months ago I was giving someone a hand with debugging their code when I noticed that two constructors had identical bodies but slightly different arguments. It was not immediately obvious that they were identical, just that they were similar: comparing anything over three lines requires more than a quick glance. In another case I found two classes with a similar purpose with many of the same member variables, and identical constructors and destructors. Before remedying this the other programmer's reply was "Oh, I don't like private member functions and I don't really like inheritance". Curing the common code eases much tension within both a program and a project!

Even if the code is not duplicated today, it may be tomorrow. I am thinking in particular of the Nightmare switch Statements from Hell that are so popular in Windows programming. Using Windows does not require you to write the kind of case-and-paste rubbish that litters most, if not all, books on Windows programming — including those regarded as the standard texts. Functions of that size are verbose, uncontrollable and unnecessary.

A couple of years ago I came across somebody who was a past(e) master of the thousand-line function. Some of his functions were so long that the compiler either ran out of space for the symbol table or just flatly refused even considering optimisation. I seem to remember him mumbling something about doing it for efficiency reasons, before side-tracking into a ramble about how inept the customer was for putting real data into his program causing it, and Windows, to fall over in a crumpled heap. Not so much the coal face as the north face of the Eiger blindfold and without safety gear.

Short functions grouped into well-considered modules with precise minimal interfaces are the order of the day. Declaring and defining functions, data and types in C and C++ could not be easier; languages like COBOL seem to stack the odds up against any programmer attempting fine-grain modularity. Class inline functions are a classic case of a notation that can be used to reduce readability in C++. Inline functions come in for much abuse already (I have seen forty-liners declared inline!); placing them in the body of a class makes the class less readable and less controllable. For a few characters more (inline, class name and ::) you get to separate the implementation from the interface, conditionally compile whether they should or should not be inlined, and you have a briefer class declaration.

Much brevity comes from reuse, in particular the standard C library — the forthcoming C++ standard has reused it by inheritance from the C standard, overriding it in a few places. Consider the following:

I won't give a function by function account of all the standard headers, but this example fragment illustrates that <ctype.h> is one that is commonly overlooked: Declaring auto variables as close to their locality of use as possible and initialising on declaration keeps function implementations small and to the point: The simplified version is, needless to say, more direct: Abuse of the conditional expression is easy, but using it in certain places encourages a more functional style, curing the clunkiness of much procedural programming. Notice that the emphasis is different in each example: the former emphasises the branching on FileName; the most prominent feature of the latter statement is that Input is being declared and given an initial value, the rest is, so to speak, just mechanism.

Simplifying expressions and use of control structures again has a lot in common with algebraic simplification:

Life is too short, but the following statement is not: Some attempts at brevity lead to personal dialects rather than common idioms: Macros are often more trouble than they are worth. Attempting to 'simplify' code by using them generally introduces more bugs and sends programmers off searching through headers to find the answers to simple questions. Often these are the kind of macros that appear in 'personal' headers. The names IsNull and StrEq are suggestive, but they guarantee nothing and so other programmers still have to check your headers — there is a subtle distinction between information hiding and information obscuring. Avoid confusion by using standard idioms: The first is a common C and C++ idiom, the second is a common C approach, the third is the equivalent C++ approach, and the last two clarify what was actually meant. One approach that I do not advocate is People come to expect operator! to be used for Boolean expressions and not simply as a low-level mechanism for turning zeros into ones and non-zeros into zeros. Such expressions are confusing because the intent is to indicate something that is rather than something that is not the case.

Put briefly: simplify and clarify, brevity will follow.

© Kevlin Henney
First published in CVu 7(2), January 1995
Converted to HTML, March 2001