Design Patterns Isn’t a Golden Hammer

0 comments suggest edit

One trap that developers need to be wary of is the mentality of the Hammer Truism. This states that

When the only tool you have is a hammer, everything looks like a nail.

This is especially true of Design Patterns. I particularly liked what Erich Gamma said in this interview

Do not start immediately throwing patterns into a design, but use them as you go and understand more of the problem. Because of this I really like to use patterns after the fact, refactoring to patterns.

All too often, I’ve encountered code that uses a pattern because the developer felt he should use a pattern there, not because he needed the pattern.

Not every developer understands that patterns add complexity to a solution. Certainly abstraction and redirection are important benefits of many design patterns, but they come at a cost. To use design patterns effectively is to know when the benefits will payback that cost with interest.

The important concept to understand is that Design Patterns are descriptive not prescriptive. They aren’t intended to instruct how one should design a system, but merely describe successful designs that have worked in the past for common problems. Should the problem you’re tackling fit a particular recurring pattern, then applying a design pattern is certainly a good choice. But when the problem doesn’t quite fit one of the patterns, trying to cram the round pattern into the square design just doesn’t fit.

I’ve recently seen an example of this in regards to using an interface. I generally follow the rule of threes regarding polymorphism. For example, if I have a class with an enum indicating its “type” (for example, a User class with an enum property indicating whether the User is an employee or a manager), when that enum contains three values, I’ll consider refactoring the class to have a base class and inherited classes (for example, the User class might have an Employee subclass and Manager Subclass). Maybe I’ll use an IUser interface instead.

However, I caution against using an interface (or inheritance) just because it’s the “right” thing to do. There’s no point to implementing polymorphism if it is never used.

For example, I recently saw several classes in some code I was reading that implemented an interface we’ll call ISomeInterface. But nowhere did I find any code that referenced ISomeInterface. Instead, there were only references to concrete classes. I expected to see something like this somewhere in the code.

foreach(ISomeInterface something in SomeInterfaceCollection)

{

    something.DoSomething();

}

But no such code could be found. This was a prime example of a gratuitous use of an interface. This interface served no purpose and needed to be removed.

The important lesson here is to always start off by writing the simplest code possible and only add interfaces and design patterns when they are absolutely needed.

[Listening to: Voices (DJ Remy Remix) - Bedrock - Gatecrasher Global Sound System: Latitude (Disc 2) (5:13)]

Found a typo or error? Suggest an edit! If accepted, your contribution is listed automatically here.

Comments

avatar

11 responses

  1. Avatar for Barry Dorrans
    Barry Dorrans May 30th, 2005

    Ah pattern happiness. Just finished a mentoring project where they had jumped onto the pattern bandwagon way too much. Now it was appropriate in some cases, a base fund class with a factory created specific concrete implementations, depending on the type of fund it was. But then they had factories for things that will never change, for example a holding company. They were everywhere.



    I'm almost convinced patterns do more harm than good. They're not new ideas, they're just "branded", so everyone uses the same language. Well that's great, but damnit people stop presenting them as the new silver bullet.



    And don't even start me on the word "refactoring".

  2. Avatar for AC
    AC May 30th, 2005

    I completely agree. In fact, I think the best way I use design patters is by writing my application without consciously thinking about patters, but more about just making it work. Then I focus on implementing patters in the refactoring stage. This is just but one reason why I love Joshua Kerievsky's book "Refactoring to Patterns".

  3. Avatar for Jason
    Jason May 30th, 2005

    I agree completely!



    Another abuse of interfaces I've seen is defining an interface and then have one and only one implementor of the interface ever. For instance, an interface that defines a data class that is completely defined by properties.



    They do reference IUselessInterface elsewhere, but they could have just as easily referenced UselessInterface.



    I think that's why I tend to use abstract base classes if given the choice. Usually, I go about solving the problem at end with whatever is simplest, then wait for duplication and commonality to jump out at me before doing some "refactoring." :)

  4. Avatar for Niels Hansen
    Niels Hansen May 30th, 2005

    I agree totally with your statement. I think we have all fell into the design pattern trap. We've all have also done the same thing when we first learned to use inheritance and threads!



    I think its a human behavior to abuse new ideas and things.



    Patterns are very good but when your forcing a pattern into something that may not need it make no sense. I constantly have to remind my team of this when they are developing a new piece of code. Since we get paid when things are delivered I have to make it very clear that the most important thing is to deliver high quality software on time. If we do a good job and its delveried on time there is usually a good chance we will get repeat business and then can refactor in a pattern based on new requirements.





  5. Avatar for Scott
    Scott May 31st, 2005

    hehehe, I can only think of a couple of instances where I've conciously implemented a pattern. Most of the time I just write code willy nilly, then I look back and say "oh look, there's a decorator pattern." The only design pattern I think about before hand is usually the object factory pattern.

  6. Avatar for Pete
    Pete June 14th, 2005

    I wouldn't go confusing patterns with principles. Coding to interfaces is a principle that doesn't cost much and can mean all the difference down the track. Just think of it as a natural part of design. For more details and justification you could refer to Item 16 of Josh Bloch's Effective Java.



    Patterns are another matter, and should only be used where a demonstrated need exists. By all means hold back on them until refactoring.

  7. Avatar for haacked
    haacked June 14th, 2005

    Pete, I agree that coding to principles is a good thing, but only when those Principles are well understood and when they are not followed blindly.



    However, I don't believe every class should always have a corresponding interface. Sometimes, coding to interfaces can be abused.



    An interface is a strict contract to be consumed by a client who understands the interface. This provides the much lauded goal of Polymorphism.



    Ideally an interface should not have too many methods because it is a contract and once you define an interface, it is unchangeable. If you change the interface, you may end up breaking existing clients.



    Hence the reason you often see COM interfaces named ISomeInterface2 or ISomeInterfaceEx. The original interface wasn't enough and needed to be modified.



    However, why create an interface if the interface does not have ANY clients? And by client, I mean any code that uses the interface in a polymorphic manner. The extensibility argument is out because there is no extensibility point. Also, with no client, you have no idea if your interface is well factored. At some point, if you do add a client to it, you might be opening yourself to problems as the interface isn't well thought out.



    Sometimes, an abstract base class is called for. Sometimes a simple concrete class.

  8. Avatar for Developer
    Developer November 22nd, 2006

    Ah! At last! Thanks! This article put a bit of light in todays frustration at work.
    I work with another developer who has this "Patterns always and everywhere" mentality, and damn it I could not explain my idea, which is exactly what you describe.
    The result is that we have a myriad of classes to describe every single things, and a system that will never do even the simplest things just because it's too complex.
    I started thinking I was completely wrong and did not understand anything in OO design, luckily enough I found your article.
    I can go home happy now.

  9. Avatar for Documentation Nut
    Documentation Nut November 23rd, 2007

    What and Why of Design Patterns

  10. Avatar for binzhan
    binzhan June 1st, 2008

    ie 5 6 7

  11. Avatar for Johan Vorster
    Johan Vorster May 9th, 2010

    Well done! Great article and spot on with patterns.
    Trust me, if you design and write good code. You will satisfy a pattern some where some how. I have come across so many patterns that I've unknowingly implemented, only because the creator of the pattern and myself came to the same implementation conclusion.
    Create your own patterns that works for you!