Archive for September, 2005

The Black Art of Good Design

Wednesday, September 14th, 2005

I’m willing to bet that any reader of this blog is likely to think of themselves as a savvy developer type who can, before breakfast, design any number of APIs, implementing said APIs, and swindle a bunch of people out of a ton of money along the way.

What has struck me recently however (beyond the fact that the above assertion is analogous to 90% of people claiming that 90% of people are stupid) is the orthogonality of coding and design.

There are a ton of developers who can write a mean algorithm. They can identify a problem and manage to digest the salient points with enough success to plop out an implementation that does exactly what it says on the tin.

Interesting enough though, this has sweet FA to do with design. Yes, the piece of software performs its function beautifully, efficiently, and one could argue, elegantly. That says absolutely nothing about its design.

Java, specifically, goes a long way towards ramming down a set of design principles. Said principles are followed fairly blindly by most practitioners. The OSS world is awash with examples of people who have read the right books, but have absolutely no skill or talent at conceptualising or grokking the underlying principles behind the books. To them, the design pattern is an end goal, not a tool. To pick one example (out of thousands), look at Matt Raible’s OSS efforts. It has inheritance! It uses PATTERNS! It is LIGHTWEIGHT! Yet, I’d argue that it’s very badly designed (if you don’t believe me, just try getting it to do anything other than the very very basics.)

So what’s the acid test for a good design? I have no idea. The closest I could come up with is A good design allows your code to do things you never expected it to have to do. It’s not about ‘oh I’ll add an interface here so I can plop in different implementations’ when there’s no sane reason you’d ever need more than one implementation, for example. Having made that assertion though, I’d imagine it’s pretty clear by now that I have no solution or fix. If you’re into that sort of thing, you can try befriending a fowlerbot, working your way to the top, then perhaps running your genitalia over his beard in the hope of getting some use out of the smug bigoted little fucker.

Another example (sorry Cedric) is TestNG. Cedric is pretty good at design, the code for TNG is on the whole quite good, but there are definitely some points where one could argue that bad design decisions were made. For example, there are interfaces for simple objects that have both getters and setters specified, which makes creating a read-only implementation pretty unpleasant. I’d also argue that putting getter+setter style methods in an interface is an implementation leak anyway, mind you. The upshot of this bad design is that the remote API for getting back TNG results is different to the local JVM API, and thus two sets of classes have to be maintained as a result of this bad design.

Another example is method ordering. There is currently a need for TNG to (internally) choose a different invocation order for the total set of test methods, but the design as it stands currently makes this change very difficult and tricky. Thus, another bad design!

On the other hand, there are plenty of other well designed areas which have been reused in some fairly unexpected ways, all of which points to decent design.

TDD for example has an interesting approach to design. It assumes, up front, that you can’t design your way out of a wet paper bag. You write tests that ensure the system does exactly what it’s supposed to do, nothing more and nothing less. You want to change things? You do it the brute force way by stomping all over your codebase and endlessly refactoring, it’s a lot more work but, in theory, any thoughtwanker can do it. Of course the downfall of THAT approach is that some portions of TDD STILL end up requiring someone intelligent, so you’re back to square one of needing someone smart, instead of swappable sweatshop bodyparts.

Yet at the end of the day, a depressing majority of java codebases look like a 3 year old had sat down in front of a large bucket of design patterns and plucked a fistful and hurled them in the general direction of some code. Proving that the tooling approach can, at best, only help the mediocre claw their way up to the average.