Wednesday, May 13, 2009

Patterns (programming)

[skip this post if you're looking for news on my game Polynomial]

Design patterns remain to be a hot topic in programming. After much consideration, I decided to hop onto pattern bashing bandwagon with some hopefully original arguments.

First, what exactly is a design pattern in programming? Wikipedia: "a design pattern is a general reusable solution to a commonly occurring problem in software design." That's good, but watch out: "A design pattern is not a finished design that can be transformed directly into code".
That's it, pattern is like c++ template class or lisp macro or c# generic, but written in English and instantiated by hand. The very antithesis of reuse. Only in technical writing you can actually refer to some English description and thus reuse a pattern.
Manually duplicated functionality is bad. It beats having no functionality, but it is still far worse than truly reusable, finished design. You should try to find or make finished design rather than just duplicate things by hand. Maybe even switch to programming language which is expressive enough for such reusable solution, or if you're some real smart fella, invent your own programming language.

But if patterns are bad, what's about design pattern books, you might ask? Surely, those are written by people who know it all? [I don't think so, but well, I'll take that as true]

Thing is, the best selling programming books are not the technically best books. It is the book that makes you feel better about yourself that sells well. Design pattern books fail squarely in this category. You read such book, and you feel good and smart that you previously (re)invented many solutions to common problems; and it does not make you feel bad that you did not make your solutions truly reusable. And since it made you feel good you go on preaching, same as for bible or other religious meme.
Sure, the book can be very informative - after all it does contain list of solutions to common problems (which you might not even recognize as problems requiring a solution) - but those solutions are unfinished and are not reusable from programmer's perspective; you're better off with a library like boost that implements those things in reusable way.

The worst part is advice to new programmers, "do patterns". No. Use a language which is powerful enough to express solutions to common problems, so that those can be transformed directly to code; ideally, with libraries rich enough so that you won't have to reinvent wheels. Do pattern only when programming language does not permit you to reuse one solution.

To add real life example here. In my projects, I use "observers" a lot. Observer is something that watches a variable and is notified by changes. Long ago, my programs typically would have code that was observing keyboard state, other code that was observing textbox value, and so on. That's following observer pattern. When it started becoming a pattern, I made few template classes for data, events, and observers, and refactored most of the code, which allowed for greater flexibility and interoperability between components, as well as cut down the code size. I still use observers, but no longer as pattern - I just use observer and observable templates instead. [edit: by templates, I mean, specifically, C++ 'templates', a powerful language feature for writing that sort of stuff just once. Not some ctrl-c ctrl-v edit edit. If you're using C# you can use generics, if you're using lisp you can use "macros" (and do it in a zillion ways), and I heard even Java has generics now too]

2 comments:

  1. Well, you're still using the pattern. You implemented it in prepared code pieces, but that doesn't mean it is not still the same pattern.
    A pattern is just this: an advice on how to implement a common problem.

    But I agree that some people hype them too much. Some schools almost make you believe that the more patterns you know by heart, the better a programmer you are.

    ReplyDelete
  2. Well, a definition of pattern explicitly excludes complete reusable implementations. I'm not cut-n-pasting prepared piece of code, either.

    To give another example, if you're programming in C, you can only do object oriented programming as a pattern (using vtables manually). If you use language such as C++ that is built-in, and does not require a pattern anymore.

    ReplyDelete