Teaching good software design
Three years ago, I was asked by one of our teams to give advice on how they should write a parser for a structured file format. Just having read up on SAX again, I recommended that they looked into designing it as a push parser. A push parser works by the design that the parser generates events each times it reads parts of the input. These events are sent to an event handler, which then builds up the internal object structure or whatever the program needs. A push parser is a very object-oriented approach to parsing.
About a year ago, I took over the reigns, as it were, on this project. The strategy I had recommended had resulted in a horrible design. After having spent a total of a few weeks to fix issues with it, I finally gave up and rewrote it as a simple procedural parser. The rewrite took me three days plus about a day of fixing some edge case bugs. The resulting code was a tenth the size of the push parser.
This leads to my dilemma: As a senior professional, what should I do when I’m asked to give advice on software design?
Object-oriented programming holds the promise that technical people not involved in a project can understand the code in the project by understanding the structure. In my experience, this often leads to the disease of architecturitis. Architecturitis is the state of a program where important-seeming elements of the system are needlessly separated out from the rest, either as objects, or as distributed components. The result is that the program as a whole is less coherent. In order to understand what the program actually does, a programmer will have to understand many separate pieces with lots of plumbing between them. My temptation in order to avoid architecturitis is to say “just do what seems best to you”. This answer is also a non-starter. This sort of advice is useful for people who have lots of experience, but haven’t learned to trust themselves yet. But to those who feel lost at sea, something more substantial is needed. For the longest time, I thought that testing was the way to go. But writing good tests is really hard, and it’s a skill that doesn’t come natural to developers. Without the sufficient understanding and experience with testing, the advice to “start by writing the tests” will just result in developers not doing anything at all, or, perhaps worse, write tests that make the program harder to change. “Write tests first” is no magic bullet. But unlike the path of “architecturitis”, I know what to look for and point out in good tests. And I know how to practice getting better. Practice, then is key to learning. Hardly ground shaking. But in the software profession, we set aside very little time to practice. “Learn on the job” is supposed to be the only form of practice. Writing good code is a long path, and the practice of writing tests first provides a set of goal posts along this path.
Comments:
Marius Mathiesen - Jun 23, 2008
Being new to the term I had a good laugh; you just nailed it. It seems somewhat related to aesthetiritis, where a programmer (probably one new to, and sold on, Ruby on Rails) is so obsessed with making his code “beautiful” that it becomes totally ungraspable.
[Eivind] - Jun 24, 2008
There are a lot of deseases out there, for example architecturitis, analysis paralysis and big design up-front, just to mention a three. And why not add object-orientation itself to the list? It is much like eating and drinking, it may give you a lot of pleasure, but abused, it often results in a lot of pain. But that doesn’t mean that we should stop doing it, does it?
I think a keyword you mention here is “needlessly”. I use to teach that if you don’t possess the modelling and abstraction capacity required for doing good object-orientation, you’d better stick to the plain, old, structured way of thinkink. At least, that gives you something that is working in the short term, although perhaps not as modifyable in the future. Object-orientation and architectures are good for managing changes. At the same time, changeability implies complexity, so they ought to be kept at a minimum. In fact, we may make everything changeable, at the price of making is so complex that it is not changeable any more. That, may be, is a good definition of architecturitis.
Johannes Brodwall - Jun 24, 2008
Hi, Eivind
Thanks for another insightful comment. As you say: We shouldn’t stop doing object-orientation. My experience is that I should only stop recommending that others choose object-oriented solutions when asked for my input.
Trying to force people to use object-orientation (or testing for that matter) without proper understanding is probably not a good idea. With teaching tests, at least I know what to point to as good examples that won’t lead people astray. With OO… not so much.
[Trond Arve] - Jun 30, 2008
One piece of advice that might be useful in most situations is to start learning about your problem domain. Writing tests is a way to start learning. Working with examples you have to think about how your solution is to be designed and used by clients. Of course there are many more ways to learn, like drawing models on a whiteboard, discussing the problem with others or just start hacking. I tend to prefer tests, but I appreciate that testing requires experience and can be a hard path to follow. In any case, giving general advice when you I know the problem well enough often fails.
[Trond Arve] - Jun 30, 2008
A typo at the end, sorry: In any case, giving general advice when I don’t know the problem well enough often fails.
TelecommunicationS - Jun 10, 2009
Designing usable software is difficult, and teaching others how to do it is worse! Although useful methodologies exist, it is not possible to teach someone simply “how to do it”. To be capable of doing more than producing Microsoft clones, student designers need a broader approach to the task, one that has important attitudinal, aesthetic and creative components.