Recently, my friend Dan shared a thought-provoking picture of a quote by Martin Golding:
When I first started writing programs back in the Dark Ages (1980s), I wasn’t even aware that coding styles existed. Not only did I probably break every applicable rule in the Embedded C Coding Standard — my code was usually cryptic, terse, and would have been very very difficult to scale.
Nowadays, looking through my code library, I can almost tell when I wrote a piece of code, based on how it looks. Here’s an example of some of my oldest BASIC code that I could find: (The file, helpfully, was called “T.BAS”)
5 PRINT TIME$
10 FOR X = 1 TO 1000000
20 P = 1 / X
30 NEXT X
40 PRINT TIME$
This is Dark Ages code for sure. No comments or other documentation whatsoever, single-letter variable names (the only reason TIME$ is there is that it’s built-in), and LINE NUMBERS. Fortunately, this program is very simple, so it’s an easy enough task to figure out what it does. (It’s a very simple benchmark for a division loop.)
Here’s how I might write it these days:
‘Division loop benchmark test program (FreeBASIC)
‘Notes time to execute one million divisions of size double
‘M. Eric Carr / eric(at)(email address)
dim as double quotient
dim as ulongint curNum
‘Note the start time
print “Doing 1,000,000 divisions…”
print “Started at: “;time$
‘Run a loop of 1,000,000 divisions
for curNum = 1 to 1000000
quotient = 1/x
‘Note the end time
print “Ended at: “;time$
This is a little better. It’s still flat code (no subroutines or other hierarchical structure), but it’s simple enough that such structure isn’t really needed. The documentation and intuitive variable names make it much easier to maintain, the output now tells the poor clueless user what is going on, and the global variables are at least declared.
Here are some other helpful tips to make your code more maintainable:
- Use comments liberally. If it isn’t immediately obvious what a line of code does, document it inline with comments. In fact, it can be helpful to write the entire program in pseudocode, as comments, and then go back and fill in the mechanics.
- Use intuitive, descriptive variable names. A variable named “x” can mean many things, but one named “currentOutdoorTemp” is a bit more descriptive. When using a compiler, this has zero runtime cost — the compiler will translate the variable names into memory locations automagically, anyway.
- Use structured programming. If you have several pieces of information that belong together, consider using custom data types. If you have a program that is more than a dozen lines of code or so, it has probably become large enough to be split into subroutines. Doing so modularizes the task of programming, making the program easier to understand and far easier to maintain, modify, and scale.
- Along with the “structured programming” theme, use as few global variables as possible. They can be modified by not only the main code, but by subroutines, making it potentially very difficult to diagnose what is happening. For multithreaded applications, this becomes crucial; any global or shared variables will require good, solid mutexes.
- Don’t use GOTO statements unless absolutely necessary. These can often be avoided even when programming in assembly. (My own goal is to never use GOTOs, with the exception of a single GOTO at the end of the main loop, when coding in assembly.) GOTO statements can make code execution very difficult to trace.
…because all too often, the violent psychopath who will have to maintain your code — is YOU!