I chose this to be the second lesson because I feel this is one of the things I learned through experience. It’s the basis of many many other lessons.
So what does it mean to be paranoid about your code? While you’re writing code, for some strange reason, you have this false confidence that it will work. It’s false because it’s statistically impossible to write code that works the first time. Consequently, you have to assume that everything you write will fail.
Sometimes a failure is not bad – it depends on what you’re writing. If you’re implementing a word count feature for a document editor and your code causes the editor to crash, then there’s always auto-save that will give the user his latest changes minus the last 2 minutes or so. But if you’re writing the auto-save feature for that same document editor, your feature can ruin big, important documents that belong to clients who will never buy software from you again.
In practice, being paranoid about code means that you should check every return value from every function and exit error situations as gracefully as possible (the optimum being working in a transaction-like manner). Include sanity checks and assertions as much as you can, so that during tests your code will crash early instead of dragging an error to the point where it can’t be found.
Both advices, “crash early” and “anything can fail”, are well known in one form or another. Today they seem obvious to me, but I first read them in a book called “The Pragmatic Programmer”, which is a great read for developers at all levels.
Great post. I’d also add that usually these sanity checks cost nothing, i mean NOTHING with regard to performance. Do not save those nanoseconds unless you REALLY REALLY REALLY have too. In other words “We should forget about small efficiencies, say about 97% of the time: premature optimization is the root of all evil.” (from http://en.wikipedia.org/wiki/Code_Complete)
What about static/dynamic analyzers?
Are you aware of this: “Sorry, you can only post a new comment once every 15 seconds. Slow down cowboy.”?
No, I wasn’t aware of it :) Nice touch by the WordPress people (I also fixed up your comment).
Luckily, I also have the Akismet plugin which filters spam, so you don’t see any crap here.
Static analysis can only go so far, I believe. Imagine a program that is supposed to run for a week non-stop and there’s a bug found 3 days after the place in the program where it originated. It is not related to static correctness, but to a logical mistake.
Dynamic analysis is great. I love Insure++ (http://www.parasoft.com/jsp/products/home.jsp?product=Insure) and Purify (http://www-306.ibm.com/software/awdtools/purify/) but these tools change your program’s behavior in the sense that they change program timing so you might not encounter the bugs if they are related to race conditions.
Another things is that these tools emit so many “possible bugs” it’s sometimes hard to distinguish real problems from non-issues. I usually use them when I see some kind of corruption (e.g. memory overrun), which is a classis case where these tools help.