I <3 Steve McConnell*
Coding Horror
programming and human factors
by Jeff Atwood

July 08, 2008

Spartan Programming

As I grow older and wisereven older as a programmer, I've found that my personal coding style has trended heavily toward minimalism.

I was pleased, then, to find many of the coding conventions I've settled on over the last 20 years codified in Spartan programming.

300-movie.jpg

No, not that sort of Spartan, although it is historically related. The particular meaning of spartan I'm referring to is this one:

(adj) ascetic, ascetical, austere, spartan (practicing great self-denial) "Be systematically ascetic...do...something for no other reason than that you would rather not do it" - William James; "a desert nomad's austere life"; "a spartan diet"; "a spartan existence"

I've tried to code smaller, even going so far as to write no code at all when I can get away with it. Spartan programming aligns perfectly with these goals. You strive for simultaneous minimization of your code in many dimensions:

  1. Horizontal complexity. The depth of nesting of control structures.
  2. Vertical complexity. The number of lines or length of code.
  3. Token count.
  4. Character count.
  5. Parameters. The number of parameters to a routine or a generic structure.
  6. Variables.
  7. Looping instructions. The number of iterative instructions and their nesting level.
  8. Conditionals. The number of if and multiple branch switch statements.

The discipline of spartan programming means frugal use of variables:

  1. Minimize number of variables. Inline variables which are used only once. Take advantage of foreach loops.
  2. Minimize visibility of variables and other identifiers. Define variables at the smallest possible scope.
  3. Minimize accessibility of variables. Prefer the greater encapsulation of private variables.
  4. Minimize variability of variables. Strive to make variables final in Java and const in C++. Use annotations or restrictions whenever possible.
  5. Minimize lifetime of variables. Prefer ephemeral variables to longer lived ones. Avoid persistent variables such as files.
  6. Minimize names of variables. Short-lived, tightly scoped variables can use concise, terse names.
  7. Minimize use of array variables. Replace them with collections provided by your standard libraries.

It also means frugal use of control structures, with early return whenever possible. This is probably best illustrated with an actual example, starting with raw code and refactoring it using the spartan programming techniques:

I don't agree with all the rules and guidelines presented here, but I was definitely nodding along with the majority of the page. Minimalism isn't always the right choice, but it's rarely the wrong choice. You could certainly do worse than to adopt the discipline of spartan programming on your next programming project.

(hat tip to Yuval Tobias for sending this link my way)

[advertisement] Peer Code Review. No meetings. No busy-work. Customizable workflows and reports. Try Jolt Award-winning Code Collaborator.

Posted by Jeff Atwood    View blog reactions

 

« The Problem With Code Folding iTunes is Anti-Web »

 

Comments

first!

gothael on July 8, 2008 06:21 AM

It's good to know I practice most of these techniques anyway. I remember I read in a programming book somewhere (I think by Chris Pine) that you should strive to program as "lazily" as possible, meaning you should try to do as much stuff by typing as little as possible. Seems pretty similar to Spartan programming to me!

Matt S on July 8, 2008 06:30 AM

It's noise reduction, especially what you are talking about in regards to declaring minimal scope (encapsulation).
If more things can be read-only and less variables are available globally this cuts down the amount of background noise and keeps things clearer, simpler and makes it easier to see what is going on and what code might be causing a bug.

Makes me wonder how people make some of the best sites in the world in PHP as that language doesn't appear to lend itself to this style of coding.

Jax on July 8, 2008 06:31 AM

Good stuff. Definately agree with most of the ideas here... although mindless swapping of ifs and switches can be questionable... and I am loathe to encapsulate variables when leaving them public will suffice (less code, less function calls... the only disadvantages are that you can't "upgrade" the class to do other stuff on get or set in later releases and that you "break" OO... if thats even a bad thing)

Still, the C example is not much different between the two (i.e approximately the same amount of coder effort to produce the code). Other than the switch statement, the compiler is likely to produce very similar results...

The Java example is much more drastic and proves the point very well I think. :)

In a similar vein, one of my favorite time savers/code shorteners is to provide a #define or typedef for unsigned long/unsigned int. typing "unsigned" all those times gives me a headache. C# gets it right with the label of "uint". :)

Jheriko on July 8, 2008 06:33 AM

"Makes me wonder how people make some of the best sites in the world in PHP as that language doesn't appear to lend itself to this style of coding."

Jax: poor workmen blame their tools. the opposite is also true, a master craftsmen will take the worst raw materials and the worst tools, and still will create a masterpiece.

Jheriko on July 8, 2008 06:34 AM

"although mindless swapping of ifs and switches can be questionable"

Likewise with reflexively replacing for loops with foreach loops. I'm not 100% sure about Java, but with C# there can be performance costs associated with such a change.

protected static on July 8, 2008 06:43 AM

"poor workmen blame their tools. the opposite is also true, a master craftsmen will take the worst raw materials and the worst tools, and still will create a masterpiece."

However, most master craftsmen, given the option, would not use inferior tools. Walk into the woodshop of any even remotely accomplished wood worker, and you probably won't find a lot of low quality tools.

Kibbee on July 8, 2008 06:49 AM

I think there are more important things to keep you up at night than the overhead costs of "foreach".

mrcl on July 8, 2008 06:50 AM

@Jax

Makes me wonder how people make some of the best sites in the world in PHP as that language doesn't appear to lend itself to this style of coding.

Care to elaborate on why PHP is not a good candidate for this kind of programming? Spartan style programming seems to be on the programmer shoulders, not on the language. PHP can do 100% of what was shown in both of the examples...for each loops, switch statments, use of local and global keywords to minimize variable scope...

I get the impression you bash PHP because jeff seems to blindly write negative posts about the language.

mmattax on July 8, 2008 06:57 AM

Less code typically means it's faster, more secure, and easier to maintain.

With, of course, the largest exception being the use of most of microsoft's standard controls.

Chris Lively on July 8, 2008 06:57 AM

I agree with the use of concise, terse names. However I don't like shortening everything to single characters as in the example, i.e. Message as m and Subject as s:

Message m = new MimeMessage(s);
m.setSentDate(new Date());
m.setFrom(new InternetAddress(from));

Call me pedantic, but Steve McConnell taught us to only do that in tight loops. Those lucky C# developers can use object initializes:

Message msg = new MimeMessage(s){
SentDate = new Date(),
From = new InternetAddress(from)};

...which also assists in keeping constructor overloads to a minimum.

Casper Bang on July 8, 2008 06:58 AM

You rarely see these kind of guidelines for functional languages since they are inherently enforced by such things as single assignment, no global variables etc.

Adam on July 8, 2008 07:00 AM

As well said by Antoine de Saint-Exupéry

"Perfection is not when there's nothing to add, but when there's nothing to take away."

lars hundertwasser on July 8, 2008 07:03 AM

> You rarely see these kind of guidelines for functional languages

True, then again, you rarely see functional languages solving real world problems. ;)

Casper Bang on July 8, 2008 07:04 AM

I too have found my coding style naturally trending in a spartan direction over the years. I've found this style makes it easier for me to catch bugs (before they get checked in) and makes it easier for me or anyone else to maintain the code down the road.

Dave C. on July 8, 2008 07:07 AM

Serious question: Why are people allergic to whitespace? That Java example has the code compressed into a huge block, line following line without pause, even after the spartanization.

I personally don't like the brace-at-end-of-line style of scope operators since I find it much harder to read with all the lines of a control block crammed together, indenting notwithstanding.

However even sections of code that are logically grouped together could stand from having some nice, free, "paragraph separating" whitespace to improve legibility.

People complain on forums and blogs when someone expresses their ideas as large blocks of text, unrelieved by the occasional empty newline. Why is this so often not the case for code?

It seems to me that if you write code in "paragraphs", you can use these as a good indicator of where you can refactor into a method, as the paragraph gets longer.

Wouldn't that be an even better way to add this spartan feeling to code? If one added whitespace in the Java example, you could see there are at least three "paragraps": one that sets up the message basics, one that adds the attachments, and one that sends the message.

One could make this code even cleaner and more spartan by making"addAttachments()" and "smtpDeliver()" methods.

Dan Fleet on July 8, 2008 07:10 AM

"terser programs are easier to understand" (from the Spartan programming page).

While the goal (readability) is good, I doubt if these rules help reaching that goal. For example, while veryLongVariableNamesThatGoOnAndOn are clearly cluttering,

c.setSN(f.getSN());

is not as easy to understand as

child.setSurname(father.getSurname());

you can might even infer the type of the variables from the latter statement.

I can find similar issues with several of the other guidelines. I think simply stopping to read what you've done after you've completed a unit of code to check if it's readable will be more useful than following these rules.

Jeroen on July 8, 2008 07:11 AM

I have to agree with the previous post. Jeff, you tell us that Code Complete is your favourite book, but this post is an obvious opposite of what is said in Code Complete. It is writeen through all the book that first of all the code should be READABLE, because it's simply easier for yourself in the first place. And short variables don't do any good to achieve this goal. Hell, we have got all this IDEs with code completeion and all, why do we have to use so small names?

There are two ways to explain what the variable does: either leave a comment, or choose a suitable name. Of course it's better to use both, but since the varibale should be given some name anyway, why not choose a good one?

At least one-letter names are very annoying when you have to maintain code written by someone else. I don't read other's C code very often (I code in Java), but when I do, I hate using lots of one-letter variables. Even if all of them are commented (I would have hung myself if they weren't), I still get confused when I try to find out how the code actually works simply because I forget what makes "s" different from "g" and what is stored in "r". The only thing I can do is to read comments over and over again.

Of course, I make use of short variables, but just in the cases when it is obvious what they store, for example, in the loops. That's it.

P.S. By the way, Code Complete advises not use such variables even in the loops. So Jeff... Maybe it's time to look through Code Complete again?

Malcolm on July 8, 2008 07:17 AM

I have also found myself in a loop of becoming more minimal, pretty steadily over the last several years.

I just wrote a similarish but more generalized post on this: http://codetoast.com/blog/im-bored-of-all-this-smorgas

Simple code tends to stay maintained and working a lot longer. Working and simple code is way better than unworking code that in theory could save the world and do my dishes and demonstrate the coolest new pattern of cleverness, umm if only it worked.

knick on July 8, 2008 07:19 AM

Sorry, many people has posted before me, I meant the post by Casper Bang.

Malcolm on July 8, 2008 07:19 AM

Jheriko: "I am loathe to encapsulate variables when leaving them public will suffice (less code, less function calls... the only disadvantages are that you can't "upgrade" the class to do other stuff on get or set in later releases and that you "break" OO... if thats even a bad thing)"

Leaving variables public has a lot more disadvantages than you think, as most good developers figure out quickly. They can easily be altered in places you don't expect because of scoping issues - which "aVar" is visible here? It also means they can accidentally be changed by others working with your code when they didn't intend to do so.

Finally, public or "global" variables are just wasteful. They consume memory when not needed, whereas variables with restricted scope ("local" variables) only take temporary space on the stack during the time they're in scope; once they're no longer in scope, the compiler can reuse that memory space. The same isn't true of global variables; the memory they occupy is used for that purpose even when the variable isn't being used.

Global variables went out of favor a long time ago with people who know what they're doing.

KenW on July 8, 2008 07:25 AM

The interesting thing is that I can't bring myself to maintain continued use of frameworks or open source code that has non-intuitive, up-front syntax. If I have a cake, while I would like to comply with standard baking and slicing conventions, I want to eat() it too.

I agree with the previous posts as well, though not quite to that level of criticism(sorry, guys). When I'm trying to read through aging code (particularly c or c++), I would much rather see a more descriptive coding practice that follows user-friendly ER modeling in variable and function names. It's a grey area, I suppose, but one that defines the difference between a poor programmer and a seasoned professional.

The number one reasons to find the balance between Spartan and Grecian (for lack of a better historical comparison) code is....legacy systems.

Raymond Berg on July 8, 2008 07:30 AM

> Global variables went out of favor a long time ago with people who know what they're doing.

True Ken, but there's still overhead with passing context around this way and things gets much more tricky when we want to pass context back again to the previous stack frame. Some languages use tuple's for this, but neither C# nor Java operates with this concept.

Casper Bang on July 8, 2008 07:34 AM

"first!"
Can we ban people who engage in this sort of Internet garbage spewing?

Spartan code is substantially easier for someone else to come in and understand/debug. The less code that is in your system, the less that can break when push comes to shove. (Less code does not mean shorter variable names or method names. Name length on those identifiers is too specific to reduce to a one-size-fits-all rule.)

I didn't see much of a mention on modules that attain god-like status in systems. They are probably the biggest offenders when it comes to proper coding style and make it much harder to work on because so many details are exposed to you at once.

Matt Green on July 8, 2008 07:36 AM

I agree with most of that I think. I don't like terse variable names they make the code harder to read. message is much better than m, emailMessage is much better than message. I don't mind i,j for tight for loops though but I'd prefer row and col (assuming that was appropriate. The more you can do to make your code read like English the better in my view.
I do agree with all the encapsulation points though and I'm a fan of "as little code as possible", some of my most productive days are when I reduce the code base by 10%.
The only bug free code is no code.

David Hayes on July 8, 2008 07:46 AM

At Malcolm :
"It is writeen through all the book that first of all the code should be READABLE, because it's simply easier for yourself in the first place. And short variables don't do any good to achieve this goal."

short variable name does not mean unreadable code or one char variables.
Looping on row, col is as readable as using tableRowIndex and tableColIndex.

tmp is as readable as tempVar

Of course sometime you will want to be able to know that modelRowIndex is different from viewRowIndex, but if there is no confusion, using row, col, or even i,j is very readable.


bandini on July 8, 2008 07:47 AM

> However I don't like shortening everything to single
> characters as in the example, i.e. Message as m and
> Subject as s

I agree. Bad, bad, bad form.

I would also add the bafflingly controversial rule to "reduce the number of returns to ONE" to the list. I go mental when I see stuff like the "good" example given under "horizontal complexity":

if ...
return
return

Rhywun on July 8, 2008 07:49 AM

>True, then again, you rarely see functional languages solving real world problems. ;)

Not because they can't, but because still relatively few people use these languages. Lack of libraries is no longer a problem. You now have functional idioms for C#, you also have F# for .NET, and Scala which runs in the JVM and is interoperable with anything done in Java.
For anyone who sees the benefit of constructs like 'foreach' and minimization of variable usage, functional programming is clearly a step forward, and it's ready to be taken.

German on July 8, 2008 07:49 AM

I think excessively minimized code often falls for the
six-month rule: You must still be able understand your own code
after having left it alone for half a year

Jens on July 8, 2008 07:56 AM

I'm not a fan of early returns, personally, it's too much of a GOTO solution. I also try to avoid break statements for the same reason.

tk. on July 8, 2008 07:58 AM

The terse rule is a double edged sword, IMO. As someone else mentioned - you need to be able to understand the code later.

If you don't use descriptive variable names, you need to have their meaning clearly defined either by context or by comments.

Lars Fosdal on July 8, 2008 08:01 AM

Of course, if we follow this argument to its logical conclusion, why are we programming in Java in the first place? Stop me if you've heard this one...

http://www.paulgraham.com/power.html
(h t t p colon slash slash www dot paulgraham dot com slash power dot html)

Dan Lewis on July 8, 2008 08:01 AM

Sorry for the funny looking link, I have a hard time remembering what gets past the comment filter because there's no Preview button (and I comment on more than one blog).

Dan Lewis on July 8, 2008 08:03 AM

Go spartans!
I've been a spartan programmer for the last 3 years. Its sometimes painful, and sometimes it means investing more ahead of time, but you definitely thank yourself a few months down the road when you need to update/fix something.

Jay on July 8, 2008 08:17 AM

>Of course, if we follow this argument to its logical conclusion,
>why are we programming in Java in the first place?

Mostly because it pays. Hopefully the industry will get over Java and the like eventually... (we can all contribute to that by learning new stuff)

German on July 8, 2008 08:19 AM

isn't "spartan programming" a fanciful expression to label dry programming?

heri on July 8, 2008 08:22 AM

1. The Java example is buggy. They removed the fds variable, which was "only used once", and forgot the SECOND use. So, the following line, in the final form of the example, won't work:

part.setFileName(fds.getName());

2. Replace arrays with collections? Well... I like lists and all (of which Collections are variants), but an array is MUCH faster. Both for memory management and access. I use them as long as speed is not important, but they are usually my first choice of optimization. And often last.

Daniel on July 8, 2008 08:26 AM

One place to avoid long variable names not only for asthetic reasons is control names in asp.net because they are actually written on the page that needs to be transfered. Now if you happen to use the container controls of the ASP.Net AJAX control toolkit, the name(s) of the container(s) is/are concatenated to every child control.
In addition the viewstate is also blown up (apparently the encoding of the viewstate does not imply compression).

If for example you have a checkboxlist within an asp.net ajax tab panel, you may get something like this on your page for a list with two items (imagine 100 items...):

<tr>
<td><input id="TabContainerLongOuterContainerName_TabPanelReallyLongInnerContainerName_CheckBoxListReallyReallyLongCheckBoxListName_0" type="checkbox" name="TabContainerLongOuterContainerName$TabPanelReallyLongInnerContainerName$CheckBoxListReallyReallyLongCheckBoxListName$0" /><label for="TabContainerLongOuterContainerName_TabPanelReallyLongInnerContainerName_CheckBoxListReallyReallyLongCheckBoxListName_0">0</label></td>
</tr><tr>
<td><input id="TabContainerLongOuterContainerName_TabPanelReallyLongInnerContainerName_CheckBoxListReallyReallyLongCheckBoxListName_1" type="checkbox" name="TabContainerLongOuterContainerName$TabPanelReallyLongInnerContainerName$CheckBoxListReallyReallyLongCheckBoxListName$1" /><label for="TabContainerLongOuterContainerName_TabPanelReallyLongInnerContainerName_CheckBoxListReallyReallyLongCheckBoxListName_1">1</label></td>
</tr>

Manu on July 8, 2008 08:27 AM

I definitely don't agree with some of those ideas.

To me, a variable name can never be too long. In my opinion, a variable name absolutely has to be descriptive, so that other programmers can more easily see what is going on. If a variable must be named horizontalScalingFactorBeforeZoom, then so be it.

The other thing that should be pointed out is that sticking to those maxims will result in slower code (a lot of the time). I especially noticed this one: "Minimizing the use of arrays, and replacing these by collections provided by standard and of-the-shelf libraries." Obviously, that will result in more overhead in many situations.

Still, it's a very interesting concept.

Evan on July 8, 2008 08:29 AM

The ability to view a complex problem as a series of simple problems and to code accordingly is one of the most important abilities when writing clean, maintainable code.

Hutch on July 8, 2008 08:31 AM

how does spartan programming apply to peer programming? if my partner breaks the build, should i put my keyboard through his chest?

Darren Kopp on July 8, 2008 08:31 AM

Great care must be taken in these approaches. Less is not always better. Sometimes it might require more lines of code for that piece to run in it's most efficient mannor...

I suggest you run some performance tests on some of your code that you "minimized" before you call it good.

Aaron on July 8, 2008 08:36 AM

I second Jens and to some extent Evans: Shortening your code is a very good way to make it unreadable.

'Less lines' doesn't necessarily means 'faster to read'. Look at abs() in 'Horizontal Complexity'. I strongly disagree to remove the else (although I think early returns are not evil): shorter program but slower to understand.

Serge Wautier on July 8, 2008 08:39 AM

Less is more.

Charles on July 8, 2008 08:40 AM

A favorite quote of mine by Edsger Dijkstra: "If we wish to count lines of code, we should not regard them as lines produced but as lines spent."

Chad on July 8, 2008 08:43 AM

@KenW:
You seem to be using "public" and "global" interchangably, or at least implying that the concepts are closely related, which is very confusing. In every language with which I am familiar, "public" is an object oriented term describing which code can access a class member: specifically that any code with access to the class also has access to the member. Jheriko suggested that sometimes it is better leave data members public (and I'm not going to get involved in that debate for now) and yet you appear to be responding with reasons why global variables are bad. I don't understand the connection.

Weeble on July 8, 2008 08:44 AM

KenW: Sorry I am mainly a C++ programmer, so most of what you said does not fit with what I know and do. I assume you are familiar with something else... for instance, there are no scoping issues on class member variables. you need to use a "." or "->" to access them...

Your stack comment is also a bit wrong, seeing as these variables will more than likely be allocated off of the heap anyway... except for local temporaries which will go on the stack, just as they should.

I agree about "global" variables though for the most part. These are pure evil, except on very small apps, where worrying about encapsulation will make your project take 2 times longer to complete or worse. These are very much the exception though...

I missed the point about foreach too... whilst there maybe more horrible inefficiencies to worry about, its best to do it right in the first instance. Personally I avoid foreach like the plague, because it hides code. Though I am very much aware that I take that philosophy too far, to the point of avoiding things like the .NET framework, VB or Java whenever possible because they hide about 99.99% of what your program does... at least with C/C++ I can look at the code and get a good estimation of what it will compile into. :)

Bleeding edge optimisation is normally too much, but don't forget that even basic things like "memcpy" can be improved upon trivially with a smattering of asm. Its naive to think that who ever implemented the library/language actually did the best job possible for your specific situation... its usually a case of picking the "best fit" method for the most cases...

Jheriko on July 8, 2008 09:01 AM

Good advice Jeff. The concept of "Spartan Programming" merges a lot of more or less well known rules. I only disagree with the C and Java examples as I don´t think they show a good coding style. The C code hasn´t been modified very much at all. The Java code made some steps in the right direction, but I think, it could have been split in a few simple methods with proper names. Also some of the variables could have been named better:

* Session ses = ... --> Session session = ...
* for (File f: attachements) --> for (File attachement: attachements)
* InternetAddress[] arr = ... --> InternetAddress[] iAddr = ...

Also a little more whitespace would make the whole thing a little bit more readable. I think one should strive for a spartan programming style but always have an eye for code readability.

Florian Potschka on July 8, 2008 09:11 AM

Except in that Spartanizing of the Java function you linked to, they have an error:

This loop can be simplified further, by removing variable fds, which is used only once, and by using a terse name instead of currPart
for (File f: attachements) {
MimeBodyPart part = new MimeBodyPart();
part.setDataHandler(new DataHandler(new FileDataSource(f)));
*** part.setFileName(fds.getName());***
parts.add(part);
}

Whoops - guess that pesky variable wasn't used only once ...

Kyle Hale on July 8, 2008 09:13 AM

Terseness is an advantage, but the extreme case is going to slow down development:

The inline function calls that remove local variables also remove the ability to breakpoint and inspect intermediate results.

Isn't it a maxim that we should step through ever line of code at least once to make sure things are occurring as expected?

On top of that, both examples look contrived. Each (especially the C code) presumes to represent actual, complex source, but neither has a single assert.

I realize that Java will throw, but how was this 'code' written and debugged?

Enguerrand on July 8, 2008 09:15 AM

@Jheriko: "I avoid foreach like the plague, because it hides code. Though I am very much aware that I take that philosophy too far, to the point of avoiding things like the .NET framework"

Weird philosophy!

Your basically saying why use existing, well-tested language constructs and libraries that "hide your code" when you can write your poor equivalents with new and interesting bugs.

Graham Stewart on July 8, 2008 09:18 AM

Like Daniel above, I was disappointed that the example java code Jeff links to is buggy even to my non java eyes. Makes it hard to take you seriously as a proponent of a system when you leave buggy code in public or if you tout an example without critically examining it first.

If you don't critically examine the ideas before you present them, you do a disservice to your readers. Given the cut and past nature of the article, I find it hard to believe that you critically examined much of it. Synthesis is more important than being an echo chamber.

Matt Katz on July 8, 2008 09:21 AM

Early returns make code much easier to use and much easier to maintain.

For example, if I have 6 reasons which make it so a block of code should not execute, I simply test the 6 reasons and return early on any if they are true (or all of them together if you want to test all of them at once).

However, without early returns, my block of code is nested under 6 (sometimes more) loops, where I have to trace back all my start and end blocks to figure out which if statement I am under. My actual code block will be at the right side of the screen, if I can ever find it...

Jeff Davis on July 8, 2008 09:21 AM

The C example could be made better by changing the #define's to const int declarations (basically the equivalent of java's final). That way the compiler will be able to identify type errors, and any static code checking software you're using should work better.

You can also extend this further by modifying your function declarations to use const parameters for variables that shouldn't be modified. For some example's of this, have a look at a C99 header file like string.h

Dana on July 8, 2008 09:27 AM

"A designer knows he has achieved perfection not when there is nothing left to add, but when there is nothing left to take away."
-Antoine de Saint-Exupery

PaulG. on July 8, 2008 09:31 AM

I like early returns. If an early return causes you to accidentally miss "clean up" code, then you're doing it wrong: you should be using RAII. (In C++, use destructors for cleanup. In C# use "using" blocks and IDisposables.) If an early return makes it hard to see all the code paths, your function is probably too long.

Weeble on July 8, 2008 09:33 AM

Inlining/folding variables that are only used once in C++ can be very frustrating. Like previous posters have mentioned, it makes it harder to parse visually. Removing the clear label that describes what the subexpression is doing can obfuscate and complicate otherwise straightforward code. You're against horizontal complexity at the macro-level, this seems like the equivalent at the micro-level!

Having small temporary const variables hold subexpression results makes stepping through the code in the debugger orders of magnitude simpler (again, in C++) as well.

I agree with your sentiment, but I think you've gone a little too far in your details! But hey, to each his own.

Charles on July 8, 2008 09:36 AM

I'm no fan of early returns and I think var names should be descriptive. But bandini hit my "Go Batshit" button with the use of 'temp' or 'tmp'. As has been pointed out, now that Globals are seldom used, all vars are temp in manner of speaking. I reserve the 'tmp' prefix for var names to situations where the var is to be removed at some future point. It bothers me when I see 5 year old code with 'tmp's still present. Good thing no one has suggested tight-coupling or I'd have broken my monitor.

twmcneil on July 8, 2008 09:37 AM

This is almost horribly bad. It is completely counter-intuitive to making readable maintainable code. While some of the ideals and principles are correct, the application of them is just plain wrong. Variable terseness is a throw back from the days of 1 character variables. It should never ever be a consideration, its time to re-read Code Complete. It is much much much better to have a variable named "messageToSend" then to have a variable named "message" or GASP "m" and have a comment above stating that this variable is to hold message that will be sent, or worse yet, not have the comment or well named variable and let the reader try and figure it out.

Where is the whitespace? White space is good, its a breaking of logical ideas in the code, makes it more readable.

How much more maintainable is code like this:

if(ShouldSendMessage())
{
... do some stuff
}

private boolean ShouldSendMessage()
{
return m.body != null && m.subject != null
}

vs.

if(m.body != null && m.subject != null)
{
... do some stuff
}

Spartan coding would frown on the first example and refactor it to the send to save lines of code.

This kind of thinking is totally backwards from the principles which are expounded upon in "Code Complete". Simplicity is good, but a good amount of "Spartan" programming is calling effeciency and cleverness simplicity. Saving the { } on a statment may save space and look cleaner, but its error prone for maintenence. Newing up a variable thats only used once nesting inside of another constructor, may save a line, and look prettier, but its harder to maintain and understand. Sure a guru, who understands all the constructs of the language and what you are doing might be able to figure it out just as easy as having it on a seperate line, but I stress this point. The average novice that picks up the code to maintain it will have a much easier time maintaining a block of code that is 200 lines long and has explicitly named variables and none of the tersity tricks, then he would trying to maintain a "clever" 50 line function. It has been said write your code like the person maintaining it is a crazed lunatic who knows where you live, but I think its even better to say "write your code, like the person maintaining it is an idiot, who has your phone number and will call you up for unbillable hours."

John on July 8, 2008 09:39 AM

"Spartans! Prepare for glory!"

Minimalism is best especially if not for yourself, but for others in collaboration with you. Why overdue it with complexity when the old adage holds true, *keep it simple, stupid*.... ? Actually I recall you saying this in past posts.

Great article Jeff.

Patrick on July 8, 2008 09:40 AM

Writing Spartan code takes a lot of work.

Long ago a mentor told me: "Don't be afraid to remove code, I spend half of my time deleting code I just wrote".

I have always found this quote inspiring and I think it is a thing that differs in "young" programmers as if they fear changing/editing/removing code that was just written. As if it demonstrates a flaw, that they did something wrong or inefficient. But, the wrong thing is letting that code live there.

My next objective is to be able to write that same quality level code without spending so much time removing code... like in a perfect/spartan first draft.

philibert on July 8, 2008 09:43 AM

@mrcl:

"I think there are more important things to keep you up at night than the overhead costs of "foreach"."

As with so many things in life, it's all in the details: what are you iterating over, what are you accessing, are you only reading the items or are you modifying them, and so on...

protected static on July 8, 2008 09:47 AM

I hardly ever use "early returns" here.
The company standard is to generally avoid them.
The only use I have for them is for establishing pre-conditions at the start of functions.

e.g.

int myfunc(int p)
{
// Precondition: p must be in the range 0 to 5
if ( (p < 0) || (p > 5) )
return -1;
...
}

Graham Stewart on July 8, 2008 09:52 AM

My biggest problem when writing as little code as possible has to do with unit tests. We have a program where we code "calculation rules" that users give us. We write a unit test for each of these rules to make it harder to mess things up, but that can take a lot of time. But, for the actual code we can usually boil a collection of rules down to a few lines of code. I don't know how to get around that, except to stop coding the unit tests. Right now the benefit of the unit tests outweighs the tedium of creating them.

Gary on July 8, 2008 09:53 AM

As long you are talking tuples, minimalist code, all wrapped up in fascicles of obsolete material, I am with you. Now off to more organ playing and long-hand writing.

Go fictitious machines! Go assembler-like OO languages.

Buy my books. "Learn the computers " (Video Professor).

DonaldKnuth on July 8, 2008 09:53 AM

I'm a big fan of early returns. They avoid that you need to indent 20 times within a function, which makes it very hard to follow the function. Unfortunately in plain-C, early return means you need to make heavy use of something frowned upon: GOTO

E.g. a function might look like this (_____ used to show idention):

// Init variables
// If all inited successfully
____// Do something with them ... lots of code here
// Clean up all variables
// Return result

Okay, now this is just one level of indention, but "Do something" might again init something and again and again, so the nesting gets deeper and deeper. Instead I want to leave the function as early as possible, but if init failed, I can't just return. I might have inited 4 vars, some might have failed (that's why I want an early return), but maybe some did not. I need to clean these up (e.g. malloc/free) otherwise I'll have memory holes! The only way to do this in a clean fashion is like this

// Init variables
// If NOT all inited goto finally
// Do something with them ... lots of code here
finally:
// Clean up all variables
// Return result

See, I removed the indention and I can do the same way for every other indention level I had used otherwise; but I can't just return in case something went wrong, the clean-up code needs to run. GOTO is the best way to do this. I use GOTO to emulate the missing TRY/CATCH/FINALLY structure in C. There is no TRY, but my labels are usually named "catch" and "finally". Finally is something that always needs to run before the function returns, no matter what happened in the function. "catch" if present, only needs to run in case of an error and not at all if everything went right.

I also can't follow the rule "GOTO is okay, but only if it never jumps backwards". I know why this rule exists. People used GOTO instead of for/while/do-loops, which makes code hard to read. But if GOTO can only jump forward and I need some catch code, the code will look like this:

// Init variables
// If NOT all inited goto catch
// Do something with them ... lots of code here
goto finally;
catch:
// Catch code
finally:
// Clean up all variables
// Return result

See, I only jump forward, but that means if everything goes right (as designed), there is a jump, too, one that jumps over the catch code. BAD! I design functions in such a way, that GOTO-jumps only take place if something ever goes wrong, but never if nothing goes wrong. If nothing goes wrong, the function runs from top to bottom, enters at top, returns at bottom; clean code flow is very important to me! Hence my code looks like this:

// Init variables
// If NOT all inited goto catch
// Do something with them ... lots of code here
finally:
// Clean up all variables
// Return result
catch:
// Catch code
goto finally;

Disadvantage: The last code of the function is not the return code, it is the catch code. Return is before the catch code. The jump from catch to finally is backwards.

Advantage: If no catch happens and also no direct jump to finally, the code runs from top to bottom, will always enter the finally block, but never the catch block, because it returns early.

Mecki on July 8, 2008 09:56 AM

Sorry Jeff, but I just had to bring up your post 834 "Thirteen Blog Clichés" here:
http://www.codinghorror.com/blog/archives/000834.html

"As the old adage goes, a picture is worth a thousand words. But you should no more insert a random image into your writing than you would insert a thousand random words into your writing. I don't care how beautiful your photographs are, it's a terrible, irresponsible practice that distracts and harms readability.

"And those of you sitting there smugly, with your stock photo library and your peripherally, tangentially, almost-but-not-quite related images that you use to break up your text, don't think I'm not talking about you, either. Because I am. Think about that the next time you read an article about a "web 2.0 bubble" accompanied by-- you guessed it-- a stock photo of a child blowing a bubble.


So OT, but I notice from time to time that you like to use your "peripherally, tangentially, almost-but-not-quite related" images, and I can't help but think about that older post on each occasion =)

Anyway, another good post today, but it's just easy being a critic!

Wade on July 8, 2008 10:26 AM

I'm going to agree with lots of other posters and say that while spartan programming in general is good, I take exception to terse variable naming.

Using the article Jeff linked to as an example - I would *much* rather have to maintain the first version of the drawing function than the second. Suppose there were a bug where the quadratic formula was written incorrectly, with two of the terms swapped. How would I find the problem if I weren't already familiar with the canonical form of the quadratic formula? There's no indication from the given code which term is x squared and which is x, for example. Is the bug that the terms are swapped inside the function, or the order of parameters is swapped in the calling function? Who knows!

Verbose variable names can be taken to an unhealthy extreme, I suppose, but the vast majority of the time I have problems with code that's too terse rather than too verbose.

Eric Lee on July 8, 2008 10:26 AM

Commonsense programming? ;-)

This entry reminds me of a couple of books that came out of a column in an ACM magazine, called "Programming Pearls" by Jon Bentle. And books like "Effective C++", by Scott Meyers.

If one practices "minimalism", then they won't need #region ;-)

dj on July 8, 2008 10:28 AM

- Try to limit method/functions to 7 or 8 lines.
- Try to limit classes to 200-300 lines
- Try to limit arguments to methods to 2 or 3
- Use spring or something simialr for initialzation

Good things happen:
- Early returns aren't a problem because your methods are so small and simple anyway
- you have more flexibility of the level of unit tests as you have the option of testing more methods or just the higher level public ones.
- Number of variables drops
- you need less comments as your method names should describe what the small amount of code in it does.
- You lean towards creating new classes to encapsulate data in order to limit arguments.


The real key here though is having an IDE that makes it painless to refactor. However well you plan to write good/well-factored/spartan code at first, when being maintained it will be chopped and changed and new conditions, variables and complexity will be created. If there's any barrier to re-factoring it doesn't happen regularly enough and the best-laid plans... well you know the rest

Alb on July 8, 2008 10:37 AM

It would be wonderful if there were more spartan products - a word processor that didn't drive like a stretch-Greyhound-bus, for example. Golly, in every field demanding creativity, it's amazing how much can be done with spartan means. Michael Connelly, whose "The Lincoln Lawyer" is one of the greatest mystery novels ever written, uses a simple, utilitarian prose style, honed during his years as an LA times crime reporter, to accomplish wonderful things. So did P.G. Wodehouse, the British humorist whom Isaac Asimov and a horde of other respected writers considered the greatest English-language stylist of the 20th century. WordStar was a marvel of utilitarian, Spartan style. So was WordPerfect, though it was the fork where word processing began to forget all about people who write (and not merely paddle words about).

runbei on July 8, 2008 11:01 AM

@ mmattax

It's true that my experience of PHP is mostly hacking around with open source projects for other people, so I don't wish to sound authoritative so perhaps you can prove me wrong and I can learn.

I wasn't talking about Spartan programming per se, more noise reduction. During my PHP hacking it seemed to me that a lot of things were (scarily) globally gettable and settable. Is this common in PHP? Perhaps it was just the case that the projects i've hacked with were badly designed but global variables are the anti-christ of noise reduction and simplification.

Jax on July 8, 2008 11:29 AM

@john,

I hope that your ordinary code doesn't look like that and that you are exaggerating, because If I ever have to work with someone who splits out single statements into their own methods for no apparent reason I will feed him his own balls.

Not only does this increase the code size, executable size, and execution overhead, it also a pain to reverse engineer. I hate having to skip around code to trace back every statement in a method and its especially annoying when it's stupid one-liners like these. Naming the function "SouldSendMessage" may help in interpreting the function's purpose, but it's not as informative as looking at the actual code. Especially in a situation where the code is only a single line. If you can't reverse engineer a single line of syntax then you don't really have any business programming, novice or otherwise.

This is especially relevant given that the name "ShouldSendMessage" doesn't actually tell us anything about the test you gave. A better name would be "MessageNotBlank." I should be able to tell from the context of the if statement that the test is whether I should send the message or not, The name of the function should tell me what's being tested. This is especially true if you plan for reuse, which is the only reason I would ever refactor something to this extreme.

astine on July 8, 2008 11:48 AM

I wouldn't get too excited about some wiki posted in the Systems and Software Development Laboratory.

That page could have easily been posted by some student (or even a staff member) with little real world software engineering experience.
While I have great respect for academia, some of the suggestion in that page seems to be either naive, or plainly contradict industry practices. It's like if I would put up a page offering stylistic improvements for writing mathematical proofs. I have limited experience in writing them, and I am not qualified to make suggestions.

The C example is particularly bad. The original code presented (seems to be from some simulator) is very badly written. Almost anything done to that code will improve it, probably.
Converting #defines to enums and chained if/else ladders to switch/case is HARDLY news. Combining two code paths into one, is also nothing earth shattering.

Many of the ideas expressed in the wiki are worthy, but again, they are not new ideas. Some of the ideas expressed are downright dangerous in the hands of the inexperienced.

M on July 8, 2008 12:03 PM

2bandini

Well, I didn't mean to take my words literally. There's nothing wrong when you are making proper use of short varibales. Certainly I use them when I need to and where it is obvious what they are for, e.g. in loops as I've already said.

What you should avoid is OVERuse. Or in different words, making most (or even nearly all) variables one-letter. I think you see what I mean.

Malcolm on July 8, 2008 12:13 PM

I simply had to comment on your post:

http://compaspascal.blogspot.com/2008/07/code-style-of-old-age-programmers.html

Lars D on July 8, 2008 12:13 PM

I think you're right on about most things, except terse variable names. For counters, sure, but for most other things, readability is key.

The problem with variable terseness is that it optimizes for *writing* code, which is optimizing the fast case. Variable names should be explanatory to optimize for the real bottleneck, *reading* (comprehending) code, which is the slow operation.

Eric Beland on July 8, 2008 12:30 PM

Let me pipe in on the subject of public variables.

First, if your language doesn't allow you to do:

object.var = expression;

where "var=" is a method, then maybe you should truly stay away from them, because your language sucks. :-) Well, because your language does not provide the proper support to leverage usage of the assignment operator. The resulting impossibility of changing the implementation of a getter/setter from a simple variable to something more complex is a deficiency in the language.

Anyway, EXPLICIT getters and setters are noise, not signal. If getters and setters weren't noise, then variable assignment would work like this:

x.setvalue(expression);
x.getvalue();

It doesn't, for good reason. It obscures. It makes the most simple expressions difficult to read.

For a good example of doing this right, see Scala. In scala, you define your class getters and setters methods, which are then used by the compiler to interpret expressions and assignments properly.

"x" stands for "value of x". "x = expression" is an assignment (:= or variants, if you prefer). One should try to avoid using two different solutions to the same problem at the same time.

Daniel on July 8, 2008 12:33 PM

> Jeff, you tell us that Code Complete is your favorite book, but this post is an obvious opposite of what is said in Code Complete.

I agree. Single letter variable names is an example of minimalism being the wrong choice, but it seems to be an important principle of Spartan Programming. It would be nice to see more information when you say you "don't agree with all the rules and guidelines presented here", especially since some of the Spartan principals directly contradict what you seem to say in your earlier writing when you praise the concepts in Code Complete.

Andrew on July 8, 2008 12:51 PM

Character count should be a concern, but not at the expense of readability. Ever.

Kris on July 8, 2008 01:03 PM

I guess this is a little late in the discussion but I recently read (yesterday?) a post that raised some really good points against private variables. Mostly about how it's rude to other programmers and isn't explicit about why they're private.

http://debuggable.com/posts/programming-psychology-ii-private-methods:481ed862-b0d8-4a0e-9247-165c4834cda3

He (Felix Geisendörfer who I like a lot) points out...

"If somebody does not understand why he is not supposed to modify the balance property - he will find ways around it. And it won't be pretty, trust me. He'll directly write his values to the database and reload the object. He'll simply change your source code without warning. He'll extend the class and overwrite the set method.

Programmers will do just about anything to restore power you are trying to take away from them.

Now you might think: "But it really makes sense to use a private property here, nobody would ever want to work around this?". Well maybe. And thats a big maybe. Predicting what other programmers will want to do with your code is like playing number guessing with uuids."

And follows up with an example that uses a validate function in the save function of the model. He claims it makes it a lot more flexible and provides yet another useful function instead of wasting time with setters and getters that may not have a consitant api between classes.

Francis on July 8, 2008 01:09 PM

Well, not I have to disagree. :-)

If the programmer will insist on screwing up, there's no help for it.

The point of using getters and setters is preventing internal changes in the implementation from having an impact on the client source code.

For instance, suppose you have an object car (which implements the Vehicle interface :), and one of the properties of the car is the acceleration. You expose this directly, and now you have everyone doing things like:

car.acceleration += 10;
print car.acceleration;

And then, one fine day, the TerrestrialVehicle class change it's implementation so that now it stores mass and force, and always calculate acceleration from and to that. Suddenly, that code up there is invalid!

Unless, of course, the language has implicit getters and setters, so that you can change the way acceleration has been implemented without the client code ever realizing it.

Daniel on July 8, 2008 01:23 PM

Nice post

John Pirie on July 8, 2008 01:42 PM

@astine

First of all: as for feeding the balls...

http://bodyspace.bodybuilding.com/ssmoimo/

Ok, now thats out of the way. Yes, that is exactly what I would do. Now of course that program doesn't make sense, but it is much better to take a complicated boolean statement and store it in a variable or a function call. (Depending on which would provide more clarity.) Yes a reasonable programmer can figure it out, but when I am looking at the logic of the method, I don't care how it determines if a message is valid, but only that it is. If I want to look at the logic of is a message, valid I'll look at that method or variable.

Also, take a look at page 434 of Code Complete 2nd edition to see that McConnell advocates that same exact technique. Granted his example is more complicated logic, but that is likely to be the case in a real example.

Also you don't have enough information to know which name is better, neither do I. Doesn't sound like your using in IDE either.

John on July 8, 2008 01:48 PM

It's definitely an art to write more expressive code with less (typing, structures,control loops,etc), but that doesn't mean abbreviating unnecessarily nor prematurely. The only goal is writing short, concise code that does no more than it should. I also don't think the notion of 'spartan' programming (i.e. not somebody's concrete definition) goes against Code Complete either. Readable and maintainable code is paramount.

But then I feel the definition Jeff quoted isn't particularly helpful. Instead: http://www.thefreedictionary.com/Spartan has a bit better definition.
spartan:
2.a Rigorously self-disciplined or self-restrained.
2.b Simple, frugal, or austere

spartan (adj)
2. (of a way of life) strict or simple and with no luxuries

The related word of non-indulgent is also pretty apt.

Think of your house. If you led a spartan existence, you would have 2 pots, 1 plate, 1 bowl and 1 set of cutlery. You don't have more because you don't need more.

Your best idea is to:
- refactor continually
- don't goldplate code
- only add as much as you need, and no more
- use unit tests to provide feedback

Developers love features, but more code = more bugs. Read books on refactoring - it's probably the best thing you can do to make yourself a better nuts & bolts programmer.

It's small-a agile .. Red-Green-Refactor.

RedGreen on July 8, 2008 02:12 PM

@Mecki: "I'm a big fan of early returns. They avoid that you need to indent 20 times within a function"

I hear this a lot, generally because people try to replace code like this:

if (func1() == false)
____return false;
if (func2() == false)
____return false;;
if (func3() == false)
____return false;;

dostuff();
return true;

...with arrow-code that looks something like...

result = false;
if (func1() == true)
____if (func2() == true)
________if (func3() == true)
________{
____________dostuff()
____________result = true;
________}
return result;

..wheras they could just do something like this...

bool statusOk = func1();
statusOK = statusOk && func2();
statusOK = statusOk && func3();

if ( statusOk )
____dostuff();

return statusOk;

Graham Stewart on July 8, 2008 02:14 PM

Keeping unnecessary things to a minimum is good and all but it can sometimes come at a price.
It can be expensive to make make code leaner and smaller. It can also seriously affect readability. Code should (and can) always be self documentary.

Keep it simple, get the job done. :)

Swedish Code-monkey on July 8, 2008 02:17 PM

How many Jr Developers have been dropped off the mountain?

Come home with your keyboard or on it.

brian on July 8, 2008 02:50 PM

After I read through some of the Spartan rules, I wondered, why? What is the benefit? They say, "short programs tend to be more correct". Are they? That's it.

Horizontal complexity: I prefer to always include the braces in and if-then-else even if there is one statement. I'm thinking of maintainability and the next person that has to review and add code.

Token count, character count: I feel like we are writing assembly code on an 8088 processor :-), and we're counting every byte. Those days are gone, aren't they? I'm confused. Is this for performance (i.e., big O notation)? Or is this because the author doesn't want to type. Most good editors have code completion. Is "a" really a better choice for a variable name than "coefficient_X_squared"? Well, at least it isn't polish notation ;-)

A good coding standard and consistency can go a long way in the current state of programming. No need to make things more complex, or create rules because you can.

Linux Kernel Coding Standard
http://lxr.linux.no/linux/Documentation/CodingStyle

dj on July 8, 2008 03:21 PM

@john

"http://bodyspace.bodybuilding.com/ssmoimo/";

LOL, flexing your muscles over the Internet are you? A lot of good it will do you. You've just given me the upper hand, and that's all I'll say about that.

Also, don't quote me this or that professor, I've never read Code Complete, never intend to, and don't acknowledge it as an authority.

I do know enough about that method to tell what it should be called; a method should always be named after it's function. Also, I've used many IDE's from VS to Eclipse/Rational to Emacs. You should never be too reliant on such tools. If you can't parse the code in plaintext, then there is something wrong with the code (or you,) not your tool.

astine on July 8, 2008 04:56 PM

> ..wheras they could just do something like this...

> bool statusOk = func1();
> statusOK = statusOk && func2();
> statusOK = statusOk && func3();

> if ( statusOk )
> ____dostuff();

> return statusOk;

That's terrible, terrible, terrible code. The entire logic is removed and abstracted away in favor of some bit juggling that nobody is ever going to understand again six months from now. And for what ? The original code was perfectly fine, readable, concise, effective.

J. Stoever on July 8, 2008 04:56 PM

Wow, Jeff, you basically copied that wiki page word for word. Even if you did cite it, this is basically link-jacking and unfair usage. Totally uncool.

James A. on July 8, 2008 05:25 PM

Plagiarism. That's the word I was looking for. Taking credit for the work of another.

James A. on July 8, 2008 05:26 PM

For compiled languages, the length of variable names does not matter. All names are tokenized anyway and you will gain absolutely nothing by using one-letter variables.

Minimalist programming has more to do with avoiding code-bloat than anything else - something Microsoft is heavily opposed to because, for some reason, Features Equal More Bloat.

BugFree on July 8, 2008 05:26 PM

Like several commenters before me, the first thing I noticed in the java example was that they attempted to remove the variable "fds" by inlining the constructor, but then left a reference to "fds" in the following line. A small compile-time bug like that doesn't even remotely nullify the overall argument, but it does bring to mind an existing counter-argument, the "if it ain't broke, don't fix it" methodology that refactoring working code can at best, leave it still working, but at worst, introduce bugs.

Also, the manager of the wiki made a serious webmaster blunder- There's no contact information that I could find anywhere in the wiki. If there were I'd have contacted him/her to point out the "fds" variable bug, but as it stands we have to mention it in the comments of a page LINKING to it and hope that he finds this post via pingback or a google search for links to the wiki.

Not sure I agree with collections instead of arrays- Arrays are faster, and leaner on memory- I would say to "use whatever data structure is given to you, unless converting it yields noticeable speedup." Leave an array as an array, a vector as a vector, etc. Even if your first inclination is to convert it to something you're used to, try and figure out why the collection was given to you in that form in the first place. If you're creating the aggregate yourself, I'd go with arrays unless there's a significant algorithmic advantage to using something else.

Alex on July 8, 2008 05:32 PM

I couldn't resist posting something that I went Spartan on:

http://seanja.com/blog/2008/07/08/spartan-coding/

I did not however sacrifice 'readability' by changing the one vaiable that there is to one letter. I hate that.

I also reduced what the function did to make it simpler... I could not see a point to having the same function update and delete. They are not the same thing! GAH!

SeanJA on July 8, 2008 05:50 PM

This particular process of "Simplifying" code is, in my opinion, almost completely offtrack. You don't make code "simpler" by reducing character count anymore than you make a Toyota Prius by putting a Ford Truck in a car crusher and reducing it to the appropriate dimensions. One would hope that obfuscated C contests would have made that clear by now. Code is simple when it does exactly what it looks like it does, and that doesn't come about just by reducing things to some arbitrary minimum sized source file.

Simple code has easy to understand control paths, and well-named symbols (both concise and accurate). Simple code is exactly as complex as it needs to be, and no more. The Spartan philosophy is a sure way to overdo it.

Also @Mecki

There is a procedural form of RAII for C that deals with this. Construct a chain of initializer funtions, that call the next initializer function in the chain if their initialization is successful. Otherwise they return early. The last in the chain is the function for real work. This is best used when things are particularly complex in the final function. A real example would return a value or modify some state, but you get the idea.

void func()
{
int *foo = init_foo();
if(!foo)
{
return;
}
func_foo(foo);
cleanup_foo(foo);
}

void func_foo(int* foo)
{
float *bar = init_bar();
if(!bar)
{
return;
}
func_foo_bar(foo, bar);
cleanup_bar(bar);
}

void func_foo_bar(int* foo, float* bar)
{
//do something
return; //anytime you like, returning from this
//will trigger all cleanup.
//do more things
}

Clark on July 8, 2008 06:30 PM

"Likewise with reflexively replacing for loops with foreach loops. I'm not 100% sure about Java, but with C# there can be performance costs associated with such a change."

Of course in Python the for loop IS a foreach loop and nobody cares about performance since it's already interpreted.

Michael on July 8, 2008 06:56 PM

Lots of comments have been posted already, but I feel compelled to chime in with my disagreement, primarily with that particular wiki page's definition of "spartan programming". Like many commenters, I too believe in creating the minimal solution to every problem. Also like many of the commenters, I might even agree with a smattering of the recommendations aimed at doing so, but I absolutely disagree with the wiki author's priorities in terms of what to minimize and how to do so. By way of a few examples:

The wiki's "micro abstractions" aren't abstractions of any kind. They are primarily syntactical options, many of which fall into the "clever" category, some of which are "clever" enough to have been banned in more than one coding standard I have found myself working with over the years.

The terseness of identifiers may minimize characters typed by the code's initial author, but also minimize readability and maintainability for those faced with the code in the future. The wiki strikes me as written by someone who has never had to maintain code in even the medium term, let alone the long term.

The reduction of whitespace and braces does, well, minimize whitespace, but does so at the cost of increasing visual density which for the majority of developers results in decreased readability and in turn maintainability.

The wiki's deadly fear of line count drives an unwillingness to do things like perform Extract Method and Introduce Explaining Variable. These simple refactorings can, like any other, be overdone but in general are a great way to increase readability and maintainability.

I could provide more examples, but I think the case has been made well enough above and by other commenters.

I've worked with a few developers who absolutely loved producing the kind of code encouraged by the linked wiki, but those developers also had a tendency for producing out-of-spec implementations that were high in defects and low in maintainbility. I know, I know, things like visual density of code (which is in many ways the primary symptom of applying the wiki's problematic recommendations) should in theory run orthogonal to defect rate and maintainability, but in practice the correlations are too great to ignore.

In my experience:

Dense, terse code = more defects, each with greater time-to-fix.

Minimal, while still visually "open" and explanatory, code = less defects, each with lower time-to-fix.

As for net new code, it is worth remembering that new code becomes maintained code character by character, and does so just as soon as you lifted the key.

Jeremy Gray on July 8, 2008 07:02 PM

@mmattax:

PHP isn't condusive to this kind of thing because PHP doesn't have a local variable scope.

The 4 scopes in PHP are
1. Superglobal scope (always visible)
1. Global scope (variables you need the global keyword to see, or can be accessed through the superglobal $GLOBALS array (well... hash))
2. Object global scope - your standard public, private, etc... variables
3. Function global scope - Variables occurring anywhere within a function can be seen anywhere else in that function.

What does lack of a local scope mean? Here's an example

function AFunction() {
for (i = 0; i < 10; ++i) {
echo i, "\n";
}
echo i; // Prints 10
}

The same code in a strongly typed language (C# in this example):

public void AFunction() {
int i;
// Some other code

for (i = 0; i < 10; ++i) {
Console.WriteLine(i);
}
Console.Write(i); // Prints 10
}

This can lead to some nastiness if you're not expecting it, particularly if you expect variables to get reinitialized for each iteration in a loop.

It also means that variables (including objects) do not go out of scope, and thus are not garbage collected until a function ends.

Powerlord on July 8, 2008 07:11 PM

You can take this much further by eliminating "frugal variables" all-together and simply compose functions ala Joy and other concatenative languages. I'm reading "Thinking Forth" at the moment and loving it, not as much as I loved the JonesForth Assembler Tutorial which are just as enlightening as the Joy essays. Go forth if you dare, and learn true minimalism.

Craig Overend on July 8, 2008 07:30 PM

Ha ha. All my projects start out spartan...

Dan on July 8, 2008 07:43 PM

I dont mean to be a downer, but sometimes it feels like these posts fish a little from the shallow side just to have some fresh content. The result is regurgitation, echoing information that other people wrote without adding anything new or original. Thats not contributing.

- After 20 years of programming, youve reflected that its usually a good idea to remove unnecessary code. quite a compelling conclusion.

- Throwing in a tangential pop-culture image just waters this down even more

- How do you justify yourself? Links to other places are a weak way to justify your opinion.

If it is just plain obvious that you should reduce your code and you dont need to justify the argument, then your whole article is ironic, because there is nothing minimalistic in writing an article about the obvious.
Consider an ieee paper regarding some case studies used to define hard figures behind the economics of software reuse
http://csdl2.computer.org/persagen/DLAbsToc.jsp?resourcePath=/dl/mags/co/&toc=comp/mags/co/1994/07/r7toc.xml&DOI=10.1109/MC.1994.10075

I don't know what its like being in your shoes as a professional blogger, and I really support your website and great writing style. Of course you cant be a guru on every subject you cover, because you write about a broad range of subjects.

Maybe my problem is that your blog has become more oriented towards people looking for the pre-digested introductory information.

I cringe a little every time I see you rehashing more common knowledge, because I know if you post less frequently, you have the skills to come up with some great in-depth research.

pete w on July 8, 2008 09:48 PM

You should not try to code smaller. Coding smaller is simply the result of right design for the content.

Andy Wong on July 8, 2008 10:01 PM

> basically link-jacking and unfair usage
> Plagiarism. That's the word I was looking for. Taking credit for the work of another.

I linked back to the wiki *ten* times, included an explicit citation at the top, and added a hat tip to Yuval Tobias, who provided me the link, at the bottom. I'd have linked to Yuval's blog page or website, too, if he had provided me a link.

How, exactly, am I claiming this as my own?

Jeff Atwood on July 8, 2008 10:47 PM

I hope Spartan Programming does not mean converting this:
if(bIsAlive)
{
Kill();
}
to this:
if(bIsAlive)
Kill();

I hate when someone does not use the braces ven if it means that its just one line. That is because:
1) The braces make it more readable and does not confuse me.
2) When maintaining such a code, if I also want to PunishTheKiller(), I have to either tag the two braces of the 'if' with enclosing code change comments or I have to comment the whole if block and rewrite it again. Something like this.
if(bIsAlive)
// >> Change # 1234
Kill();
// >> Change # 1234

------ OR ----------
// >> Change # 1234

----------------------------------
------- WHEN IT COULD BE ---------
----------------------------------
if(bIsAlive)
{
Kill();
PunishTheKiller(); // Change # 1234
}

Daanish Rumani on July 9, 2008 12:17 AM

Correction:

if(bIsAlive)
// BEGIN Change # 1234
{
// END Change # 1234
Kill();
// BEGIN Change # 1234
PunishTheKiller();
}
// END Change # 1234

------ OR ----------
// BEGIN Change # 1234
//if(bIsAlive)
// Kill();

if(bIsAlive)
{
Kill();
PunishTheKiller();
}
// END Change # 1234

----------------------------------
------- WHEN IT COULD BE
----------------------------------
if(bIsAlive)
{
Kill();
PunishTheKiller(); // Change # 1234
}

Daanish Rumani on July 9, 2008 12:19 AM

>100 comments so far. Am I the only person here who suspects that this Spartan programming guide is tounge-in-cheek?

Charles Monk on July 9, 2008 12:42 AM

Most of the things look cool except that naming convention thing. In other words one should not be burn down variable names to letters or don't try to write obfuscated code while there are obfuscating tool already available.

Faheem on July 9, 2008 12:50 AM

Hi,

I guess I am responsible for coining the term "Spartan Programming", and for authoring the wikipages on the topic. My attention was drawn to this thread. I truly appreciate the comments, and would like to hear more of those - and get the discussion going.

Here is my response to some of the comments I saw here:

- Terse naming in in a sense an end, not a tool. That is, you should code in such a fashion that terse names make sense. Consider for example the code fragement: "c.setSN(f.getSN());" used here.
Is "c" a good or a bad name? Well, it depends, not on the complexity fo the algorithm, but rather on the scope: if "c" is defined and used in a very small scope (say a handful of lines), with a few other similarly short scoped identifiers hanging around, then "c" is an ideal name.

If however, the scope is large, and there are many other names that the reader has to keep in mind, then "c" is a bad name. The cure I think is not in using a longer, more meaningful and much more verbose
name for this entity, but rather in refactoring that would make the code small enough so that "c" becomes an appropriate choice.

- There were some comments about "foreach" construct. I firmly believe that "forach" is the way to iterate, whenever possible, but
not beyond that limit.

- PHP can also be spartanized: I once run a huge project in which I was trying to semi-automatically spartanize a CMS program, using the number of conditional as the primary metric. The results were encouraging, but the whole project went down the drain due to a disk crash.


- Please note that the wiki offers many examples of Java classes written in the Spartan style. These are not perfect, but you may want to consider these in your discussion. Here are a number of links
(there are more):

http://ssdl-wiki.cs.technion.ac.il/wiki/index.php/Class_Position
(an implementation of a (line:column) pair

http://ssdl-wiki.cs.technion.ac.il/wiki/index.php/Class_Graph
(an implementation of a Graph data structure)


http://ssdl-wiki.cs.technion.ac.il/wiki/index.php/Class_DBC
(an implementation of Design by Contract)

http://ssdl-wiki.cs.technion.ac.il/wiki/index.php/Class_Defaults
(a useful "micro abstraction")

Many more examples can be found by searching for the "Class XXXX" pattern in the wiki index.
http://ssdl-wiki.cs.technion.ac.il/wiki/index.php/Special:Allpages

----------------

Thanks for your attention, I would try to make myself available for more comments and discussion.

Yossi

Yossi GIl on July 9, 2008 01:22 AM

@J. Stoever:
> "..[my code].. That's terrible, terrible, terrible code. The entire logic is removed and abstracted away in favor of some bit juggling that nobody is ever going to understand again six months from now."

Hmm... there is absolutely NO "bit juggling" going on there. So I'm not sure what you mean by that.
Personally I think it's purpose is pretty obvious and I've never had comments on code like that from peer-reviewers or guys doing maintenance.

But okay, if you want the logic to be more explicit then you could also have the slightly more verbose:

bool statusOk = func1();
if (statusOk)
____statusOk = func2();
if (statusOk)
____statusOk = func3();

if ( statusOk )
____dostuff();

return statusOk;

..which likewise doesn't suffer from the "need to indent 20 times within a function", which as my original point.

If you want to see a properly obscure way of doing this, then consider this approach which was suggested to me in the past (and rejected):

bool result = false;

do {
____if (func1() == false)
________break;
____if (func2() == false)
________break;
____if (func3() == false)
________break;

____dostuff();
} while (false);

return result;

Graham Stewart on July 9, 2008 02:02 AM

"Weird philosophy!

Your basically saying why use existing, well-tested language constructs and libraries that "hide your code" when you can write your poor equivalents with new and interesting bugs."

Yeah... I take it too far. Still... I will use stuff like strcpy etc out of laziness... but to use a whole framework like .net or java... no thanks. Only when a project gets really big... and as a one man band that basically never happens. :)

Jheriko on July 9, 2008 02:37 AM

Yes, a little bit cryptic, single-letter identifiers whenever we need, for *we do know what the asceticism is*.

Considering the article on regular expressions, I am afraid I am not able to get the point. Readable and maintainable code? I don't think so ...

Maximus on July 9, 2008 02:42 AM

"To me, a variable name can never be too long. In my opinion, a variable name absolutely has to be descriptive, so that other programmers can more easily see what is going on. If a variable must be named horizontalScalingFactorBeforeZoom, then so be it."
This is what led to me spending half, before realising that horizontalScalingFactorBeforeZoom and horizontalScaleFactorBeforeZoom weren't the same. Compare scale and scaling.
LONGER IS NOT MORE DESCRIPTIVE.

Tom on July 9, 2008 02:51 AM

"To me, a variable name can never be too long. In my opinion, a variable name absolutely has to be descriptive, so that other programmers can more easily see what is going on. If a variable must be named horizontalScalingFactorBeforeZoom, then so be it."
This is what led to me spending half an hour debugging some code, before realising that "horizontalScalingFactorBeforeZoom" and "horizontalScaleFactorBeforeZoom" weren't the same. Compare scale and scaling.
LONGER IS NOT MORE DESCRIPTIVE.

Tom on July 9, 2008 02:52 AM

I suppose its best with an example... by using the C++ string functions to extract values from plain text (sscanf) and do stuff with them (strcat/sprintf) I had a particular app taking minutes to parse large text files. My friend suggested that the string functions were at fault, which I initially was pretty skeptical about, but I debugged the code and stepped through to the runtime library code where I found that strcat was needlessly rechecking the string length (I could have worked this out for myself on inspection were I a better programmer).

So I wrote my own code that kept track of the length from the beginning and increased it as it created the string... problem solved. It became unnoticably quick... i.e. it took less than a second to parse the file and produce the new text.

there is a strncat function... but sadly it provides the rather useless option of adding the first n chars. rather than letting you feed the length of the string to be appended to. mystr[n] = 0; is any harder to read or understand than strncat(foo, mystr, n)?

API and language developers are just as crap as the rest of us.

I'm sure this is a pretty noobie problem that many may have encountered. I'd be interested to hear if there is a good solution using pre-written functions...

This is precisely the sort of thing which .NET will hide under a foreach or similar construct too...

Jheriko on July 9, 2008 02:53 AM

I agree, on the whole, with this post and with Graham. All too often I see:

if(hasBrain == true)
return true;
else
return false;

Firstly, as a programmer you know that hasBrain is a boolean, so why compare it to a literal value that has to be created just for the comparison? Secondly, why create a further literal for the return value, when the value already exists? I know that some people find it "easier" to read but, if you have two brain cells to rub together, it's just as easy to read:

return hasBrain;

This principle can also be extended to:

if(length > 10 && length < 20)
return true;
else
return false;

Why not just:

return length > 10 && length < 20;

I know it's (slightly) less readable but only someone with hasBrain = false won't know what it returns.

Steven Bey on July 9, 2008 03:01 AM

I think one of the more important types of minimalism these days is dependencies. This is a layer above the more code-centric issues that you have already mentioned, and looks at the system as a whole.

The other day I updated my copy of Pidgin through the MacPorts system on OS X. It worked for literally hours, downloading and building package after package of random dependencies, of which I knew nothing of their purpose. This kind of runaway dependency bloat afflicts many open source programs.

I like to build programs that depend on as little external stuff as possible. Sometimes I might have to build a tiny bit of extra functionality that could be obtained by linking with yet another library, but I choose to make it easy on the author, the maintainers, and the users.

Greg Hewgill on July 9, 2008 03:13 AM

@michael:
"""Of course in Python the for loop IS a foreach loop and nobody cares about performance since it's already interpreted."""

Please get your facts right. First point : Python is byte-compiled (at least CPython, StacklessPython, Jython and IronPython are). Second point: yes, there are people that actually care about Python's performances.

bruno on July 9, 2008 03:16 AM

@Daanish Rumani, I've always preferred to put 'change' comments in source control rather than litter my code with them, otherwise the code just gets harder to read. That way a diff between versions, along with the comment helps to identify and cross reference any changes.

Agree with you about the braces though, I like to see them even for single line blocks, much easier to read.

j450n on July 9, 2008 03:17 AM

I think spartan is important, I code not organized and I face problems when I want to change my code :(

Omar Abid on July 9, 2008 03:49 AM

For me, the example under 'horizontal complexity' is terrible; I always try to write such constructs as:

int abs(int x) {
return x < 0 ? -x : x;
}

The shorter the code, the less the cognitive strain, the less chance of bugs, etc. I became a far more efficient coder once I started making full use of the ternary operator.

bobby on July 9, 2008 05:27 AM

@Steven Bey

You mean "only someone with !hasBrain", of course ;)

bobby on July 9, 2008 05:29 AM

Here's some succinct code I wrote just now that caused a stackoverflow :)

public double LargestYVal
{
get{ return LargestYVal;}
}

An unusual retrograde fitting scenario (short version legacy code pre the coding standard in our team) caused me to use a not ideal naming convention (the private member was already labelled LargestYValue ;) ) Which meant intelisense ( a tool to aid lazy programming) allowed me to inadvertantly code a tight loop, which the compiler swallowed without complaint.

So in my attempt to avoid renaming all occurances of LargestYValue to largestYValue (to save time Ha!), I lost having to go through a second build and test !

HollyStyles on July 9, 2008 06:00 AM

"The shorter the code, the less the cognitive strain, the less chance of bugs"
Not really. Code that's been deliberately compressed in terms of the lines or the speed requires more cognitive strain than slightly more verbose code that performs in an easily understood manner.

Tom on July 9, 2008 06:07 AM

@bobby

I like your comment but it was a conscious decision to write it as hasBrain = false (for the guys who can't read !hasBrain), although my point was muted, slightly, as it should really have been hasBrain == false.

Steven Bey on July 9, 2008 06:17 AM

I'll give a second to this response:

"Character count should be a concern, but not at the expense of readability. Ever."
--Kris on July 8, 2008 01:03 PM

N on July 9, 2008 06:22 AM

I'm the only one to think that by replacing this

String curr = i.next();
InternetAddress[] temp = InternetAddress.parse(curr, false);
toAddresses.addAll(Arrays.asList(temp));

whit this:

toAddresses.addAll(Arrays.asList(InternetAddress.parse(r, false)));

you make the code 10x less readable?

And many of rules from Spartan programming remove readability of the code?

Igor Ghisi on July 9, 2008 06:31 AM

Yup, this pretty much looks exactly like my own personal coding philosiphy.

At this moment I'm in the process of rewriting some code that isn't working. I spent weeks trying to figure out what it was doing. I traced the main execution path on a whiteboard, and found it goes through 10 layers of function calls, including a callback (but not including possible extra layers from one recursive routine). The source file is over 10,000 lines long. But if I insert a "return" statement at the top of the first routine there is no difference in results.

So far I've rewritten the equivalent of the first 5 layers (including the callback) in one routine that takes about 80 lines (comments included). That's actually still a bit large for my tastes, but a major improvement. I may find more I can remove later.

T.E.D. on July 9, 2008 06:36 AM

Spartan comment.

A. Lloyd Flanagan on July 9, 2008 06:43 AM

For Sparta!

Anon on July 9, 2008 06:45 AM

@Tom
> LONGER IS NOT MORE DESCRIPTIVE

Your example shows two _long_ poorly named variables. I'd wager to say that two _short_ poorly named variables are just as bad.

A longer, more clear name is always better than something short and cryptic, but both are going to fall apart when named almost identically.

So, anyhow, yes - longer is more descriptive.

HB on July 9, 2008 06:49 AM

I think the point is that going with either too terse or too verbose causes problems. Avoid extremism, be a moderate coder.

Jeff Davis on July 9, 2008 06:51 AM

> c.setSN(f.getSN());
>
> is not as easy to understand as
>
> child.setSurname(father.getSurname());

I'd agree with that. However, I find the following even better:

child.set(father.surname());

or in the case where there might be multiple different kinds of names a child has that you'd want to set this way (likely in this case):

child.surname(father.surname());

This first is still clearer if you can pull it off though. I think its because you can get away with noun names for constant (non-modifying) methods, but should really have verb-ish names for modifying ones. Having multiple members with the same type kind of hoses you here. This is why you should make your code as strongly-typed as is reasonable to do. Add that to the list. :-)

T.E.D. on July 9, 2008 07:00 AM

Applying Spartan techiniques during maintenence of non-Spartan code looks exactly like the movie.

David B on July 9, 2008 07:08 AM

Hmmm. Looking over their example at http://ssdl-wiki.cs.technion.ac.il/wiki/index.php/Spartan_programming_C_example I see one further thing I'd do. Namely, I'd put the whole frigging thing in a namespace named "SAL", and then remove the "SAL_" off the front of everything. I count 52 of them that would get rid of.

T.E.D. on July 9, 2008 07:33 AM

ANSI-C to T.E.D. > "What's a namespace?"

Graham Stewart on July 9, 2008 07:48 AM

> ANSI-C to T.E.D. > "What's a namespace?"

Oooh, that is plain C, isn't it?

This is a good illustration why I always avoid C when possible. It just lacks *way* too many tools.

Add avoiding C to the list. :-)

T.E.D. on July 9, 2008 07:53 AM

To elaborate on the general unfitness of plain old C, I just went through their list of Spartan techniques. Of the variable techniques, 4 of the 7 are either impossible or much more difficult in C. 2 more are debatable. Of the 5 listed control techniques, 2 are impossible in C.

I think this is a nice objective illustration of the inferiority of C for writing concise readable code. (Although really I find C's worst offense to be lack of exception support, and the oceans of error-checking code that engenders).

T.E.D. on July 9, 2008 08:53 AM

@j450n
Our condition is a bit different. We have different teams starting with say v1.0 code base and do modifications to their modules. Each of the teams maintain a separate fork on the source control server. So when v2.0 is nearing release, there is a "big bang" merge that happens which would be the v2.0 code base. We then integration test it.

But apart from a "big bang" merge we may also have to merge code for a particular Change Request (that fixes a particular bug). And many a times, two or more change requests cause changes to the same file(s).

Besides, having the code change comments means that any person from the team can do the merge. That person receives a list of changed files, compare those with the checked-in ones, merges them locally and then they are finally check back in.

However, I do admit that it becomes messy after some time. But perhaps that is the price we pay!

Daanish Rumani on July 9, 2008 09:04 AM

Is there any way to make the number of commenters, and the comments, more Spartan?

Never fails -- do a post on programming preferences, watch the comments fly...

steve on July 9, 2008 09:53 AM

@T.E.D.:

Nice troll against C. I'll bite.

Firstly, I disagree - /most/ of those techniques sound like they will work just fine in C. List the ones you think are impossible or difficult.

Secondly, yeah C is a pretty old language that was never intended for modern large-scale enterprisey business solutions. So it lacks modern comfort-blankets like namespaces, exceptions, strings, classes, ADTs and a usable framework.

However it is still an excellent language for embedded and other close-to-the-metal applications where speed and size still matter.

And it is *definitely* possible to write concise C code - as for readable... well that depends who is reading it :)

Graham Stewart on July 9, 2008 10:00 AM

More comments:

* Terse naming refers mostly to variables. So in referring to the example, c.setFN(...), Spartan does not argue that the function is named setFN.

* The C example is not very convincing, I agree. Will try to find a more illustrative one.

* Most importantly, I invite anyone to examine the Spartant code samples (taken from a large, production application), to make more concrete comments.

Yossi GIl on July 9, 2008 10:26 AM

I can't remember ever disagreeing more with Jeff on any issue before.

@Graham:
Comparisons aren't free, you loose some milliseconds on them. And hiding logical sequencing using and/or tricks when calling your functions and lazy evaluation is bad taste in most languages.

Early returns are a definitive "yes" if your code is in a critical procedure to be called hundreds or thousands of time per second by other parts of your whole program.

It's definitely safer and faster (and easier to read) to do this:
my proc{
do_stuff();
if(error){
return error_code;
}

do_more_stuff();
if(final_condition){
return calculated_value;

even_more_stuff();
if(error){
return another_error_code;
}
return another_value;
}

than using boolean flag variables and doing comparisons all the way down:
my proc{
do_stuff();
if(error){
error_detected = true;
return_value = error_code;
}

if(!error_detected){
do_more_stuff();
if(final_condition){
final_condition_reached = true;
return_value = calculated_value;
}
}
if(!(error_detected or final_condition_reached){
even_more_stuff();
if(error){
return another_error_code;
}
return another_value;
}
}

Early return is equivalent to a GOTO, and for good reasons!!!
The Linux kernel code still has some goto's here and there, mainly on critical error catching stuff. And it's logical: if an error has been detected, you'd better go fast as fast as possible to the code that deals with the problem.

I just *hate* single character variable names, they obscure too much the code.

And I have learned to avoid ternary operators as plague over the years. Doing simple stuff like:
int abs(int x) {
return x < 0 ? -x : x;
}

Is OK. But time after time in different companies I've worked for, I find developers who abuse them. I once found code written by some "clever" developer who thought using 4 ternary operators (2 of them nested within the other and yet with another ternary expression within) was preferable to the "long" version using plain old if...else structures.

Guess what? His code had bugs. And it was easier to understand/debug when I rewrote it into several if...else lines.
So I for one am happy some modern languages (like Python) have simply proscribed them. These kind of features (like inheritance and polimorphism) tend to be abused way to often.

Joe on July 9, 2008 11:01 AM

I can't remember ever disagreeing more with Jeff on any issue before.

@Graham:
Comparisons aren't free, you loose some milliseconds on them. And hiding logical sequencing using and/or tricks when calling your functions and lazy evaluation is bad taste in most languages.

Early returns are a definitive "yes" if your code is in a critical procedure to be called hundreds or thousands of time per second by other parts of your whole program.

It's definitely safer and faster (and easier to read) to do this:
my proc{
do_stuff();
if(error){
return error_code;
}

do_more_stuff();
if(final_condition){
return calculated_value;

even_more_stuff();
if(error){
return another_error_code;
}
return another_value;
}

than using boolean flag variables and doing comparisons all the way down:
my proc{
do_stuff();
if(error){
error_detected = true;
return_value = error_code;
}

if(!error_detected){
do_more_stuff();
if(final_condition){
final_condition_reached = true;
return_value = calculated_value;
}
}
if(!(error_detected or final_condition_reached){
even_more_stuff();
if(error){
return another_error_code;
}
return another_value;
}
}

Early return is equivalent to a GOTO, and for good reasons!!!
The Linux kernel code still has some goto's here and there, mainly on critical error catching stuff. And it's logical: if an error has been detected, you'd better go fast as fast as possible to the code that deals with the problem.

I just *hate* single character variable names, they obscure too much the code.

And I have learned to avoid ternary operators as plague over the years. Doing simple stuff like:
int abs(int x) {
return x &lt; 0 ? -x : x;
}

Is OK. But time after time in different companies I've worked for, I find developers who abuse them. I once found code written by some "clever" developer who thought using 4 ternary operators (2 of them nested within the other and yet with another ternary expression within) was preferable to the "long" version using plain old if...else structures.

Guess what? His code had bugs. And it was easier to understand/debug when I rewrote it into several if...else lines.
So I for one am happy some modern languages (like Python) have simply proscribed them. These kind of features (like inheritance and polimorphism) tend to be abused way to often.

Joe on July 9, 2008 11:06 AM

Jheriko: I am not sure that a programming language is just a tool in the same way a painter's brush is a tool. Your statement, "poor workmen blame their tools. the opposite is also true, a master craftsmen will take the worst raw materials and the worst tools, and still will create a masterpiece" may apply in the case of a painter, but not so much in the case of a program [ as the final product ] and the programming language it is written in [ as the tool ].

Here we are looking at, lets say a dish and its ingredients. Bad ingredients more than likely will result in bad tasting food, no matter how good the cook is.

For instance [ hoping not to come acro