Design patterns to avoid

A lot of people seem to agree, that the Singleton pattern has a number of drawbacks and some even suggest avoiding the pattern entirely. There's an excellent discussion here. Please direct any comments about the Singleton pattern to that question.

My question: Are there other design patterns, that should be avoided or used with great care?

--------------Solutions-------------

Patterns are complex

All design patterns should be used with care. In my opinion you should refactor towards patterns when there is a valid reason to do so instead of implementing a pattern right away. The general problem with using patterns is that they add complexity. Overuse of patterns makes a given application or system cumbersome to further develop and maintain.

Most of the time, there is a simple solution, and you won't need to apply any specific pattern. A good rule of thumb is to use a pattern whenever pieces of code tend to be replaced or need to be changed often and be prepared to take on the caveat of complex code when using a pattern.

Remember that your goal should be simplicity and employ a pattern if you see a practical need to support change in your code.

Principles over patterns

It may seem like a moot to use patterns if they can evidently lead to over-engineered and complex solutions. However it is instead much more interesting for a programmer to read up on design techniques and principles that lay the foundation for most of the patterns. In fact one of my favorite books about on design patterns topic stresses this by reiterating on what principles are applicable on the pattern in question. They are simple enough to be useful than patterns in terms of relevance. Some of the principles are general enough to encompass more than object oriented programming (OOP), such as Liskov Substitution Principle, as long as you can build modules of your code.

There are a multitude of design principles but those described in the first chapter of GoF book are quite useful to start with.

  • Program to an 'interface', not an 'implementation'. (Gang of Four 1995:18)
  • Favor 'object composition' over 'class inheritance'. (Gang of Four 1995:20)

Let those sink in on you for a while. It should be noted that when GoF was written an interface means anything that is an abstraction (which also means super classes), not to be confused with the interface as a type in Java or C#. The second point principle comes from the observed overuse of inheritance which is sadly still common today.

From there you can read up on SOLID principles which was made known by Robert Cecil Martin (aka. Uncle Bob). Scott Hanselman interviewed Uncle Bob in a podcast about these principles:

  • Single Responsibility Principle
  • Open Closed Principle
  • Liskov Substitution Principle
  • Interface Segregation Principle
  • Dependency Inversion Principle

These principles are a good start to read up on and discussed together with your peers. You may find the principles to interweave with each other and other processes such as seperation of concerns and dependency injection. After doing TDD for a while you also may find that these principles come naturally in practice as you need to follow them to some degree in order to create isolated and repeatable unit tests.

The one that the authors of Design Patterns themselves most worried about was the "Visitor" pattern.

It's a "necessary evil" - but is often over used and the need for it often reveals a more fundamental flaw in your design.

An alternative name for the "Visitor" pattern is "Multi-dispatch", because the Visitor pattern is what you end up with when you wish to use a single-type dispatch OO language to select the code to use based on the type of two (or more) different objects.

The classic example being that you have the intersection between two shapes, but there's an even simpler case that's often overlooked: comparing the equality of two heterogeneous objects.

Anyway, often you end up with something like this:

interface IShape
{
double intersectWith(Triangle t);
double intersectWith(Rectangle r);
double intersectWith(Circle c);
}

The problem with this is that you have coupled together all of your implementations of "IShape". You've implied that whenever you wish to add a new shape to the hierarchy you will need to change all the other "Shape" implementations too.

Sometimes, this is the correct minimal design - but think it through. Does your design really mandate that you need to dispatch on two types? Are you willing to write each of the combinatorial explosion of multi-methods?

Often, by introducing another concept you can reduce the number of combinations that you're actually going to have to write:

interface IShape
{
Area getArea();
}

class Area
{
public double intersectWith(Area otherArea);
...
}

Of course, it depends - sometimes you really do need to write code to handle all of those different cases - but it's worth taking pause and having a think before taking the plunge and using Visitor. It might save you a lot of pain later on.

Singletons - a class using singleton X has a dependency on it that's hard to see and hard to isolate for testing.

They're used very often because they're convenient and easy to understand, but they can really complicate testing.

See Singletons are Pathological Liars.

I believe the Template Method pattern generally is a very dangerous pattern.

  • A lot of times it uses up your inheritance hierarchy for "the wrong reasons".
  • Base classes have a tendency to become littered with all sorts of unerelated code.
  • It forces you to lock down design, often quite early in the development process. (Premature lock down in a lot of cases)
  • Changing this at a later stage becomes just harder and harder.

I don't think you should avoid Design Patterns (DP), and I don't think you should force yourself to use DPs when planning your architecture. We should only use DPs when they natural emerge from our planning.

If we define from the start that we want to use a given DP, many of our future design decisions will be influence by that choice, with no guarantee that the DP we chose is suited for our needs.

One thing we also shouldn't do is treat a DP as an immutable entity, we should adapt the pattern to our needs.

So, sumarizing, I don't think we should avoid DPs, we should embrace them when they are already taking shape in our architecture.

I think that Active Record is an overused pattern that encourages mixing business logic with the persistance code. It doesn't do a very good job of hiding the storage implementation from the model layer and ties the models to a database. There are plenty of alternatives (described in PoEAA) such as Table Data Gateway, Row Data Gateway and Data Mapper which often provide a better solution and certainly help to provide a better abstraction to storage. Also, your model should not need to be stored in a database; what about storing them as XML or accessing them using web services? How easy would it be to change the storage mechanism of your models?

That said, Active Record is not always bad and is perfect for simpler applications where the other options would be overkill.

I hope I won't get beaten too much for this. Christer Ericsson wrote two articles (one, two) on the topic of design patterns in his real time collision detection blog. His tone is rather harsh, and perhaps a bit provocative, but the man knows his stuff, so I wouldn't dismiss it as ravings of a lunatic.

Some say that service locator is an anti pattern.

It is simple ... avoid Design Patterns that are not clear to you or those that you do not feel comfortable in.

To name some ...

there are some unpractical patterns, like e.g.:

  • Interpreter
  • Flyweight

there are also some harder to grasp, like e.g.:

  • Abstract Factory - Full abstract factory pattern with families of created objects is not such a breeze as it seems to be
  • Bridge - Can get too abstract, if abstraction and implementation are divided to subtrees, but is very usable pattern in some cases
  • Visitor - Double dispatch mechanism understanding is really a MUST

and there are some patterns that look terribly simple, but are not so clear choice because of various reasons related to their principle or implementation:

  • Singleton - not really totally bad pattern, just TOO overused (often there, where it is not suitable)
  • Observer - great pattern ... just makes code much harder to read and debug
  • Prototype - trades compiler checks for dynamism (which can be good or bad ... depends)
  • Chain of responsibility - too often just forcedly/artificially pushed into the design

For those "unpractical ones", one should really think about before using them, because there is usually more elegant solution somewhere.

For the "harder to grasp" ones ... they are really great help, when they are used at suitable places and when they are implemented well ... but they are nightmare, when improperly used.

Now, what's next ...

  • Head First Design Patterns is a MUST
  • Sourcemaking is the "first aid"

I believe the observer pattern has a lot to answer for, it works in very general cases, but as systems become more complex it becomes a nightmare, needing OnBefore(), OnAfter() notifications, and often posting of asynchronous tasks to avoid re-entrancy. A much better solution is to develop a system of automatic dependency analysis that instruments all object accesses (with read-barriers) during calculations and automatically creates an edge in a dependency graph.

A complement to Spoike's post, Refactoring to Patterns is a good read.

Iterator is one more GoF pattern to avoid, or at least to use it only when none of alternatives are available.

Alternatives are:

  1. for-each loop. This construction is present in most mainstream languages and may be used to avoid iterators in majority of cases.
  2. selectors à la LINQ or jQuery. They should be used when for-each is not appropriate because not all of objects from container should be processed. Unlike iterators, selectors allow to manifest in one place what kind objects is to be processed.
Category:design patterns Time:2009-01-16 Views:1

Related post

  • What are good light-weight design patterns for avoid nulls in Java? 2012-02-06

    Obviously one of the greatest banes of Java programming is nulls and null-pointer exception. What design patterns are there that don't add too much to your code but reduce the problem of sand null-pointer exceptions? --------------Solutions----------

  • Design pattern to avoid downcasting in message passing 2012-02-17

    Base class MessageHandler has derived classes. They would like to pass messages to each other. Messages could be of different classes, but can be made to share a base class. How can each MessageHandler avoid downcasting a received message? Is it some

  • State design pattern but avoiding singletons 2012-01-18

    This is getting little bit tricky. I am using state pattern in my application to manage states. I want to have a single instance of each state in my application but I do not want to make each state class as a singleton class. The other approach that

  • A design pattern to avoid multiple ifs 2011-10-21

    I have a really awfull class with two methods that start or stops some services when that services are available. Something like the following (they are not if-elses, just if): void startServices() { if (service1 == true) { start1(); } if (service2 =

  • How to avoid C++ cast for specific class methods? Design Pattern? 2011-03-25

    Suppose I have something like this: class Father { public: virtual int genericMethod (void) =0; }; class Son1: public Father { public: int genericMethod () { } }; class Son2: public Father { public: int genericMethod () { } int specifClassMethod() {

  • What can I use (Design pattern maybe?) to avoid this ISP violation? with a Asp.net basepage 2011-10-24

    I have a class: class BasePage { protected abstract Company ReferencedCompany { get; } } And an asp.net page that inherits from it. However i do not want/need to implement this property in the inheriting class. And I dont really want to leave it blan

  • Do you use design patterns? 2008-08-14

    What's the penetration of design patterns in the real world? Do you use them in your day to day job - discussing how and where to apply them with your coworkers - or do they remain more of an academic concept? Do they actually provide actual value to

  • What are some real life examples of Design Patterns used in software 2008-08-30

    I'm reading through head first design patterns at the moment and while the book is excellent I also would like to see how these are actually used in the real world. If you know of a good example of design pattern usage (preferably in a OSS program so

  • Data Validation Design Patterns 2008-09-05

    If I have a collection of database tables (in an Access file, for example) and need to validate each table in this collection against a rule set that has both common rules across all tables as well as individual rules specific to one or a subset of t

  • Design Pattern for Undo Engine 2008-09-08

    I'm writing a structural modeling tool for a civil enginering application. I have one huge model class representing the entire building, which include collections of nodes, line elements, loads, etc. which are also custom classes. I have already code

  • design patterns or best practices for shell scripts 2008-09-17

    Does anyone know of any resources that talk about best practices or design patterns for shell scripts (sh, bash etc...)? --------------Solutions------------- I wrote quite complex shell scripts and my first suggestion is "don't". The reason is that i

  • How do you know when to use design patterns? 2008-09-17

    Anyone can read the GoF book to learn what design patterns are and how to use them, but what is the process for figuring out when a design pattern solves a problem? Does the knowledge of the pattern drive the design, or is there a way to figure out h

  • Appropriate design pattern for an event log parser? 2008-09-18

    Working on a project that parses a log of events, and then updates a model based on properties of those events. I've been pretty lazy about "getting it done" and more concerned about upfront optimization, lean code, and proper design patterns. Mostly

  • Creating the Singleton design pattern in PHP5 2008-10-15

    How would one create a Singleton class using PHP5 classes? --------------Solutions------------- /** * Singleton class * */ final class UserFactory { /** * Call this method to get singleton * * @return UserFactory */ public static function Instance()

  • Misused design patterns 2008-10-30

    Are there, in the canonical Gang of Four list, any design patterns that you often find misused, misunderstood or overused (other than the highly debated Singleton)? In other words, is there a design pattern you would advise to think twice before usin

  • Null object design pattern question 2008-11-25

    I recently watched this youtube tutorial on the Null Object design pattern. Even though there were some errors in it: such as the NullCar that doesn't do anything creates an infinite loop, the concept was well explained. My question is, what do you d

  • What are the best programmatic security controls and design patterns? 2008-12-21

    There's a lot of security advice out there to tell programmers what not to do. What in your opinion are the best practices that should be followed when coding for good security? Please add your suggested security control / design pattern below. Sugge

  • Are design patterns something you invent as you go 2008-12-24

    Are there set design patterns or does each individual sufficiently skilled software developer recognize and reduce their code to develop new patterns. Effectively creating their own "design" patterns. Edit - Thanks for the responses. In reality I'm j

  • What is the most common design patterns for any windows forms application? 2009-01-01

    I am asking about that as I am going to develop a client side application using c# to display stock data and make some user-interaction, so give me links for best tutorials you read before --------------Solutions------------- Jeremy Miller's guide is

Copyright (C) pcaskme.com, All Rights Reserved.

processed in 0.808 (s). 13 q(s)