Spartan Programming

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

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

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.

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.

ANSI-C to T.E.D. What’s a namespace?

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

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

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

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

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…

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

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.

Can everyone stop? Quit sending code snippets?

PLEASE BE SPARTAN IN YOUR COMMENTS.

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.

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.

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?

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.

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

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

Correction:

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