Mantras for software engineers
There are certain aspects of software engineering that are so close to being
fundamental truths that all developers should have to repeat them to themselves
10 times per day and twice on Mondays. They are independent of language, operating
system and whatever editor or syntax highlighting scheme you hold sacred. If you
keep these in mind, at least the worst errors are less likely to come up and bite
you in the bum when you aren't expecting it. Here's an attempt to write some of
them down: since I'm a very fallible person this list is bound to be incomplete
and (horror!) possibly even misguided. Let me know.
-
Don't make one entity try to do more than one thing.
This is so important, and so often ignored that it defies belief. Objects can
do many things, but their components should only do one thing. The best historical
example I can think of is that of old-school stack push-pop operations (which
were firmly engrained in programmers' and computer scientists' conciousnesses)
meeting the new world of threads and exceptions: it was eventually noted that pop
could never be an exception-safe operation specifically because it reads and
modifies the stack at the same time. Modern implementations of pop tend not to
return the top of the stack — they only throw it away — am aesthetically
nice solution is the explicit addition of a "peek" function. The moral lesson:
atomicity is good. This example also has the nice feature that
is shows how working with legacy code and engrained ideas can tie you into a world
of pain, which can be fixed by taking a step back and thinking about how things can
be simplified.
-
Keep it simple (stupid).
Just because you can overload operators doesn't mean you should. Just because
you could do the whole thing with one regular expression doesn't mean you should.
Just because you could do it in Perl doesn't mean you should :-) In short,
you or someone else will one day have to come back and re-hack code you wrote
in the distant past: don't make them reverse engineer your cool tricks when
"wasting" another carriage return would have made it clear as crystal. Good
developers know when not to be clever.
-
Introduce version tags early
With successful projects, you may end up with several versions of your library /
file format / whatever "in the wild" at one time. If you didn't provide a versioning
tag with your first release version, you are then in the nasty position of having
to determine which version a given instance is by the absence of such a
tag. Yuck. This makes handling "schema evolution" and related topics much harder and
a great dela messier. So think about version tagging right at the start... otherwise
you'll end up wishing you had access to a time machine (and that's an even harder
problem!)
-
Comment your code
Do I even have to elaborate? Okay, one elaboration: comment your code for use
by an automated documentation system like Doxygen, epydoc, pydoc, JavaDoc...
-
Modularise agressively...
... but not too agressively! It all gets very Zen when you think about it: the
key to success in most endeavours runs along the lines of "strong but supple".
A series of near contradictions, whose solution is the thin line between
success and failure. Well, that's rather pessimistic — the line isn't
that narrow and there are always shades of grey confusing the neat black and white
picture — but you get the idea. Provide a function if you can use
functionality intwo places in your code. Provide a new module/package if you
have substantial functionality that can be used outside your project.
-
Hide complexity behind interfaces
Operate a "need to know principle". Interfaces are the key to this: a developer
should need to know what to put in, what comes out and maybe some commentary
on efficiency and alternative approaches. They shouldn't need to know how
in detail your code achieves its specification.
-
Before you start, see if someone else has already done it
Yes, I know your idea is so brilliant that it would take one person in a
million to come up with it. There are millions of technical people, there is
the birthday theorem (telling you that collisions occur with roughly the
square root of the single event probability, so that one-in-a-million
really becomes one-in-a-thousand). Chances are someone else has already
made a start. Help them or use their work rather than learn their lessons twice.