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

July 8, 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)

Posted by Jeff Atwood    View blog reactions
« The Problem With Code Folding
iTunes is Anti-Web »
Comments

first!

gothael on July 8, 2008 6: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 6: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 6: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 6: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 6: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 6: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 6: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 6: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 6: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 6: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 6: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 7: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 7: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 7: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 7: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 7: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 7: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 7: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 7:19 AM

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

Malcolm on July 8, 2008 7: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 7: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 7: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 7: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 7: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 7: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 7: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 7: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 7: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 7: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 7: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 8: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 8: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 8: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 8: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 8:19 AM

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

heri on July 8, 2008 8: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 8: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 8: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 8: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 8: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 8: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 8: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 8:39 AM

Less is more.

Charles on July 8, 2008 8: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 8: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 8: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 9: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 9: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 9: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 9: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 9: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 9: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 9: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 9: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 9: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 9: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 9: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 9: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 9: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 9: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 9: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 9: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 9: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 9: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 9: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 9: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 1: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 1: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 1:23 PM

Nice post

John Pirie on July 8, 2008 1: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 1: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 2: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 2: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 2: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 2: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 3: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 4: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 4: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 5:25 PM

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

James A. on July 8, 2008 5: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 5: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 5: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 5: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 6: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 6: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 7: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 7: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 7:30 PM

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

Dan on July 8, 2008 7: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 9: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 1: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 2: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 2: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 2: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 2: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 2: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 2: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 3: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 3: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 3: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 3: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 3: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 5:27 AM

@Steven Bey

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

bobby on July 9, 2008 5: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 6: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 6: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 6: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 6: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 6: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 6:36 AM

Spartan comment.

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

For Sparta!

Anon on July 9, 2008 6: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 6: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 6: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 7:00 AM

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

David B on July 9, 2008 7: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 7:33 AM

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

Graham Stewart on July 9, 2008 7: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 7: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 8: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 9: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 9: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 across as comparing apples and oranges ], how would you separate slowness of a program written in, lets say, Perl from the language when compared to its equivalent written in a compiled language, C or C++.

Languages are more than just a tool in that they give life to algorithms while carrying on their own built-in attributes.

Ivan on July 9, 2008 11:25 AM

i could not help but refactor the java-example to c#:

public static void SendEmail(
string vsFrom,
List<string> vsaRecipients,
string vsSubject,
string vsBody,
List<string> vsAttachements,
bool vbActuallySend)
{
MailMessage msg = new MailMessage();
msg.From = new MailAddress(vsFrom);
foreach (string lsRecipient in vsaRecipients)
{
msg.To.Add(new MailAddress(lsRecipient));
}
msg.Subject = vsSubject;
msg.Body = vsBody;

foreach (string lsFilename in vsAttachements)
{
if (!File.Exists(lsFilename))
{
throw new FileNotFoundException("file not found", lsFilename);
}
msg.Attachments.Add(new Attachment(lsFilename));
}

if (vbActuallySend)
{
SmtpClient loSmtp = new SmtpClient();
loSmtp.Credentials = null; // insert your creds here
loSmtp.Send(msg);
}
}

It has not the exact same function as the example, but seems to be more readable, i hope. Of course, some of the won readability is the merit of the sophisticated .NET-libs, not the language itself.
The function itself is possibly superfluous, because you could rebuild this scheme at the position of the function-call - could be more mantainable in some cases.

titrat on July 9, 2008 1:21 PM

I actually agree with most of Graham's comments about C. For bare metal work, I think you are actually still better off using Ada if you know it and have a compiler available, but those are two huge ifs. That's another argument for another time though.

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

Actually, that's a very good suggestion.
Using the lists from http://ssdl-wiki.cs.technion.ac.il/wiki/index.php/Spartan_programming

Frugal use of Variables
1) The first half of this works great in C, the second half doesn't work at all. C has no such "advanced programming constructs".
2) This works in C today, although it is only recently that compilers started allowing variables to be defined in loops.
3) No such thing as a "private" variable in C. If its in the interface, anyone can whack at it.
4) No such thing as "constants" in C. You can kind of fake it with the macro preprocessor, but that's not type-safe, has universal scope, and is just plain nasty to boot. No restrictions. No annotations.
5) Not really sure what this one means. But I am sure it works just fine in C, whatever it is.
6) This one's a bit vague too, but as I understand it, it should work just fine in C.
7) No standard componet library for C. I'm sure there are tons of do-it-yourself C-only component libraries floating around, but none of them are really universally recognized standards. Every program I've seen rolls its own data structures using pointers or arrays.

Frugal use of Control
1) No classes or inheritance support.
2) Works fine in C.
3) No classes, thus no action applicator classes.
4) Works better in C than most other languages I've seen. Ada allows you to label loops and exit out of specfic layers, instead of just one, but Ada doesn't have continue.
5) Designed for C, obviously.

T.E.D. on July 9, 2008 1:22 PM

Dear Jeff,
someone is eating all trailing whitespace in the comments - is there a special reason for this behaviour?

titrat on July 9, 2008 1:25 PM

Following the discussion, I completed the Java Spartan Programming example. The result, shown at http://ssdl-wiki.cs.technion.ac.il/wiki/index.php/SendAnEmail_case_study

demonstates why short, one variable names makes sense.

private static void sendEmail(final String from, final List<String> to, final String subject, final String body,
final List<File> attachments) throws Throwable {
final Session s = Session.getInstance(new Properties());
final Message m = new MimeMessage(s);
setHeaders(m, from, to, subject);
setContent(m, body, attachments);
sendMessage(m, s);
}

private static void setHeaders(final Message m, final String from, final List<String> to, final String subject) {
m.setSentDate(new Date());
m.setFrom(new InternetAddress(from));
for (final String t : to)
m.addRecipients(Message.RecipientType.TO, InternetAddress.parse(t, false));
m.setSubject(subject);
}

private static void setContent(final Message m, final String body, final List<File> attachments) throws MessagingException {
if (attachments.size() == 0) { // ''No attachments to send''
m.setText(body);
return;
}
// ''Generate a multi-part message''
final MimeBodyPart textPart = new MimeBodyPart();
textPart.setText(body);
final Multipart mp = new MimeMultipart();
mp.addBodyPart(textPart);
for (final File f : attachments)
mp.addBodyPart(makeBodyPart(f));
m.setContent(mp);
}

private static MimeBodyPart makeBodyPart(final File f) throws MessagingException {
final MimeBodyPart $ = new MimeBodyPart();
final FileDataSource fds = new FileDataSource(f);
$.setDataHandler(new DataHandler(fds));
$.setFileName(fds.getName());
return $;
}

private static void sendMessage(final Message m, final Session s) {
final Transport t = s.getTransport("smtp");
t.connect(smtpServer, port, userName, password);
t.sendMessage(m, m.getAllRecipients());
t.close();
}

Yossi GIl on July 9, 2008 1:38 PM

Terrible idea. Oh, I can see its use in math formulas where the Xs and Ys are established by convention, but parameters as single letters? Never!

int abs(int x) {
if (x < 0)
return -x;
else
return x;
}

is clearer than

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

Rather than "frugal coding", I suggest a "frugal response". If I were to write one, it would likely be:

!me

Paul Schirf on July 9, 2008 2:11 PM

to Schirf: how about:
int abs(int x)
{
return (x < 0) ? -x : x;
}

at least it's spartanic ...

titrat on July 9, 2008 2:26 PM

Baited by a troll? Perhaps.

Sorry @Yossi, I disagree 100%, but then I use languages with objects as first class citizens, and most of your one-liners can be removed by using a class and better use of object oriented techniques.

/// xmldoc comments deleted.
public SendMessageResult SendMessage( HtmlMailMessage htmlMailMessage)
{
// check preconditions
if( htmlMailMessage == null ) throw new ArgumentNullException("htmlMailMessage");
if( !htmlMailMessage.HasRecipients() ) throw new Exception("no recipients in message");
if( !htmlMailMessage.HasSender() ) throw new Exception("no sender specified");

// create SmtpMessage from our own HtmlMailMessage
SmtpMessage message = new SmtpMessage();

message.Type = MessageType.Html;
message.Body = htmlMailMessage.HtmlBody;
message.Sender = CreateSmtpSenderFor(htmlMailMessage.Sender);
SetMessageRecipientsTo(message,htmlMailMessage.Recipients);

try
{
SmtpClient client = new SmtpClient("mail.mycompany.com");
SentMessageIdentifier messageId = client.Send(message);
return new SuccessSendMessageResult(messageId);
}
catch( SmtpClientException ex )
{
// this method does not propagate smtp client exceptions.
return new ExceptionSendMessageResult(ex);
}
}

None of this rubbish with s, m, t, etc. It's readable even if you don't know C#, and even if you don't know what the SendMessageResult, ExceptionSendMessageResult, SuccessSendMessageResult or HtmlMailMessage objects look like, and you don't have to look at the methods CreateSmtpSenderFor and SetMessageRecipientsTo to figure out what they're supposed to do.

Maybe I've evolved, but I have to keep scanning up to see what s, m, and t are. My brain does a great job of pattern recognition, and there's a cognitive penalty to single character variable names when they're not universally accepted e.g. 'ex' is accepted for exception (in C#), but s and m are not session (or was that sender) and message universally. It's easier to read if the variable is session, not s.

The only thing I see is an attempt to round up a few half-baked refactoring techniques in a few pages of text and label it 'spartan'. You can only get out what you've put in. Read Fowlers Refactoring book, which I might add will take a few days, as it's more than a few hundred pages.

Go to http://www.refactoring.com/

RedGreen on July 9, 2008 4:28 PM

@TED I'd reckon that child.Surname = father.Surname is a little clearer.

For property-disabled languages, child.set_Surname( father.get_Surname() ); (or whatever your language's convention is)

child.surname() by itself implies that surname is an action, and is not just setting a property. I surname() you? Huh? Property get and set's are best done with a convention that implies they are just properties, and their only side-effect is a property set (or get).

Maybe to a western, english reader's perspective it's obvious, but even we can't agree what to call it.

RedGreen on July 9, 2008 4:31 PM

Oh, I didn't say that you claimed it as your own. However, you are reaping a significant benefit out of its use, which in the form you apply it is nearly a word for word copy.

Basically, the concept is like this. Suppose someone quoted 90% of a novel, interjecting comments every few pages and copiously mentioning the title and author of the novel. It would still be plagiarism and unfair use because the original content dramatically outweighs the new contribution.

The only place I did misspeak is that it's possible the wiki page has licensing that allows this type of use. Which means it is not exactly "wrong." But still, the central point is that you are here deriving benefit from content which is primarily someone else's work. And I don't like it.

Your article here is barely better than a link to the page along with a picture and your disclaimer in the final paragraph. You're free to do what you please with this, but since you provide a forum for comments, I felt I should voice my objection.

James A. on July 9, 2008 4:32 PM

Bothered to look up the definition of plagiarism: I used it incorrectly. For that I am sorry. However! I still believe the use you put this wiki article to is unfair because, whether you claim _academic_ credit for it or not, you are still deriving _financial_ benefit from the work of another. Mere citation does not absolve you of this; original content would.

James A. on July 9, 2008 4:38 PM

I figured modern compilers are usually smarter than the programmer writing them. So, in all likelihood, it's better to write clear and concise code and let the compiler sort out the optimization. But, in the interest of science, the compiled bytecode is different (for now). Although the JIT'er is free to do it's own optimizations.

Typically I'd prefer code in Cone_A because it's more easily debugged and easier to understand that it's been coded correctly.

public class Cone_A
{
public double Radius { get; set; }
public double Height { get; set; }
public double ComputeVolume()
{
double result = Math.PI * Math.Pow(Radius, 3) * Height;
result /= 3.0;
return result;
}
}
public class Cone_B
{
public double Radius { get; set; }
public double Height { get; set; }
public double ComputeVolume()
{
return ( Math.PI * Math.Pow( Radius, 3) * Height) / (3.0);
}
}

The result, Cone_B::ComputeVolume() is much smaller in release mode. Execution time wasn't tested.

I apologise for the long post, but it's the only way to shut people up.

//In .net, DEBUG version of code. Cone_A::ComputeVolume
.method public hidebysig instance float64
ComputeVolume() cil managed
{
// Code size 57 (0x39)
.maxstack 3
.locals init ([0] float64 result,
[1] float64 CS$1$0000)
IL_0000: nop
IL_0001: ldc.r8 3.1415926535897931
IL_000a: ldarg.0
IL_000b: call instance float64 Inlining.Cone_A::get_Radius()
IL_0010: ldc.r8 3.
IL_0019: call float64 [mscorlib]System.Math::Pow(float64,
float64)
IL_001e: mul
IL_001f: ldarg.0
IL_0020: call instance float64 Inlining.Cone_A::get_Height()
IL_0025: mul
IL_0026: stloc.0
IL_0027: ldloc.0
IL_0028: ldc.r8 3.
IL_0031: div
IL_0032: stloc.0
IL_0033: ldloc.0
IL_0034: stloc.1
IL_0035: br.s IL_0037
IL_0037: ldloc.1
IL_0038: ret
} // end of method Cone_A::ComputeVolume

//DEBUG Cone_B::ComputeVolume
.method public hidebysig instance float64
ComputeVolume() cil managed
{
// Code size 53 (0x35)
.maxstack 3
.locals init ([0] float64 CS$1$0000)
IL_0000: nop
IL_0001: ldc.r8 3.1415926535897931
IL_000a: ldarg.0
IL_000b: call instance float64 Inlining.Cone_B::get_Radius()
IL_0010: ldc.r8 3.
IL_0019: call float64 [mscorlib]System.Math::Pow(float64,
float64)
IL_001e: mul
IL_001f: ldarg.0
IL_0020: call instance float64 Inlining.Cone_B::get_Height()
IL_0025: mul
IL_0026: ldc.r8 3.
IL_002f: div
IL_0030: stloc.0
IL_0031: br.s IL_0033
IL_0033: ldloc.0
IL_0034: ret
} // end of method Cone_B::ComputeVolume


// And again, in RELEASE mode. Cone_A::ComputeVolume
.method public hidebysig instance float64
ComputeVolume() cil managed
{
// Code size 52 (0x34)
.maxstack 3
.locals init ([0] float64 result)
IL_0000: ldc.r8 3.1415926535897931
IL_0009: ldarg.0
IL_000a: call instance float64 Inlining.Cone_A::get_Radius()
IL_000f: ldc.r8 3.
IL_0018: call float64 [mscorlib]System.Math::Pow(float64,
float64)
IL_001d: mul
IL_001e: ldarg.0
IL_001f: call instance float64 Inlining.Cone_A::get_Height()
IL_0024: mul
IL_0025: stloc.0
IL_0026: ldloc.0
IL_0027: ldc.r8 3.
IL_0030: div
IL_0031: stloc.0
IL_0032: ldloc.0
IL_0033: ret
} // end of method Cone_A::ComputeVolume

// RELEASE Cone_B::ComputeVolume
.method public hidebysig instance float64
ComputeVolume() cil managed
{
// Code size 48 (0x30)
.maxstack 8
IL_0000: ldc.r8 3.1415926535897931
IL_0009: ldarg.0
IL_000a: call instance float64 Inlining.Cone_B::get_Radius()
IL_000f: ldc.r8 3.
IL_0018: call float64 [mscorlib]System.Math::Pow(float64,
float64)
IL_001d: mul
IL_001e: ldarg.0
IL_001f: call instance float64 Inlining.Cone_B::get_Height()
IL_0024: mul
IL_0025: ldc.r8 3.
IL_002e: div
IL_002f: ret
} // end of method Cone_B::ComputeVolume

RedGreen on July 9, 2008 4:40 PM

@Joe:

Your example is exactly why I don't like early returns.
Four different return points - yikes! I definitely don't find that easier to read.

> "Comparisons aren't free, you loose some milliseconds on them.

Granted, but measure it. Really. Call it a ten thousand times and measure it.

Try comparing:

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

if ( statusOk )
____dostuff();

return statusOk;

...to the original..

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

dostuff();
return true;

My version has 3 comparisons - the early return version has 3 comparisons.
The only advantage of the early return version is that it is quicker when hits an error, but the normal success path will take roughly the same time for both of them.


@T.E.D.: Thanks for that. I confess I've had one too many beers to go through it tonight, but I'll prepare a suitable rebuff tomorrow.

Graham Stewart on July 9, 2008 4:41 PM

Doesn't seem to be much of anything in the C code. They just defined a struct that needed to be defined anyway, made an enum to replace #defs, and collected two bits of common code together into a function, all of which are things they teach in first year computer science classes anyway.

Personally, I wouldn't even use the enum, since it looks like the meanings of those #defines are tied in with the hardware (I could be wrong), and #defs make it explicitly clear what the flags are, whereas the enum hides it. Enums are best used when the actual values of the enum isn't important.

Bill on July 9, 2008 7:18 PM

Bill: You are very right. The C example is basic. It must be revised!
-------------------------------------------------------------

James A: As the author of the page on Spartan programming, I do not feel being treated too unfairly. To the contrary...
************************************
Further, what I would like to do is open the wiki for editing by
other people interested in the technique. If you are interested, please write to me (my address is not hard to find: look for "Yossi Gil Technion" at Google and it will give your all sorts of contact information.
------------------------------------------
----------------------------------------------------------------

RedGreen: I am not sure I agree with the criterion you offer: that the code is readable even to somone who does not know the language.
I suggest you examine the final code:
The main routine, sendEmail, has only six statements, which make the algorithm particularly clear.

final List<File> attachments) throws Throwable {
final Session s = Session.getInstance(new Properties());
final Message m = new MimeMessage(s);
setHeaders(m, from, to, subject);
setContent(m, body, attachments);
sendMessage(m, s);
----------------------------------
Paul Schirf: Liked your "!me" answer. And, I can understand why some people object to one letter names. Now, I wonder whether your sentiments are as negative towards the final version of the revised
sendEmail message, namely, http://ssdl-wiki.cs.technion.ac.il/wiki/index.php/SendAnEmail_case_study#Final_Result
------------------------------
Tirat: I would write the abs example as
int abs(int x) {
return x > 0 ? x : -x;
}
That is, check first for positiveness (in accordance with the rule of
shortest branch first), and elminate the parenthesis.
---------------------------------------------------
T.E.D. : Would you like to help in revising the C example? Would you mind if I used your suggestions?

Yossi GIl on July 9, 2008 9:23 PM

Can everyone stop? Quit sending code snippets?

PLEASE BE SPARTAN IN YOUR COMMENTS.

steve on July 9, 2008 10:38 PM

I'll make my own programming paradigm. I'll call it Williamprogramming, and it's precept is one:
1) Use good programming practices.

It'll make a million dollars. Anyone want to buy my book?

Bill on July 9, 2008 11:06 PM

@Graham Stewart

I haven't laughed so hard in a long time ....


bool result = false;

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

____dostuff();
} while (false);

return result;

Chris on July 9, 2008 11:41 PM

@Bill
And I will use it(Williamprogramming) to write bad code.
Then what?

Niyaz PK on July 10, 2008 12:22 AM

Now the time has come for me to conclude:
(1) It depends.
(2) Its all about trade offs.

Niyaz PK on July 10, 2008 12:25 AM

I usually apply the DRY principle on my code.

Although it is not actually the same as "spartan programming" (how much I like this name !), I think it shares the basic concept.

Stefano on July 10, 2008 12:31 AM

this.issparta() ?

Mike Kingscott on July 10, 2008 1:51 AM

Yeah I definitely disagree about using shorter variable names. Though making them too long can also be a problem, like variableNameThatGoesForWayTooLong.

If you look out an individual line in their final coding sample, such as m.setContent(mp); you have to remember that m is the message and mp is the multi-part. Yeah I know its only a couple lines up but its still harder to read that then something like message.setContent(multiParts);

Also better named variables can help when it comes to compiling and debugging. For example, in the debugger when you watching variables its easier to know what message is then m.

Grom on July 10, 2008 1:58 AM

to yossi gil:

return x > 0 ? x : -x;

This leads to returning -0, if 0 is the input - not so nice.
I ever use parenthesis when using the ?:-pattern for the "question" - i think it's easier to read this way.
If the code between the : is more complex, i use them even there ().

titrat on July 10, 2008 2:04 AM

That C example is one UGLY piece of coding!

A person that uses if-else in that way should be taken out back and shot (or at least given one hell of a wedgie)

Sverrir on July 10, 2008 2:40 AM

Okay T.E.D. I'm sober enough to attempt a reply:

> 1) The first half of this works great... C has no such "advanced programming constructs".

Yeah fair enough.

> 2) This works in C today, although it is only recently that compilers started allowing variables to be defined in loops.

Hmm.. pretty sure this has been in since at least ISO/IEC 9899 (adopted by ISO in 1999) but I don't have the standard handy to check.

> 3) No such thing as a "private" variable in C...

You can still minimise the "accessibility of variables" e.g. by using static variables.

> 4) No such thing as "constants" in C...

Hmm.. const.. page 39, K&R (2nd edition)

> 5) ..I am sure it works just fine in C, whatever it is.

Yep.

> 6) ..it should work just fine in C.

Yep.

> 7) No standard componet library for C...

Fair comment - though it does also suggest "off-the-shelf" libraries, which, as you pointed out, are available.


> 1) No classes or inheritance support.

Yeah but the rule is "Minimizing the use of conditionals by using specialized constructs" - classes it just an example. It also suggests Ternarization which C has.

> 2) Works fine in C.

Yep

> 3) No classes, thus no action applicator classes.

Yep - can't really do this in C.

> 4) Works better in C than most other languages I've seen.

Yep.

> 5) Designed for C, obviously.

Yep.


So from my point of view, almost all of those rules work for C in some respect :)

Not that I actually agree with all those rules by the way, but I did want to defend C's honour... it's too old to defend itself :)

Graham Stewart on July 10, 2008 3:06 AM

Here is a meta-issue for everyone to consider. I tried reading most of the stuff written here, and noticed a couple of statements, which follow the following 3 parts syllogism:

"(1) Programming practice X is good [bad], because it produces code of style Y.
(2) Style Y is good [ugly] code. For proof see part (3).
(3) I say style Y is good [bad]."

The great fun in making such an argument is never shadowed by the futility of trying to convince anyone with it.

Is there an alternative? I am not sure. My attempt in making the case for Spartan programming was based on more or less agreed upon metrics, and then trying to optimize these.

The difficulty with my argument is that it is a universal truth that any one of these metrics, or any other metric for that matter, is that they can be used to ridicule the purpose they are set to serve.

There is a general agreement (I think) that in general, shorter code is better than longer code, all things being equal.

But, if you try to get the shortest possible program for any given task, you would quickly become a competitor of the obfuscated C code contest.

How does one quantify code quality? Is there a more or less objective method to asses quality?


Yossi GIl on July 10, 2008 3:26 AM

Yossi,

The trouble lies in proving that any particular style is good or bad.

One approach is to back your assertion with some data from a study. This is something that Steve McConnell does repeatedly in Code Complete and personally I find it quite convincing.

For example, on the tricky subject of a good variable name length (Chapter 11.1 in Code Complete 2) he first makes his assertion:

"..Names that are too short don't convey enough meaning. The problem with names like x1 and x2 is that even if you can discover what x is, you won't know anything about the relationship between x1 and x2. Names that are too long are hard to type and can obscure the visual structure of the program.."

...and then backs it by referencing an appropriate study...

"Gorla, Benander, and Benander found that the effort required to debug a program was minimised when variables had names that averaged 10 to 16 characters (1990). Programs with names averaging 8 to 20 characters were almost as easy to debug."

Graham Stewart on July 10, 2008 3:52 AM

re C++ code and making the enumerated switched

This is a classic Make a desert and call it tranquility* neophyte simplification, the kind of code that looks really neat when on display as a snippet, but is a nightmare to maintain in the middle of a piece of real code

Why on earth is it better to break the ontologically significant order in the enumeration to save a bit of scanning the text? Sure you get the unexecuted code up the top, but by having an enumeration in place you get the same movement through every time, you have a geography to the code that is the same every time you encounter the enumeration. It also helps followers-up on the code-base to know what to expect, and to spot egregious errors

moreover - doesn't that mean that for ALL of the code moved forward the ENTIRE switch gets traversed EVERY time? Why is that better than a lot of breaks avoiding the traversing?

*ob ref Tacitus atque ubi solitudinem faciunt, pacem appellant

Ivodne Galatea on July 10, 2008 4:44 AM

I tend to agree with most of the ideas and for the most part have practised something close for years without giving it a special name. When it comes to variable names though, I disagree, I've gone the opposite way because I think it improves clarity, avoids errors and allows me to use my IDE as it was designed.

Andrew McCall on July 10, 2008 5:34 AM

I tend to agree with most of the ideas and for the most part have practised something close for years without giving it a special name. When it comes to variable names though, I disagree, I've gone the opposite way because I think it improves clarity, avoids errors and allows me to use my IDE as it was designed.

Andrew McCall on July 10, 2008 5:34 AM

Graham: I am of course familiar with statistical methods. I am not sure they can be used here: unlike many other fields of science, experiments are very difficult to conduct, and the interpretation is very subjective. As a reference point, consider application of statistical methods to determine whether a certain protocol is better than another in treating a particular disease. The design of such an experiment is not trivial, and there are companies which make fortune just by doing that. But, the problems in doing a software based experiment are much much worse - and any change to the fundamental variables will invalidate the results: change of programming language, programming environment, debugging task, debugger tool, programmer training, underlying code, etc. It would be nice if we could run experiments of this sort. I am not so sure this is possible - but I will check out the references you provide.

What I am looking for is a method, which obviously exists in other disciplines, of reaching some agreement, without the usual bickering.
Such methods must exist in fields such as law, humanities, and other, non exact, non empirical fields of science.

Yossi Gil on July 10, 2008 5:43 AM

titrat: I am not sure I fully understand the implications of returning "-0". Do you say it may be less efficient? Or do you say it may lead to wrong results on some machines?

Yossi Gil on July 10, 2008 5:44 AM

> > 2) This works in C today, although it is only recently that compilers started allowing variables to be defined in loops.
>
> Hmm.. pretty sure this has been in since at least ISO/IEC 9899 (adopted by ISO in 1999) but I don't have the standard handy to check.

I suppose "recently" is a relative term. My first contact with C was in 1983. The reference book I still use for the language is copyright 1984. 1999 (and the subsequent adoption in compilers which would have taken a few years) seems quite recent to me.

> > 3) No such thing as a "private" variable in C...
>
> You can still minimise the "accessibility of variables" e.g. by using static variables.

Heh. Well, yeah. In most other languages this kind of thing (no program-global visibilty for objects not explicitly defined in an interface) comes out of the box. It didn't even occur to me that this would be considered a feature. But I suppose you could claim this for C if you really want.

It seemed to me this technique was talking about creating what we used to call "opaque types" ("private members" for you whippersnappers). C++ can do that with "private" and "protected". With C, no dice. The best you can do is declare the thing a void * and redefine it properly in the .c file (Security through obsurity). That's generally a lot more work than its worth.

T.E.D. on July 10, 2008 6:35 AM

The final refactored sendEmail is a much cleaner example of coding, but are Spartan techniques really the cause of this? Breaking the routine into smaller functions isn't some new method to achieve readable code. My problem with the code: !OO. Make the email message an object with appropriate properties and a Send method! Oh wait, what language am I thinking in?

Paul Schirf on July 10, 2008 6:50 AM

> name. When it comes to variable names though, I disagree, I've gone
> the opposite way because I think it improves clarity, avoids errors
> and allows me to use my IDE as it was designed.

I sent the link to the rest of my group here, and that was the most contraversial part for us as well.

Its possible that part of the problem is just confusion on our part. There's no explanation for "short names technique", and the link is broken. Someone more of an expert in wikis than I hacked the address manually and got a look at the page, but I'm holding out for it to get fixed (hint. hint).

What we came away with is that if it is a reaction to names like Electronic_Warfare_Tactile_Subsystem.Cockpit_Radio_Aids_Tacan_Package.Tacan_Output_Bytes_Written, then we'd agree. If instead it is an affirmation of names like fgwios (the gross weight of the aircraft, as a float, formatted for the Instructor Operator Station), I'm afraid we part ways here.

T.E.D. on July 10, 2008 7:03 AM

To Paul Schirf: I am glad you liked the final version (again, I am not sure how we should go about quantifying liking...).

The point here, which I should probably have stressed better is the following. Terse names, that is one or two letter names, make more sense if the context is small. Consider for example identifying an individual person. Within the small family cycle, a one syllable nickname would do. In a classroom, you may need to use the first name spelled in full: "Paul". When the individual is part of a larger audience, say, participants in a forum, you may need to write "Paul Schirf", and if you need address this individual among all citizens of a large state, you may need to write: PaulSchirfMaleOfPalmSprings.

The point is the following: the smaller the scope, the shorter the name. Conversely, if you strive for short variable names, you will be gravitating towards smaller modules.

There is another point to make here (eventually I will add this to the wiki): in the course of decomposition, you often come up with small, yet general modules. These modules often make terse names even more necessary.

In the "Paul Schirf" example, suppose you have a module with code designed to serve as back door of an application, e.g., by testing "if (user=="Paul Schirf") { do lots and lots of special things }".

Now, in decomposing the body of the conditional, one may come up with a small sub module designed to send a birthday greeting by email to the individual. I would expect a signature of the sort of,
congratulate(Person p)
to that module. Conversely, if the same code was inlined into the main module, you would more inclined in using a "verbose" name for the user to congratulate, by writing e.g.,

User backDoorUser = ...;
Message congratulation = ....;
send(congratulation, backDoorUser)

The point here is that the strive towards general, non descriptive names, is stimulates and is satisfied by good modular decomposition.

PS.
Others here may suggest using "congratulate(Person person)" as signature for the submodule, i.e., naming the parameter "person" rather than "p". I am interested in understanding better what makes people prefer the more verbose version in such a case.

Yossi

Yossi GIl on July 10, 2008 8:06 AM

> T.E.D. : Would you like to help in revising the C example? Would you mind if I used your suggestions?

I'd probably like to help in revising all the code in the world, but I don't think I have that kind of time. :-)

As for using my suggestions, that's what they were made for.

The way I see it, we are all in the brotherhood of software developers here (female readers included). It is our moral obligation to teach and learn where we can, and to try to leave behind code for our fellow brothers that come behind us that won't cause them unnessesary grief and time at work away from their loved ones. Our hope and prayer is that those who write the code we read will do the same. So rest assured that I'll be using any ideas I get from you all without shame.

T.E.D. on July 10, 2008 8:17 AM

Interesting that people here mention C++. I first used the term "Spratan Programming" in the context of C++ - and even gave a tutorial on the method in the TOOLS USA 1996 conference.

(believe it or not, there is an acronym behind the term)

The Wiki page was written to help my amazing students train with the method.

Yossi GIl on July 10, 2008 8:22 AM

While the smaller code sets create more understandable small variable names, they only do so because our brains can maintain contextual understanding across a few lines. That doesn't mean the small variable is more understandable; it simply means it can be understood.

private static MimeBodyPart makeBodyPart(final File f) throws MessagingException {
final MimeBodyPart $ = new MimeBodyPart();
final FileDataSource fds = new FileDataSource(f);
$.setDataHandler(new DataHandler(fds));
$.setFileName(fds.getName());
return $;
}

Is this really more readable than?

private static MimeBodyPart makeBodyPart(final File file) throws MessagingException {
final FileDataSource filedatasource = new FileDataSource(file);
final MimeBodyPart result = new MimeBodyPart();
result.setDataHandler(new DataHandler(filedatasource));
result.setFileName(filedatasource.getName());
return result;
}

Paul Schirf on July 10, 2008 10:55 AM

Rhywun, tk., and Graham Steward: Using a return object to "enforce
single return" is cargo cult programming. You're accomplishing nothing
and you're doing it because of an old misunderstanding of Dijktra's
and Hoare's "Structured Programming". One principle was "one entry
point, one exit point" but as soon as you have a changing return
object, you've already violated that principle (for all intents and
purposes) and you've reduced clarity.

There's nothing "goto" about early returns, quite the contrary.
(Unless you count lambda as the ultimate goto.)

Swedish Code-monkey: What is "readability"? I see this word, I hear
this word but there's never a definition. "Spartan programming" is
clearly defined with a number of metrics and practices, unlike
"readable code" which in my experience usually turns out to be a word
for redundant, overly explicit code.

Danish Rumani and j450n : Blocks are for more than one statement; i.e. when
you're using side-effects or state. If you're adding additional
side-effects to a conditional clause you better well be on the look
out for bugs, since that's something that should be done carefully, if
at all. To my eyes, every {}-pair means "Here be side-effects!"
similar to the exclamation marks in Scheme, and I use them
as sparingly. In your "PunishTheKiller" example, you've added
state-changing functionality.

Sunnan on July 10, 2008 10:59 AM

Well, maybe it is...

I still prefer the idea of making this an object. In doing so, the result is far more readable.

Daniel hit the nail on the head when he said "EXPLICIT getters and setters are noise, not signal". The language should support object.var = expression;

I also personally dislike case sensitive languages. Context in natural language rarely changes based on case. Oh sure, there are exceptions... and they obscure meaning.

Paul Schirf on July 10, 2008 11:05 AM

Paul Shirf: Yes.

Sunnan on July 10, 2008 11:09 AM

What is readability?

I've been in code reviews were non-coders were included to check for code readability. The idea is that, if the context of what is taking place in the code is clear to a non-geek, then its code that can be debugged easier in the future by coders who have incomplete understanding of the code outside of the routine they're looking at. And don't say that this isn't one of the benefits of OO! Encapsulate context/meaning!

Paul Schirf on July 10, 2008 11:12 AM

This looks pretty darn close to what McConnell advocates for in Code Complete, doesn't it? If not explicitly (although using enumerated types and case statements this way *is* explicit) at least philosophically.

Mark Kohalmy on July 10, 2008 11:48 AM

This post of yours, Jeff, had by far the most impact on me from everything that I have read for the last two months. Willing just to put link to the original post, I eventually ended up writing <a href="http://eterniel.blogspot.com/2008/07/spartan-programming-real-man-way-to-do.html">a full 3 page essay</a> about Spartan Programming and the ways to write programs like a real man (I'm sorry I borrowed your 300 spartans screenshot).
It was... very entertaining. Thank you :)

Gary Schubert on July 10, 2008 2:38 PM

Yo YG, the rzn ur wrng is vars 2 shrt is 2 hrd 2 read unless ur used 2 it. I call blsht.

Maybe you need to examine whether you are objectively considering that short 1&2 variable names are easier in general, or whether it's just easier for you personally. You must divorce your personal bias when making your recommendations because the recommendation needs be based on fact.

Code Complete provides reasoning backed up by studies (thks G). You need your own compelling, and scientifically valid data to contradict or at least call into question the results of the "Gorla, Benander, and Benander" research. Yes research is hard, but so what. Your assertion needs to be backed up by proof. Otherwise it's just opinion, and we've all got 'em.

Most people here, however, seem to disagree with you. So in this court of public opinion, you're wrong.

Not that you need to change, but just realize that what makes you happy isn't necessarily what makes anyone else happy. You have a hypothesis at this point, and nothing more. You've assembled and shared a list of personal preferences. Great, but don't pretend it's anything more than that!

Maybe rename the wiki to 'YG minimalist Coding Style for PHP which YG affectionately calls Spartan'

Also Note that I did notice in your final result you initially mention the Character Count and Token Counts as metrics, but you never tell us what the final result is, so what's the point? Seriously? These are pretty poor metrics to go by.

---

Is summation, I declare that calling something a programming 'style' belies the fact that it's just a collection of personal preferences. Code for yourself and code however you want. Otherwise code for someone else to read and maintain it.

RedGreen on July 10, 2008 2:44 PM

While I take full responsibility for giving html a try even though *no HTML* was clearly stated, feel free to write about non-rfc compatible and buggy auto-hotlinking in modern blogging platforms :)
Cheers :) And thanks again for the original post.

Gary Schubert on July 10, 2008 2:47 PM

Hi Jeff,
I read your blog almost everyday, and usually anything you post, has a bunch of links that give more information that what you state in your article.

This one was pretty disappointing, coz more than 50% of the content of this post, is from the source url. I am sorry for calling out on you, but as your reader, I have come to depend on your blog for daily insights into the work I do, and have hence come to expect more quality from you.

(I know my blog sucks, which is why I hard write and no one read it :) )

Shivanand on July 10, 2008 5:37 PM

lesscode.org

gonna leave it like that, but http://lesscode.org/about/ says it succinctly: use less code to get more done. It focuses more on the solution as a whole, rather than individual techniques in various platforms. Sometimes the bigger win is not to refactor a function or a file altogether, but the platform altogether.

angch on July 10, 2008 11:51 PM

Agree! There is no point to stuff in fat code for a lean task. If this is done so, then who else would want to jump in your code and learn from it? It might actually be better to rewrite everything if isn't so minimalist.

sweetperceptions on July 11, 2008 12:15 AM

Not to kiss-up to my professor, here's another way to examine terse variable names.

First, variable names are actually used for two purposes:
1. Specifying a name to access the area in memory (which isn't mandatory in C++ signatures, but is in Java interfaces)
2. Documenting the meaning of that variable

Just as you should prefer writing code that explains itself without comments, so should you strive for short and well-written methods that describe the meaning of the variables they use. An extreme case of this is Java's System.out.println(), where an entire group of methods have the same meaningless argument name "x".

Looking at this the other way around, terse variables are a kind of litmus test for method complexity: if you have many long- and descriptively-named variables (which are a mental-load on the person reading the code), it might mean that you should break-down the method.

And as for "shrt vars tht r hrd 2 read", @RedGreen, according to this style, variable names are either one-letter or the full word (plus "s" for collections). Never shortened names like you suggest, not even "msg"; either "message" or "m".

uv on July 11, 2008 2:23 AM

"The Spartan programming methodology *dictates* minimization of horizontal complexity [...]. This is because *it is believed* that horizontal scrolling is even more intellectually demanding then vertical scrolling. Further, *it is believed* that deep nested control is difficult to understand."

This guy is dictating to me based on a set of beliefs? Where's the evidence? Sounds like religion to me.

Thwock on July 11, 2008 3:06 AM

@Sunnan: > "Rhywun, tk., and Graham Steward: Using a return object to "enforce single return" is cargo cult programming. You're accomplishing nothing and you're doing it because of an old misunderstanding of Dijktra's and Hoare's "Structured Programming"..."

No cargo cult here. I can't speak for the others but I'm doing it for two reasons (neither of which have anything to do with Dijkstra):

1) it is the preferred approach in my company's coding standard. The standard contains wisdom from 20 years of writing code and sticking to it keeps our code consistent.

2) I'm also a member of the code review team and I know from my own experience that I find it easier to mentally parse and trace possible code paths in routines with a single return point.

Also, as I said before, I do sometimes use early-returns for establishing pre-conditions at the start of a routine (e.g. if param1 is null then return -1) or in very short routines (up to about 10-15 lines) where readability won't be affected. But generally I prefer to keep them to a minimum.

For the record, Code Complete 2 (Chapter 17.1, "Unusual Control Structures") has the following advice, which I believe fits well with my approach:

- Use a return when it enhances readability.
- Use guard clauses (early returns or exits) to simplify complex error processing.
- Minimize the number of returns in each routine.

Graham Stewart on July 11, 2008 3:32 AM

Personally my only reasoning for using single return points is when some memory is allocated or some library/structure/function is initialised that must be shutdown before exiting the function (e.g. fopen/fclose, CreateWindow/DestroyWindow etc...).

Here I also use that most heinous of all evils the "goto" statement. Its pretty much the one place I will use it...

In other situations I don't find it helps... it just makes an extra step when reading code, which may or may not involve using "Find" or a lot of scrolling about in a file in order to track what I think the code should be doing... I like to avoid these sorts of constructs, as much as they have little or no effect on the compiler or program output.

Jheriko on July 11, 2008 3:47 AM

@Jheriko:

So (based on your posts):

you leave member variables as public to save writing accessors; you don't use foreach or other language constructs that "hide code"; you avoid using existing frameworks; you write your own versions of basic library routines like strcat(); and you use gotos.

Man, I'm glad I don't have to review your code! :)

Graham Stewart on July 11, 2008 4:11 AM

Rather than Spartan Programming, I'd call it Laconic Programming. I know for a fact that the Spartans used COBOL.

Paul Schirf on July 11, 2008 6:43 AM

to Yossi Gil:
> Or do you say it may lead to wrong results on some machines?

Yes, for example the -0 could be printed as "-0", which could baffle some souls.

titrat on July 11, 2008 9:42 AM

tirat is right, it should really be:

return (x >= 0) ? x : -x;

Take a look at http://en.wikipedia.org/wiki/%E2%88%920_(number)

Graham Stewart on July 11, 2008 10:00 AM

Is it that it is spartan, or that one is taking the time to think it through and design it better. A bit of a mini code re-factoring if you will.

ss

StinkySQL on July 11, 2008 10:06 PM

Paul: You probably know that the term "Laconic" is after Laconia, the name of the piece of land were Sparta is located. In choosing the term "Spartan", I was referring to this meaning as well: Spartans did not talk much. But, also to aspect of their lives and training.

Graham: Thanks for the "-0" reference. Not sure how relevant this is e.g., what should be the absolute value of "-0"? And, in working with Java, this should not be a concern.

All: I fixed the link to "terse naming". And, the entry is too short... Still, my argument for one (or two) letter names is ONLY in the case that the variables are ***general*** instances of their respective types.
So, in

sendMail(..., String subject, String[] attachements) {
}

the names "subject" and "attachements" should not be abbreviated.

but in

traverseNode(Node n) {
}

the parameter name "n" is OK


Yossi GIl on July 12, 2008 10:29 AM

@uv - You're apparently a student, so I'll try to be nice.

1. Single letter variable names went out with Fortran.
2. While shortening variable names to 1 letter may in fact be a litmus test of complexity, it doesn't mean that leaving them in a short form is desirable nor good practice.

"if you have many long- and descriptively-named variables (which are a mental-load"
Which part is the mental load? Long names or to many vars?

Your 'spartan' rule for using a single letter variable is so seldomly applicable in real life that's it's a useless rule, and given it's frequency of occurrence, you're better off sticking to longer variable names to decrease cognitive dissonance.

It is also true that variable names that are too long and wordy, or if there are too many variables in a method (regardless of their length) are also a bad smell, and refactoring should be considered. That statement is nothing groundbreaking. Most of us already know that.

'Spartan' may be a cute name, but it's not a style, nor a methodology. It's collecting a few accepted refactoring patterns with a few pet rules for non-oo php programming.

---
[rant....]
I've noticed that Coding Horror more and more targets an uninformed audience when it comes to coding. Discussion tend to revolve around fixing other posters braindead notions, and certainly not anything like a rational discourse. Seriously - f'ing single letter variables. I feel like I've been trolled. I feel dirty. Talking about this makes me feel dumb.

Spartan is a Coding Horror. Coding Horror is a horror :(

Lift your head out of the muck and read some real books on programming. Talk about something cool like Linq, lambda's and closures. I don't care about xml config files or single letter variable names. That crap is just housework. Are you sweeping the floor, or are you building a skyscraper?

later

anon on July 12, 2008 2:22 PM

Interestingly, the web link to the wiki page on Spartan Programming specifically states that early returns are to be encouraged, as to reduce control code.

I know this isn't /., but c'mon, RTFA:
http://ssdl-wiki.cs.technion.ac.il/wiki/index.php/Spartan_programming

Loren on July 12, 2008 11:45 PM

This discussion highlighted the fact that the term "terse names" may be confusing to some, and people may think that spartan calls for obfuscating the code with short and cryptic names.

To clarify: names consisting of a couple of letters are to be used for GENERIC variables only. You write Message m = new Message(...) to denote that you are authoring a generic message. If the context is not sufficiently small so that "m" is clear to readers, then you probably should rewrite it to make it sufficiently small.

You write Message response = new Message(....) when you wish to compose a specific message, serving as a response.

Yossi Gil on July 13, 2008 3:22 AM

I cannot stand maintaining code with no descriptive variables. Java programmers are absolutely notorious for this idiotic behavior. It seems, particularly with the use of client side scripting visible to users who "View Source" that programmers intentionally make their code difficult to read and follow so that others cannot easily decipher what is being done.

And I also agree with those questioning the removal of whitespace. Whitespace is my friend. I refuse to write code that does not have whitespace for readability. If I am maintaining code, I always add the whitespace.

The maxim KISS should apply only to the complexity of what you are doing, not in the readability of the code. Descriptive variable names and readability whitespace should NEVER be altered and in most cased, should be added to existing cluttered crap. Keep It Simple, Stupid applies to using the least amount of variables and the lowest scope possible and the fasted method's for getting a given task accomplished. Spartan Programming does not mean make the damn code difficult to maintain or read.

Adam on July 14, 2008 9:32 AM

I also practice some of the principles of the spartan programming, but I don't know how good it is on those projects which won't have a 2.0 version, because thinking about how to write shorter and more elegant code slows you down.

Jeno on July 15, 2008 8:27 AM

I agreed with the Java email example, until the end, when he used $ as a variable name without explanation. That's just not right.

11011011 on July 15, 2008 2:18 PM

@Adam - I don't really know what side you're arguing for, or what your argument is for that matter.

smashmouth on July 15, 2008 4:21 PM

Probably the most pointless thing I have ever read. As a software contractor of 6 years, and 16 years development experience, if I ever worked with someone who says they use Spartan programming, I would move to have them fired. You are gaining nothing by "improving" code in this way, in these days of advanced IDEs with code templates and intelligent code completion. The emphasis should be more on readable, maintainable code. I read an article not long ago about lazy programming which made far more sense.

Hugh on July 16, 2008 1:30 AM

In case anyone is interested, I worked out another case of code simplification using spartan programming.


http://ssdl-wiki.cs.technion.ac.il/wiki/index.php/GnuParser_flatten_case_study

Yossi Gil on July 19, 2008 2:39 PM

I like it. I'm a spartan programmer too.

Luigi R. Viggiano on August 6, 2008 2:03 AM

From "code bloat" to "Spartan Programming" - Too much or too little, either is bad. Besides, the Spartans fought naked, covered in olive oil and not at all like that silly movie; olive oil is bad for my keyboard and mouse but the naked part is OK. :-)

What should drive code is architecture. Unfortunately, in today's slap-dash coding practices, the programmers usually back-engineer the code so that they can "explain" what they did to future programmers. No one wants to THINK any more - so they just start slinging code and hope that something good comes of it. Spidey Man isn't the only web slinger in the world.

SDG
jco

jco on August 6, 2008 6:43 PM

<a href="http://www.regltd.com" title="&#27880;&#20876;&#39321;&#28207;&#20844;&#21496;">&#27880;&#20876;&#39321;&#28207;&#20844;&#21496;</a>

idealpro志卓i on August 13, 2008 1:50 AM

thats new to me..im coming back for more acquaintance.

backyardni donglloyd on September 17, 2008 10:22 PM

Good !

metallic yarn on November 6, 2008 10:00 PM

to find many of the coding conventions I've settled on over the last 20 years http://www.paopaomoshou.cn

sillo on November 19, 2008 7:31 PM

This is the best coding technique which i am using for 15 years.

MASK on December 17, 2008 10:13 AM

god ,[url=http://www.youngsunblog.com]&#24037;&#19994;&#33258;&#21160;&#21270;&#21338;&#23458;[/url]
[url=http://www.hzpackmachine.cn]&#21253;&#35013;&#26426;&#26800;[/url]
[url=http://www.hzpackmachine.cn]&#21253;&#35013;&#35774;&#22791;[/url]
[url=http://www.hzpackmachine.cn/pro06.shtml]&#25171;&#21253;&#26426;[/url]
[url=http://www.hzpackmachine.cn/pro07.shtml]&#23553;&#31665;&#26426;[/url]
[url=http://www.hzpackmachine.cn/pro10.shtml]&#32544;&#32469;&#26426;[/url]
[url=http://www.youngsunpack.com]&#21253;&#35013;&#26426;&#26800;[/url]
[url=http://www.youngsunpack.com]&#21253;&#35013;&#26426;[/url]

包装机械 on March 8, 2009 6:28 PM

[url=http://www.youngsunpack.com/english/strapping.shtml]strapping machine[/url]

strapper machines on March 8, 2009 6:30 PM

good

包装机 on April 13, 2009 11:26 PM

The Avery Dennison line of labelers allows for a wide variety of different applications. Speeds of 30 meters (ALS206) or 40 meters per minute (ALS204) are standard but much higher speed models can be selected.
http://www.accentpack.com/products.htm?cat=11

label applicator on June 22, 2009 3:07 AM






(no HTML)


Verification (needed to reduce spam):


Content (c) 2009 Jeff Atwood. Logo image used with permission of the author. (c) 1993 Steven C. McConnell. All Rights Reserved.