Monday, 10 September 2007

Do you GoF?

My first encounter with design patterns in action was a memorable one. It was about 10 years ago, shortly after the GoF book appeared and everybody who thought to be somebody was supposed to speak about it. I too pored briefly over the book, but was not a very dedicated student of it, and did it rather out of the sense of obligation. Not by any means to be able to solve a design-patterns crossword (yes, things like that exist in the vast open spaces of the web*)!

But what about the announced encounter? Well, there was a guy on the project I was in at that time, and he used nearly every pattern he could. The trouble was, his program didn't work! This gave me the first impression of the design patterns: it's something for weirdos, something to brag about, nothing for the people who really want to get the job done!

Then I have re-read the GoF book two or three times and found some of the techniques interesting, some not so, and some rather dull. Now, 10 years later, rather suprisingly for myself, I arrived at the opinion that I never really used the design patterns that much!!! I realized for example, that the much beloved patterns of the Java community** had never much appeal to me. For example I never used a factory pattern: why should I do it though? If I need an object, I simply create it using its constructor. Nothing simpler than that! In that way I never needed an Inversion of Control framework - I simply used Dependency Inversion, i.e. I parametrized the lower layer objects from the upper layer ones! I used the singelton pattern, but only to sort out the C++ problems with static object's initialization, not to ensure a single instance of something. If you need it once, create it once as Uncle Bob rightly said***. Ok, I must confess my sins: I used singletons instead of global objects :-((, but it was my laziness, and - yes, you guess it - nobody dared to gripe about this, as it was a "design pattern"! I never used the visitor pattern: it's simply too complicated, too confusing, and its variants (like asynchronous visitor) didn't make the situation any better. It's an "aha" moment when you realize that the visitor pattern is not about visiting but about adding new methods to classes!

An yes, I admit, there could be some problems where I'd use the abstract factory pattern, and there is always a problem where I will use the observer pattern, but here it is, my main point about GoF-ing: it is not that difficult to make out the equivalent solution on your own, really! Moreover, having a pattern given to you and ready to use (i.e. ready to copy and paste) is actually pernicious, as you won't have the deeper understanding of what you are doing, which can only arise from intensive occupation with the subject at hand. I know, the "deeper understanding" phrase sounds rather Harry Potter'esque, but I think it contains some truth.

So maybe the real value is that they establish a "pattern language" for the solutions of SW problems? I think it is so. You can refer to a portion of your code like "I use here an observer for this and a singleton for that" and don't have to describe the solution in detail - only its main idea.

Alas, the design patterns are presented to the developers rather as a catalogue of ready-made, off the shelf solutions to be copy-and-pasted every time you have a problem, or worse, every time you want to look smart to some other people. And this way they are stifling the creativity, stopping you from starting your own journey. But they were invented (if I'm interpreting Ch. Alexander's notion of architectural pattern correctly) to let you start your journey from a higher level.

PS: There is another opinion on design patterns out there: Mark Dominus maintains that a design pattern is really an indicator for a flaw in a programming language, i.e. that a language of next generation will make it obsolete. His example is the iterator pattern. I must admit I still haven't given it enough thought. On the other hand Rod Johnson makes a case again the design patterns as well - in this case again J2EE design pattens. He accuses them of being a mere workarounds for the design flaws of the J2EE platform.

---
* design patterns crossword: http://www.vokamis.com/products/cword/app/enterGame.php?ns=/a/a&or=V&h=128&pub=2&ex=http://www.softwaresecretweapons.com/jspwiki/Wiki.jsp?page=GangOfFourSoftwareDesignPatternsJavaScriptCrossword
** see for example Rod Jonson's book, Expert One-on-one J2EE Design and Development, Chap. 4: http://www.theserverside.com/tt/articles/article.tss?l=RodJohnsonInterview
*** Uncle's Bob blog: http://butunclebob.com/ArticleS.UncleBob.SingletonVsJustCreateOne

3 comments:

sothim said...

Concerning Factories, I found it worth a thought especially for C++ to avoid duplication of the template parameters:

From (example):
Sixtuple<A,B,C,D,E,F> t = new Sixtuple<A,B,C,D,E,F>(a,b,c,d,e,f);

to:
Sixtuple<A,B,C,D,E,F> t = Sixtuple.create( a,b,c,d,e,f );

thus deriving the type of the object to create from the parameters for frequently used classes..

Marek Krj said...
This comment has been removed by the author.
Marek Krj said...

Well, that's a good point. As far as I remeber, STL uses this pattern (factory function) quite liberaly:

template <class Operation, class T>
binder1st<Operation>
bind1st(const Operation& op, const T& x)
{
return binder1st<Operation>(...);
}

So we normally don't see the binder1st object and only use the factory function (function returning a functor and binding its first argument... how do you name it - a higher order function?).

08 January 2008 07:54