Posted 15 Mar 2001 at 18:27 UTC by Bram
Software engineers suffer from not knowing what their code should look like. The classic essay worse is better exemplifies this - How can worse be better? Isn't worse worse? Even more confusingly, it's generally referenced to claim the exact opposite of what it's trying to argue.
The problem is that people use very different, and often antithetical, criteria to judge the 'beauty' of code. Clearly there is a need for a measure of code quality which is more objective than aesthetic.
I suggest that you judge code based on it's maintainability.
Truly maintanable code is flexible and can be taken in many directions. Code is not more maintainable just because it has more features - invoking functionality which is currently dormant is not maintenance, it's use. Maintenance is when you add new functionality or change existing functionality. This is often done long after the code was originally written and in a completely unforseeable manner.
Planning for the unexpected is a paradoxical concept - if you don't know what it is, how can you plan for it? Thankfully, there are many concrete techniques which work.
Use less code
The less code you have, the less there is to maintain. You shouldn't slavishly count characters or lines of code in your program and reduce it at all costs, but generally speaking, less is better. Get rid of unused functions and diagnostic statements - they're just more muck to wade through.
Using existing libraries, of course, results in less code. In practice, many libraries so low quality that you're better off rewriting them, but many aren't, and you should use those when possible.
Encapsulate
If you create well-defined boundaries which are only connected by narrow bridges, you can rearrange entire towns with the neigbors being none the wiser. If there's too much travel going on, even a single eviction can cause widespread panic.
Reduce preconditions
Code which is very persnickity about how it's invoked makes everything else harder to maintain. Examples are requiring that methods be called in a certain order, and requiring that a certain method be called only once. Try to avoid those.
Write in an easy to maintain language
My favorite language for maintainability is Python. It has simple, clean syntax, object encapsulation, good library support, and optional named parameters. An example of a language which is terrible for maintainability is Perl. Yes, I said it. No, I'm not going to back down.
Write test code
New code always runs the risk of breaking something. A test suite which is easy to run and either returns 'everything passed' or 'these tests failed' makes it very easy to detect and fix regressions. Test code has to be changed much less often when it tests interfaces rather than implementations. For example, code which turns objects into strings and back again (known as 'pickling') can be tested by pickling and unpickling an object and comparing the result with the original. Those tests will continue to work even if the string format is completely changed.
Create tools
There are two ways of building a barn - one is to make a hammer and use it to nail the barn together, the other is to nail it together with your hands. They might take about the same amount of time, but the hammer will help you again in the future.
Use safe techniques
There are several techniques which result in more maintainable code under almost all circumstances. Garbage collection magically removes all the headaches of memory allocation. Monothreading gets rid of all the headaches of thread safety. And don't forget the first rule of writing internet applications - 'Don't re-implement TCP/IP'.
Let yourself get frustrated
Many times I have gotten frustrated doing something the 'right' way, figured 'fuck it', and done something simpler and more expedient. Sometimes it turns out to be a hack, but often it turns out to actually be a more flexible solution, for the very reasons I got frustrated by.
A word about performance
There's a rule of thumb that 1% of the code takes up x% of the actual runtime, and in recent years x has been increasing dramatically. Combined with how much cheaper fast machines are than developer time, this means that performance is much less of an issue than it used to be. Sometimes it makes sense to work on better performance, but it should be viewed as a feature like any other, not an overriding principle to build software around. Maintainability works much better.