31 May 2014

The Template-Method-Antipattern

I had been skeptical about the GOF pattern book ever since I read it many years ago. Many of the patterns in the book seemed so trivial that I was irritated by how much attention they are given. Others have examples that seem overly simplified and never quite fit what actually happens in practice. Looking back now, I find that the premise of the book seems to be the early OO memes of "avoiding repetition" and "finding the right design for the application domain". The latter relates also to graphical modeling and model-driven-design. While those ideas are doubtlessly important, I think that early OO philosophy over-optimizes in that one direction and forgets about another very important direction: keeping the code as simple as possible. Instead of over-designing and already including space for "later extensions", realize that there are usually unknown unknowns and the later extensions might go into quite a different direction. It is the new agile world where running code and automatic tests are more important than fancy diagrams and great designs.

There are many guidelines which help us to write simpler (and thus more flexible) code. Before criticizing the template method even more, I want to remind you the two most powerful ones:

  • Number One law of procedural programming: favor pure functions over mutators. (And if you have mutators, separate them from the pure functions.) Note that this law fully applies to object-oriented programming as well!
  • Number One law of OO programming: favor composition over inheritance. (And let most of your inheritance be implementations of pure interfaces.)

I have always had trouble explaining why certain patterns were bad (especially those which over-use inheritance), but it was nonetheless very clear to me. I always found it hard to describe succinctly and precisely what the template does without going into the details of inheritance and the subclasses. Other people just didn't need this kind of clarity it seems. But yet, every time I had a debate with someone over a particular and specific piece of code I could convince them that my simpler variant was better in that particular case. So I am right in all cases, but still couldn't give a generally convincing reasoning why this is so.

Now recently I realized that rigorous unit-testing is a great way to validate a design: if it is hard to test, then that's a big smell and motivation to simplify! In a template method arrangement it is definitely hard (even though it's still possible) to test the template and its instantiations separately.

But instead of going on explaining what I find hard to explain, let's hear what others have to say:


Post a Comment