Defensive Programming Published Fri Mar 20 02:00:00 SAST 2015
For every few lines of code I write, I will introduce a certain number of bugs. The rate at which I introduce bugs will vary by project, complexity and sleep deprivation, but one thing is certain: there will be bugs.
Over time, I have adopted a principle to minimise bugs and compensate for my own stupidity and ignorance. I call this principle defensive programming[^1].
I started writing this essay two years ago, but it was not finished without a concrete example. That is, until I read On Toolkit Dialogs by legendary Jamie Zawinski, in which he describes how a crashing GUI bug in a screensaver daemon could bypass security:
[As] a critical piece of security software ... any bug in the screen locker that causes it to crash will cause the screen to unlock.
Let's suppose that down in the bowels of some particular version of some particular toolkit library, there lurks a bug. Let's suppose that the nature of this bug is something relatively obscure: say that it's something like, if you hold down 5 keys on the keyboard for 10 seconds then drag the middle mouse button, the text entry widget gets a SEGV. (In fact, I'm not making this up: I saw this very bug once, years ago.)
Hm. I've written bugs like that. He continues,
Bugs like that will exist in GUI libraries; it's inevitable. The libraries are big, and do many different things.
One way to protect against that problem is to keep the number of libraries used by the xscreensaver daemon to an absolute minimum. That's why I implemented the unlock dialog using only Xlib. The amount of code in Xlib is very small, and has been extensively security audited.
To me, this practice exemplifies defensive programming. After working with many younger and more talented programmers than myself, the key difference underscoring my experience has been their unconscious incompetence compared to my conscious incompetence.
What else can we take from this?
- Explicit code is better than implicit code
- Less code means fewer bugs
- Minimise dependencies
- Minimise coupling
- Avoid toolkits for crucial infrastructure
You see, I know how bad of a programmer I am, and I think that makes me a better software engineer.
[^1]: There is a related article on Wikipedia with the same title, but it describes a different practice.