Thursday, April 20, 2006

3 Laws of Software Development

One of the most important things to come out of the after-work beer-fuelled pub braindump sessions with John is our "3 Laws", which we thought of as we reviewed what we did right and what we did wrong on our project. We have them pinned up in big letters in the office. Here they are:

1. Test First

Yes, yes. Everyone has been saying this for ages. There must be a thousand blog entries about Test-Driven Development and Extreme Programming. Of course we had heard about XP and I even own Martin Fowler's great book on refactoring, but to actually follow the principles of XP takes a crapload more self discipline than we have. So I'm not necessarily talking about JUnit tests here, but I definitely insist on heavy, if not total, automation.

The "project" we're working on is to replace a legacy system that does something we didn't know a lot about, written by a guy who left the company, with no written spec. This is the perfect problem to solve with Law 1, because the basic idea is that your test cases are the spec. And the beautiful thing is, now we do follow this Law, we can test the test cases by running them against the legacy system, before running them on the new system. Brilliant.

This approach has also been great for benchmarking the old system vs the new system, so we can say things to my boss like, "the new system is 30 times faster than the old one - see, here's the test results to prove it."

2. Optimise Last

Dr Knuth said, "premature optimization is the root of all evil" - and it's true. I got that quote from an excellent book about Java performance, which encourages continuous benchmarking (see Law 1). Another book I have about NIO makes the important point that these days software tends to be IO bound rather than CPU bound. (That means your program probably spends much much more time talking to a DB or to the OS about files or network, than it does calculating or manipulating memory.) That point alone implies that most of the time optimising algorithms gains nothing at all!

That doesn't mean that you shouldn't ever optimise algorithms of course, but you should only do it if these two conditions are satisfied:

  1. continuous benchmarking shows that something that used to be fast is suddenly very slow
  2. your profiler software finds a hotspot

Most of the time however, I have found that performance improvements tend to come from the architecture level. For example, if you discover your JVM spends a lot of time garbage collecting, then there's probably some leaky code or unnecessary data copying going on somewhere. Usually the fix for that would be a micro design change that avoids the need to copy that data.

3. Write Code for Right Now

The phrase "I think Law 3 applies" has become interchangeable with "we'll cross that bridge when we come to it" in our team. This is the anti-framework Law. Object-oriented programmers have a natural (and evil) tendency to write über-generic classes, in the name of code reuse. Code reuse is a good thing, but too often we write a generic, reusable class, and then use it only once. In extreme cases that reusable class evolves into a framework, which just makes maintenance harder because every time you change it you have to consider both how it will fix the problem at hand and how it affects the other imaginary users of the framework.

The other natural (and evil) tendency that this Law avoids is adding unrequested features, and fulfilling fictional requirements. Yes, the users might ask for Feature X next quarter, but they haven't yet, so let's just write the simplest possible thing that will meet the requirements we know about Right Now.

This can be a tough Law to obey because let's face it, you only think of disobeying it when doing so would be fun. If I'm finding myself extra tempted my usual trick is to jot down the technical idea I have on a post it note, and tell myself that if I finish the real requirements quickly I might have time to do it later. Of course I never have time later - but that's the point: there's no time to waste writing code that isn't needed.

Summary

3 is a convenient number of Laws because you can memorise all of them easily, but in truth we've never felt a need to add a 4th Law. These seem to be the key to everything. When we obey them, good things happen. When we disobey them, bad things happen. Simple as that. I hope they will be useful for other people too.

Tuesday, April 18, 2006

Happy Things for the Java Posse

My first techblog entry has to be about the Java Posse, since listening to them is what inspired me to start blogging about Java. I've never missed a single episode since the beginning and I've listened to some of them more than once!

I don't have a lot of time to read TSS or any other Java web sites, so these guys are basically my only source of Java news — but I'm pretty sure that's all I need. A lot of the time they mention stuff that I will then go and check out for myself, of course.

If you're a Java developer or architect and are too lazy to have clicked the link above, basically they're 4 guys in the states that are all seriously experienced Java architects and they scour all the news from the Java world each week and discuss the interesting bits. Although they agree with each other waaaaaaaay too much, it's really awesome to hear their opinions because they're really smart guys who know a lot about Java and software architecture.

But probably the best thing about their podcast is they get some incredible people on for interviews: Cameron Purdy, Josh Bloch, Jonathan Schwartz, Bruce Eckel, to name just a few. Unreal.

It's my life ambition to do something significant enough in the Java universe to be worthy of being interviewed on their show!