37

Is there a conceivable design pattern for any object-oriented program? I ask this because recently I saw an implementation of a Door class with a Lock. It was part of a test and the answer said that the code is following the Null Object pattern:

class Lock
{
public:
    virtual void close() = 0;
    virtual void open() = 0;
    virtual bool is_open() const = 0;
    virtual ~Lock() { }
};

class DummyLock
    : public Lock
{
private:
    DummyLock();
    DummyLock(const DummyLock&) = delete;
    DummyLock& operator=(const DummyLock&) = delete;

private:
    void close() { }
    void open() { }
    bool is_open() const { return true; }

public:
    static DummyLock m_instance;
};

class Door
{
public:
    Door() : m_lock(DummyLock::m_instance) { }
    Door(Lock &lock) : m_lock(lock) { }

public:
    Lock& get_lock() const { return m_lock; }

private:
    Lock &m_lock;
};

This made me think: This code follows a good design pattern even though the description is so simple (this class is designing a door class with a lock), so if I am writing more complex code, should there always be some design pattern that I am following?

  • 3
    Very related: Choosing the right design pattern – user40980 Oct 2 '14 at 18:10
  • 51
    Do you think you could speak entirely in idioms? No? Then you shouldn't construct your programs by cobbling together design patterns. – Kilian Foth Oct 2 '14 at 18:14
  • 4
    In your example, the Null object pattern is only added for academic purposes, it does not introduce "a good design" into this code. – Doc Brown Oct 2 '14 at 19:08
  • 4
    @djechlin: in other words, use the "two word" design pattern :) – Michael Shaw Oct 3 '14 at 6:14
  • 11
    The problem is that too many people believe that design patterns are a substitute for thought, and a substitute for experience (which implies a certain amount of trial and error). You can't take a book full of design patterns and put them together like Tinker Toys to produce an application with non-trivial size and complexity and decent quality. Even experienced programmers often need to try two or three designs before they find one that works. – Daniel R Hicks Oct 4 '14 at 2:03
143

should there always be some design pattern that I am following?

Dear God NO!

I mean, you can go ahead and say that any random code is following some random XYZ pattern, but that's no more useful than me claiming to be king of my computer chair. Nobody else really knows what that means and even those that do won't exactly respect my claim.

Design patterns are a communication tool so that programmers can tell other programmers what has been done or what should be done without spending a bunch of time repeating themselves. And since they're things that come up a bunch of times, they're useful concepts for programmers to learn "hey, making XYZ always seems to come up because it's good/useful".

They do not replace the need for you to think for yourself, to tailor the patterns for the unique problem in front of you, or to handle all of the inevitable things that don't fit into nice buckets.

  • 5
    Your first paragraph is part of how I would answer this. Something becomes a pattern when it is repeated. If it is repeated enough times to require communication, it is a Pattern and benefits from a name. It is even argued by some that a pattern only develops because some abstraction is missing. Pursuit of patterns is the road to infamy as a member of the vaunted Cargo Cult. – Magus Oct 2 '14 at 21:09
  • 11
    @Cerad: Sure, as long as you promise not to write God classes as well! – yatima2975 Oct 2 '14 at 21:51
  • 9
    John Doe - Technical Engineer, Generic Code Monkey and King of his computer chair – h.j.k. Oct 3 '14 at 3:29
  • 1
    Arguably, a design should use patterns where appropriate and classes should be named as such. They are important tool. Being afraid of the_cult (tm) is just as dangerous. – Gusdor Oct 3 '14 at 8:48
  • 25
    Great answer! My one criticism is that the "Dear God NO!" isn't big enough. – tobyink Oct 3 '14 at 10:59
37

No.

This is what the Gang of Four (who originally popularized design patterns) had to say about it in their book:

"No discussion of how to use design patterns would be complete without a few words on how not to use them. Design patterns should not be applied indiscriminately. Often they achieve flexibility and variability by introducing additional levels of indirection, and that can complicate a design and/or cost you some performance. A design pattern should only be applied when the flexibility it affords is actually needed."

The example you show doesn't actually do much of anything (I don't think it was meant to, I think it was just meant to be an example). By itself, it has no need of the null object pattern. In the context of a larger program, it might.

The wrong approach is assuming that just because it has been labelled a "design pattern" it must be good, and then looking for more places to cram more patterns in. Use them when they fit the program and actually solve a problem for you.

  • 7
    The book being Design Patterns: Elements of Reusable Object-Oriented Software by Erich Gamma, Richard Helm, Ralph Johnson and John Vlissides. – developerwjk Oct 2 '14 at 23:38
  • 4
    +1 For actually quoting the source of the design patterns. – Pharap Oct 4 '14 at 5:13
29

if I am writing more complex code, should there always be some design pattern that I am following?

No. Design patterns are just that: patterns in relationships between objects. In other words, relationships that are used and reused often enough that someone said "Hey, we seem to be doing this a lot, let's give it a name." The list of design patterns were not determined all at once in the beginning of OOP and then handed down by GOF! They were discovered and eventually documented, and then popularized by the book.

That said, a big part of the benefit of design patterns is that they make it easier to think about software design at a higher level. They let you skip worrying about implementation details and think more about the big picture. In that sense they free you from the minutia, but they can also limit you in the same way that the way you express yourself can be limited by the words that you know. So, there may come a time when there is a design pattern for most of what you do simply because the patterns that you know are the terms in which you think. Keep your eyes open for cases where you might be abusing a pattern, and where you may need to think more deeply about better ways to do things.

Also, realize that in practice you often don't implement a given design pattern so much as recognize the pattern in some existing code, like an object framework. Knowing about common design patterns makes it much easier to learn how a framework is intended to be used because you can see the relationships between classes in terms that you already understand.

10

Design patterns have two advantages

  1. They are easy to describe to other developers, because people generally agree on what the patterns are
  2. They tend to have been beaten on pretty thoughtfully by our predecessors, so their strengths and weaknesses are well understood.

The goals of every program should be

  1. It works. It has to do whatever the end goal is, or it doesn't matter how many design patterns you use. OO design patterns make it easy to dice up the problem into easy to understand bits so its easier to prove it works.
  2. It is easy to read. This is where design patterns are nice. The OO problems they solve are complicated. If you solve them in a "standard" way, its easier on the next developer
  3. It is easy to grow. Almost 0 modern programs finish where everyone planned them to. Every program grows after its initial release. OO patterns are known for being curiously good at growing.

That all being said, note that every reference to OO design patterns is "they're just good at the job." They are not perfect, but they do fill a niche very effectively. Use them when they work, avoid them when they don't.

As an example, of "complex code," as you mentioned in your question, take a scripting language I wrote. Most of it is OO with design patterns everywhere. However, when it came to writing the garbage collector, I unceremoniously dropped all pretenses of OO, because the particular things I needed to do were better modeled as good ol' fashioned bit-bashing. There's not an OO pattern in the entire thing up until it came to writing finalizers, where once again OO started to be a useful model again. Without any pomp nor circumstance, the code suddenly shifted back into using OO techniques again.

Use design patterns whenever they make your product better; avoid them when they make your product worse.

  • 2
    I think that last sentence should be at the top in bold or as a summary. – Pharap Oct 4 '14 at 5:15
5

I will buck the trend a little, because the answer is more subtle than other answers are letting on. Every class you write should not employ a design pattern, but most non-trivial programs you write likely should.

A non-trivial program without any design patterns indicates:

  • Your program is so unique that no portion of it is similar to common problems programmers have faced before. Or
  • Your program contains those common problems, but you've solved them in a better way that no one has thought of before.

Both scenarios are highly unlikely, no offense.

That doesn't mean the design pattern should drive your design, or that you should insert one indiscriminately because you think it will look bad if you don't. The wrong design pattern is worse than none.

What it does mean is you should look at a lack of design patterns in your overall program as a code smell. Something that makes you take a second look and reevaluate if your design couldn't be cleaner. If at that point you decide to leave design patterns out of a program, that should be a deliberate, informed decision, not happenstance.

For example, you don't say, "I need to model a door and a lock, what design pattern should I use?" However, if you designed it first without using any design patterns, that should prompt you afterward to say something like, "I have an awful lot of null checks in this code, I wonder if there's a design pattern that could help manage those."

See the difference? It's a subtle but important distinction.

  • 5
    There are many more common problems (and their common solutions) than there are design patterns. Design patterns are a cataloged subset of common OO solutions -- not the set of all common solutions. – Michael Shaw Oct 3 '14 at 21:24
  • 1
    Could you define what you mean by 'non-trivial', I was under the impression that the term 'non-trivial' was subjective. – Pharap Oct 4 '14 at 5:17
  • 1
    It is subjective. I mean the kind of program you would write on a team at work, requiring multiple maintainers on an ongoing basis. – Karl Bielefeldt Oct 4 '14 at 5:25
  • If you're lucky enough to see your problem afterwards. Null checks, sure. Security vulnerabilities? Other insidious ways the program will break under maintenance? Problems only the next engineer will uncover? Much more yucky. – djechlin Dec 3 '14 at 15:47
  • "I need to model a door and lock, what should the interface be? Will performance be a part of the contract? Should I use a service or library? How will resources be passed?" should all be asked, and you should have answers that are basically regarded as design patterns. – djechlin Dec 3 '14 at 15:48
4

Broken question. Let me give you a novel definition of design pattern that would undo a lot of damage released by GoF: a design pattern is a good coding practice. That's it.

Any reasonably complex module will have several design patterns in it. Any time you cache it's probably a flyweight pattern but I'm not going to revoke your programming degree if you don't call it that. Any time you have a callback in it you're in some sort of event / fire / callback pattern. etc. If you have the word "static" you have a singleton. If you have a static constructor you have a factory pattern. If a resource is passed to your module you are using dependency injection.

"Design pattern" is a broken term ill-popularized by GoF, that makes it sound like all patterns are on the same level or you should use the doctor recommended 3 to 5 per class. Any time you do something right that someone else did right, it's a design pattern. A for(;;) is a common pattern used to represent an infinite loop, for instance.

You shouldn't go try to learn a bunch of design patterns. Programming knowledge is not indexed by design patterns! Rather you should learn how to write good code by read books, blogs, and attend conferences in your field. For instance, if you're already using dependency injection but just haven't labeled it, you might benefit from always using DI or using an IoC framework. Or if you're struggling to code right in events and callbacks, go learn Haskell so you're familiar with functional design patterns and it becomes easy.

And if your entire class reads as one big thing someone else did right, why are you reinventing the wheel? Just use their stuff.

  • 2
    In what language is for(;;) idiomatic? That is probably not the best example of something someone did "right". – Telastyn Oct 3 '14 at 1:41
  • 1
    @Telastyn C, C++, Java, Javascript, C#. – djechlin Oct 3 '14 at 1:45
  • 2
    I've never seen anyone prefer that over while(true) (or while(1)) in C, C++, Java, or C# in my 20+ years of programming. – Telastyn Oct 3 '14 at 1:48
  • 1
    @Telastyn stackoverflow.com/a/2611744/1339987 fwiw I started preferring while(true) because it looks more readable to me. – djechlin Oct 3 '14 at 1:51
  • 1
    I always use for (;;). No particular reason, I read it somewhere probably. I like the fact there are no variables or constants involved. Anyway, @Telastyn now you've met someone. – Ant Oct 3 '14 at 16:06
0

You should always follow OO design principles (e.g., modularity, information hiding, high cohesion, etc.). Design patterns are a relatively refined niche of OO design principles, especially if you consider the KISS principle.

Patterns are solutions to common design problems. These problems come from one of two places (or a mix of both): the problem space (e.g., software to manage Human Resources in a company) and the solution space. An OO programs is an instance within the solution space (e.g., one of many ways you could design an OO program to facilitate the management of HR).

It's not so easy to know when to use a pattern. Some patterns are low-level, closer to coding and the solution space (e.g., Singleton, Null object, Iterator). Others are motivated by requirements in the problem space (e.g., Command pattern to support undo/redo, Strategy to support multiple input/output file types).

Many patterns come from the need to support variations of the software in the future. If you never need to make those variations, a pattern could be over-design. An example would be using the Adapter pattern for working with the existing external HR database. You decide to apply Adapter because the current database works with Oracle and you might want to support NoSQL in the future. If NoSQL never comes to your organization, that Adapter code could very well be useless. See YAGNI. Support for variations that never come is misusing a design pattern.

0

Patterns are common solutions to common problems. We are always following some patterns, the patterns by GoF address the most recurring ones. That, to have a shared understanding and shared approach known to software engineers.

That said, my answer is no, but yes you are always following some pattern of your own. As the GoF rightly puts it-

One person's Pattern is another person's primitive building block.

Great quote.

  • this doesn't seem to offer anything substantial over points made and explained in prior 7 answers – gnat Nov 17 '14 at 5:06
  • Fine. Note, I made a general point...it's applicable to Design Patterns as a theoretical discussion. – Syed Priom Nov 17 '14 at 5:18
  • "This site is all about getting answers. It's not a discussion forum..." (tour) – gnat Nov 17 '14 at 8:27
  • I did answer the question. Thank you. This conversation ends here. – Syed Priom Nov 18 '14 at 2:47
  • @gnat it's a heck of a lot more concise, though. – djechlin Dec 3 '14 at 15:50
0

When I am writing code, I do not plan on deliberately using as many design patterns as I can. But, I guess, sub-consciously, when I get a coding problem, one of the design patterns seems to fit, and I just use it. And sometimes nothing fits. What is more important to me is writing code that does the job and is easy to maintain and grow.

Here is an article on applying OOD principles using design patterns, and it has code examples as well (in C++). It shows how and when to apply some of the design patterns to write clean code.

protected by gnat Jan 12 '15 at 19:55

Thank you for your interest in this question. Because it has attracted low-quality or spam answers that had to be removed, posting an answer now requires 10 reputation on this site (the association bonus does not count).

Would you like to answer one of these unanswered questions instead?

Not the answer you're looking for? Browse other questions tagged or ask your own question.