Spartan Programming

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.

I simply had to comment on your post:

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

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.

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

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.

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

public static void SendEmail(
string vsFrom,
Liststring vsaRecipients,
string vsSubject,
string vsBody,
Liststring 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.

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

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.

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

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 ListString to, final String subject, final String body,
final ListFile 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 ListString 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 ListFile 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();
}

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

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

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

at least it’s spartanic …

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

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 …

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.

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.

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…

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.

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.