Design Patterns: Still controversial


I recently read a classic book: the GoF Design Patterns. This is one of the most known yet one of the most controversial books in our industry. This is one of the buzzwords that pop up at job ads and during job interviews too. On the other hand, many developers just hate them. They say that when they used design patterns then they ended up with code that was more obfuscated than ever before. Sometimes they say that there aren’t any design patterns in dynamic languages. (This book documents some of those patterns.)

Peter Verhas uses a great metaphor here: whether a design pattern is a good thing or a bad thing is the same question whether guns are good or bad. As it’s not the guns but it’s the people who kill, it’s the people who misuse (overuse, abuse) design patterns. Yes, people do that all the time. Yes, sometimes I do that too.

Still, I think that design patterns are a Good Thing ™ . I didn’t always have this opinion though.

So, what’s wrong with them?

Let’s suppose that something is wrong with design patterns. What would that be?

1. Complicated

First of all, design patterns are complicated. Each design pattern starts with an “intent” section, then, after some pages, they introduce many new classes. Later it’s hard to tell which classes belong together thus it’s difficult to guess their reason. Worse, there are alternatives for each pattern. Moreover, each pattern has drawback, like when you shouldn’t apply them. Well, the Design Patterns book is definitely not a Silver Bullet.

Say, you still want to learn them. There are many introductory materials in this topic. They promise you a quick-and-easy way to learn the patterns. They say they will be more interesting than an IRS sheet. Unfortunately, these resources are not quite complete. Sometimes they present the patterns out of their context. Or they show so much context that they have no room for most of the catalog.

2. Make the code more complex

Unfortunately, that’s right. Design patterns introduce new classes and interfaces thus they increase the conceptual complexity. Sadly, the application is complex too. The question is whether the actual design patterns you have are pulling their weight or not. Sometimes they do, sometimes they don’t.

But, wait! How exactly do they pull their weight? One phrase from the GoF book is “encapsulate the concept that varies”. I believe that’s another way of saying SRP.

What’s SRP?

E.g., you have a widget where the users can type in some text and the widget formats it. But, there are many formattings out there, like formatting integers, formatting money, etc. One way of doing it would be using just one switch statement. OK, maybe two. The other way is to use a formatter, for instance, a NumberFormatter or a MaskFormatter along with your JFormattedTextField. The former solution uses more and more switch statements. The latter one is an example of the Strategy design pattern. OK, it’s a bit hairy example, but let’s complain about it later.

It turns out that the second example is easier to extend. It is so because there is one class for accepting text input and displaying it to the user; and there is another class that knows where to insert the extra characters. That’s it: each class does one thing and it does that thing well. (Well, JFormattedTextField uses other patterns too. Name as much as you can so you can win a Túró Rudi). So you have more classes, but those classes are easier to understand.

3. It’s hard to tell when to apply them

Well, that’s right. As the TMMM says, there is no Silver Bullet. We still have to think. Design Patterns offer several concepts that we can apply. Beware! Each pattern has a part called “Applicability”. In that part the authors enumerate the circumstances when the pattern is for your benefit.

At the “Consequences” part they weigh the pros and cons for the pattern: what you win and what you lose with each of them. Unfortunately requirements change. A pattern that served well for several months might be in your way later.

Moreover, when you design your code with certain changes in your mind, requirements might change another way – which your current solution doesn’t support. Well, you over-engineered your project. Don’t worry, it happens to everyone. It’s just unfair to blame the patterns for this.

4. Sometimes you just can’t tell them apart

Have you ever wrap a file reader into a buffered reader? I mean something like this:

BufferedReader br = new BufferedReader(new FileReader(""));

This might be a Decorator as the BufferedReader buffers the bits of the FileReader. It also might be an Adapter as it adapts the FileReader to a line-oriented interface.

Have you ever wrote an interceptor? Well, the container just created a Proxy Object for you. Some sort of proxy that does its thing, then delegates to the wrapped object. Did the container create only a wrapper for you? Who knows?

Here it is. Patterns and their names are sometimes confusing. Using patterns and their names consequently won’t save you from talking to your co-workers. Here we are, communication is inevitable. Patterns won’t and shouldn’t spare you that.

5. Patterns are unnecessary in dynamic languages

One could say that patterns are unnecessary in dynamic languages as it’s easy to write flexible code with closures and dynamic typing.

In fact, the more freedom you have the easier it is to create a mess. I know, you won’t do so because you use TDD and you already write short methods even when you have to hurry. (That would be nice, wouldn’t it?)

Still, the dynamic languages don’t eliminate the need of design patterns. They just implement a few of the for you. Say for instance whenever you write things like

names.each { |name| puts name}

then you are passing a Command object as a parameter.

If you learn JavaScript then soon you’ll know that instead of inheritance they use prototypes. But, if you take a closer look then you’ll see that you can create objects with functions. Well, you can refer to them as Factory Methods. There is a design pattern for either of them.

But, wait! You said patterns are great!

That’s right. Patterns are great, for many reasons:

1. You can use them as a bag of tricks

Hell, yes! Design Patterns show you many examples how to change behavior dynamically; how to create complex object and many more. They are somewhat complementary to the SOLID principles. While SOLID teaches you how to recognize good object-oriented code, Design Patterns show you examples on how you can write them. (Apart of practicing TDD, of course.)

As, for each trick you can check the Applicability section to make sure you choose the right trick for your problem. Moreover, you can check the implementation section for variants of that pattern. E.g. there is a variant of the Command pattern that supports Undo, and there is another that doesn’t. These examples help you to write your custom variant – the one that fits your actual problem.

2. They help communication

You could describe each pattern with your own words. Like “here we can use a simple interface with a do() and undo() method and the caller can pass an argument as an implementation of this interface, so our code will be orthogonal”. Or you could just say “This is a good place to apply the Command pattern.” You can even use this name in your code, like “FooCommand {…}” so whoever reads your code will know your intent with that class.

That’s it: design pattern provide names for recurring solutions.

3. They make you write better code

There is a mantra through this book: “Encapsulate the concept that varies”. This is pretty much the same as the SRP: One class does one thing and does that thing well. For other things, e.g. for other algorithm we use another Strategy class.

Moreover, almost each pattern introduces an interface or an abstract class. Depending on them means that you apply the Dependency Inversion Principle. If you use the patterns carefully then you apply it whenever it’s appropriate.

Then, why are patterns so deeply misunderstood?

Well, patterns are abstract and fairly complex. They are definitely not for beginners. Still, a greenhorn can learn them, one step at a time. This is how they could do it:

1. Learn refactorings.

Martin Fowlers refactoring book is an inevitable volume to read. It touches the basics of software development: we have to improve the design of existing code. We have to do so either because the code is messed up or simply because the requirements changed. Either way we have to change our code in small reversible steps without making any functional difference.

One shocker in that book is that it depends on unit tests. This is a big motive to write them, isn’t it? The other thing is that it shows how much one can do with those small steps.

The refactoring with method object prepares you to meet the Command pattern. When you replace conditional with polymorphism or you introduce a Null object prepares you to the State and Strategy patterns.

2. Observe patterns and anti-patterns in your code.

I think you already have some patterns and anti-patterns in your code. I think you have both. (At least, I do.) If you claim not having anti-patterns then think about it: maybe you just haven’t recognized them Or your code is trivial. Don’t worry, every programmer implements anti-patterns. You just need to recognize them as soon as possible.

What you need to do at this stage is this: while coding, reflect a little on what you are doing. Reflect on the solutions in your code base. Evaluate them: which parts are easy to understand and which are difficult? What modifications yield to more unexpected errors? What is really easy to change? So you get some experience.

3. go through an introductory design patterns material

This is important too. After some time you can try to deliberately apply design patterns. Just do it carefully, and check whether they help you.

4. Read books like Effective Java / Effective C++

Every language has its own idioms. Learn them for your language. Those idioms are pretty much like patterns, except that they are less abstract.

Once you are familiar with them then you are already applying some design patterns. Sometimes the naming is deceptive though. Say for instance, the Effective Java starts with “Static Factory Methods“. The design pattern catalog calls them “Singleton”. The Factory Method is a different pattern.

5. OK, now you can read the GoF patterns book

Already got here? Did you already spent years as programmer and just kept learning? Good job! I think now you can read the GoF Design Patterns book. At least, this is the stage when I read it. Reading it was like having a constant “Now, I get it” feeling.

About these ads

About tamasrev

A software developer, specialized in Java EE, addressing himself as generalist. A proud daddy. Owner of 1.25 cats.

2 Responses to Design Patterns: Still controversial

  1. thenewphalls says:

    It’s definitely important to know when and where to use a design pattern. Some people will write elaborate code so that it can easily be abstracted away or modified in the future, for very simple tasks that would otherwise take just a few lines of code and will probably never be changed anyway – meaning that more time is spent on planning, writing and testing all those interfaces and factories and what not than will ever be saved making modifications in the future. However, some code does need proper design for maintainability, modularity, scalability, etc. The trick is in developing a sense for when a piece of functionality needs to be designed properly from the beginning – or whether it can wait and be refactored later.

  2. Peter Verhas says:

    Very good article. I was a bit worried where you will land but at the end it was OK. :-D

    I value especially that you give links to the terms you use so it is only one click away for the readers who are not familiar with one or the other (e.g.: TMMM as an abbreviation did not ring a bell for me).


Leave a Reply


You are commenting using your account. Log Out / Change )

Twitter picture


Facebook photo


Google+ photo


Connecting to %s