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.


This is a companion discussion topic for the original blog entry at: http://www.codinghorror.com/blog/2008/07/spartan-programming.html

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

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 Geisendrfer 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.

Well, not I have to disagree. :slight_smile:

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.

Nice post

@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.

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.

@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;

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. :slight_smile:

How many Jr Developers have been dropped off the mountain?

Come home with your keyboard or on it.

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 :wink:

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

@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.

…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.

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.

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

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.

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.

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!

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!

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
}