Myth 1: Design Patterns are Bad or Useless.

At some point in a software developer’s career they will be introduced to “patterns”. These are recipes of design that serve as methods to solve commonly seen problems in software design. They can range from something as simple as “Factory Method” to something more difficult to understand such as “Bridge”. The first time a software developer runs into this concept their initial reaction may very well be, “Oh my, this is the best thing that ever happened to me!” They’re right.

The problem at this point, and why I think many people look at patterns with disgust, is that a new developer then starts trying to solve every problem they see with one pattern or another. This blind application of patterns is a stage that perhaps must be gone through in order to learn more about them, but it’s also probably the most frustrating thing for a moderately successful software designer to deal with. Software developers who are algorithmically minded rather than design minded (and there’s nothing wrong with that) find this even more frustrating and see no purpose in the design aspect to begin with. Furthermore, a good software designer doesn’t go about prosthelytizing the great value of patterns because they understand both the benefits and costs of applying them. It’s the new guy, who thinks this is the most wonderful thing in the world, that speaks unceasingly about patterns, applies them all over the place, and frustrates the better developers around them. So this gives patterns a bad name to many people.

Past this point in a software developer’s learning though is a more balanced, correct application of patterns should they get to that point without abandoning the concept or being convinced out of it. Patterns appear everywhere in life and are inherent to the problem being addressed. Patterns don’t need to be pushed into a design, they need to be found in it…pulled out of the problem. Having a wide variety of patterns in your repository of tools makes it easier to recognize them in a problem. A good designer is able to see these patterns in the problem itself without imposing them as a solution where they may not apply (not all problems are generic).

That’s not the only useful aspect to knowing patterns though. One thing that knowing patterns provides is to be able to talk with other developers at higher abstractions than is otherwise necessary. Instead of having to explain in detail how function X creates a pointer to type T that is of the classification in abstraction A, a designer can say, “This here is a Factory Function,” and those who’ve studied patterns know what the person means and will immediately be thinking of 3-4 ways to implement it. Reading a function knowing that the purpose of it is to be a Factory Function also gives a context to understanding it when it comes to code reviews and in understanding and modifying existing code.

This gives us the most useful view of patterns. Patterns are a set of common problems, a way to classify them, and a language to communicate them. Developers and designers need to learn them so that they know that language and can communicate with each other at the design level rather than quibbling over algorithms and basic, every day techniques. These things are important in many conditions more more importantly is the maintainability and legibility of a software product’s design. It’s the design, not the algorithms, that give a product a long or short life. A design that makes good use of patterns is easier to communicate and thus easier to work on. This means that it can survive personnel changes and long lists of new feature additions–much more than a product that makes use of none that is.

Another thing to consider is that try as you might, you’re not coming up with a brand new approach to solving that problem you’re meeting. The chances are high that someone’s faced it before and has devised an elegant solution. The amount of problems solved by the Chain of Responsibility pattern is endless, the likelihood that you’ve solved one of those in a unique and particularly brilliant way is next to zero no matter how smart you are. You probably used a Chain of Responsibility but simply don’t know it. When you’re trying to train your replacement and they say, “Ah, that looks like a Chain of Responsibility…that means…,” you can say, “Why yes!” rather than, “Uh, what?” Not knowing the language because you’re too smart to apply it is not a sign of intelligence, it’s a sign of arrogance.

At the very least a software engineer or developer absolutely needs to know the language of patterns even if they don’t familiarize themselves with the kinds of implementations that exist. Even if you have no intention to apply patterns the language has inherent utility; you need to know it.

Advertisements

11 comments on “Myth 1: Design Patterns are Bad or Useless.

  1. Tim K says:

    Very useful insight for a beginner. Could you please recommend a good book to get familiarized with patterns (assuming that now there are tons of them). Thanks in advance.

    • Crazy Eddie says:

      There’s the Design Patterns book itself (aka Gang of four). It’s not really a tutorial book though. I have not read but hear good things about Pattern Oriented Software Architecture. There was also recently a course in coursera on pattern oriented design that may come up again and you might find the videos on youtube or something. You could also review the NetObjectives wiki: http://www.netobjectivestest.com/PatternRepository/index.php?title=Main_Page

      I’d suggest at least getting the Design Patterns book and at least familiarizing yourself with the motivations behind each pattern and its cost/benefit. Then just practice. You could flip through code on github or something and see what patterns you can recognize.

      The first program I wrote after buying the GoF book was a paint program for college. Was amazing how easy it became to create undo/redo stacks with commands and mentors. I of course became pattern obsessed for a while, but that’s not a bad thing I don’t think…just a stage to go through.

  2. John Carter says:

    Sigh! The worst is the _increased_ use of globals sprinkled with the sacred magic of patterns and the Singleton pattern.

    The second worse is the Observer pattern.

    I call it the “come from” statement.

    Do you remember “Goto considered harmful”? (If you don’t look it up, it’s important)

    The Observer pattern is the “come from” and is downright evil.

    The problem is that many patterns in the GoF are standard patterns to get around the deficiencies of C++ or Java…. and the need for them vanish like the dew in the morn in a decent language like Ruby.

    But as a vocabulary for software architecture… I’m OK with them.

    • Crazy Eddie says:

      I’ve read the article you cite and I don’t see that it supports your notion. Seem totally unrelated in fact. I don’t agree with anything you’ve said but everyone’s free to their opinions. Call things what you want I guess, though without any explanation it seems pretty mysterious and though it may seem intuitive to you it’s making zero sense to me. Hopefully your code is more expressive 😉

      • John Carter says:

        Look it this way… A “goto statement” is problematic because the control flow become hard to analyze. You look at the code downstream of a label… and it could have got there from an explosion of possible routes. You eye tells you line 1, is followed by line 2, is followed by line 3…. except if there is a statement label in which case it becomes very very hard to reason accurately about the code.

        With the observer pattern it is even worse. Some lexically distant part of the code registers the observer for updates (with perhaps more than one observed item of state) and some completely unrelated part of the code updates that state… and triggers a jump to the lexically unrelated observer.

        What things trigger updates? Very hard to tell.

        What is the flow of control after an update? Very hard to tell.

        What is the flow of cause and effect in the presence of the observer pattern? Very very hard to analyze.

        If you think about it, if some evil language designer were to come up with a “come from” statement….. it would bear remarkable similarities to the observer pattern.

      • Crazy Eddie says:

        I’m not sure I buy the idea of being able to analyze your program by walking through the entire thing from start to finish. I can’t imagine being able to do that with even a moderately complex program these days.

        So your idea of “comes from” seems to me to be fairly innocuous. Any object or function you’re working on has a variety of “come froms” that cannot be immediately found in a straight forward manner, nor more or less difficult than connecting to an observable anyway. Callbacks are a long standing method of decoupling action from handler and the observer is simply the OO version of callbacks. Generic function pointers and binders actually make it more powerful but of course only increase the level of indirection you seem to lament.

        Actions shouldn’t need to know what their handlers are. One of the most common channels of change are users that say, “When I do this I want it to also do this other thing in addition to what it does already.” It’s a whole lot simpler to attach the handler that will do what the user wants than to add yet more handling code to the action source itself. Or they ask for another X source attached to a different kind of handling behavior. Being able to plug in action->handler is a VERY powerful tool when faced with problems like this.

        Decoupling and cohesion are essential to good software development and it at least seems to me that observers are one great way to provide both. Finding where the source is also isn’t any harder than asking, “What observer interface does this function implement?” Then you know that your function is being activated by activity from sources of type X.

        OOP is not the same as procedural programming. You need to think of your program as a set of connected, reusable objects rather than a stream of procedures to effectively understand it. I think you’re on the wrong track here and I’m afraid I don’t see your point.

    • Charter says:

      The thing that gets me with the observer pattern is that the observer is supposed to provided a common interface for the objects to implement. So the observable must track it’s observers and the observers must have knowledge of their observables; That’s crazy. I find that the whole observer pattern can be replaced with callback functions and it is often more readable and takes far less code – then there was Java… I find the idea that the Subject would have knowledge of the those watching it pretty absurd from the beginning. How does one then test the subject in isolation?

      • Crazy Eddie says:

        Callbacks are a design pattern also, and one not unlike Observer. Sinks still have to be tracked, the interface still has to be implemented, and any testing difficulty is the same.

  3. The Recursion King says:

    He’s saying that it needlessly increase the complexity of an application because the ability to understand the execution flow is severely hampered. This in turn makes it very hard to debug such a program, which leads to spiraling costs, I.T. projects failing and companies going out of business. The principle job of every developer should be to /minimise/ complexity while solving the business problems. This means avoiding patterns which make understanding code very difficult and writing code that makes it very simple and even elegent.

  4. Pharap says:

    A little anecdote to (sort of) support what you’re saying.

    Several months before I learnt that programming patterns even existed, (let alone what they were useful for,) I tried writing a tower defence game in C# with XNA. During the attempt, aside from not realising the patterns that were already built in to XNA I managed to put both the factory pattern and the prototype pattern into my design.

    This shows that if someone who is totally unaware of patterns starts accidentally using them (or constructs similar to them) then the patterns are logical solutions to existing problems.

    That said, much like different programming languages, different patterns are tools that should be used to fix the problem they are designed for. A hammer will always be more efficient at putting a nail in a wall than an oversized spanner.
    (http://www.zhihua-lai.com/wp-images/acm/2012/lang.jpg)

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

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

Twitter picture

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

Facebook photo

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

Google+ photo

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

Connecting to %s