Design patterns became popular during the 90s, when the “Gang of Four (GoF)” (Erich Gamma, Richard Helm, Ralph Johnson, and John Vlissides) wrote the well-known book:
"Design Patterns: Elements of Reusable Object-Oriented Software"
This book is one of the most influential books ever published in the software industry. However, it was written more than 25 years ago. It is reasonable to wonder whether design patterns are as relevant today as they were when the book came out.
Many would answer ‘No’ to this question. A common argument is that design patterns reside at a lower level of abstraction than most developers work on. In other words, design patterns are encapsulated or “hidden” within the frameworks, standard libraries, and languages that developers use today.
I disagree with this argument, and, even if it was true, I would consider it insufficient because the same reasoning applies to, for example, algorithms, data structures, and memory management. We have advanced tools, but this does not mean that it is not important to know what is under the hood.
If, at this point, you have guessed that my answer to the above question is ‘Yes’, you are correct. I do believe that designs patterns are still relevant, and, in this post, I try to explain the reasons behind my opinion.
To explain these reasons, I don’t discuss about what design patterns are. My focus is on benefits of design patterns that I consider relevant for any developer that is working in the software industry in the present time.
1. Design patterns give you design knowledge.
Design patterns represent design solutions that skilled professionals have used again and again in the past to solve recurring problems. Since these solutions incorporate the expertise of qualified professionals, we can expect them to apply good design principles.
Design principles are indeed pervasive in design patterns. For instance, the "State" pattern from the GoF book applies the "Open-Closed Principle" (which is one of the well-known SOLID principles) to make the addition of new states and transitions easier.
This leads to a (probably less conventional) way to look at design patterns: as practical examples that show good design principles in action.
Design patterns is a mainstream technique for organizing design ideas. When you study design patterns, you do not only learn the patterns. You learn design principles and gain general design knowledge.
2. Design patterns give you vocabulary to talk about software design.
Can you imagine an architect discussing about a house only in terms of bricks, walls, doors, and similar “low-level” terms?
It would take ages to describe a basic house.
To keep a more economical discourse, architects use “room patterns” such as bedroom, bathroom, and kitchen. This allows them to convey a lot of information with simple sentences such as "a three-bedroom two-bathroom house". The word “bathroom” carries implied information that does not need to be stated explicitly; for example, strong privacy requirements and specialized infrastructure such as sink and drainage.
In a similar way to construction architects, it would take ages for software engineers to describe a basic system if they could only speak in terms of objects and references between them.
In object-oriented design, everything is an object, a reference or a message. This is a useful abstraction, but you need something more, at a higher level. You need patterns with special names that allow you to convey more information with less words.
You need to be able to say: “add an Abstract Factory to this module” or “we can solve this problem by means of Dependency Injection”.
Design patterns allow you to pack a lot of information in short sentences. Design patterns enable more productive design discussions, when the team is familiar with the patterns.
3. Design patterns give you refactoring targets.
When all you have is a hammer, everything looks like a nail.
It is common, especially when you are learning about design patterns, to apply them everywhere. A pattern can give you an elegant design solution, but it can also add unnecessary complexity. Abstractions have a price, and paying this price is not justified when the abstractions address the wrong problem.
Extreme Programming (XP) advises us to avoid overengineering and to “do the simplest thing that could possibly work”.
If we keep the design simple and the quality of the code high, we can refactor continuously, easily incorporating new abstractions as they prove necessary. During refactoring, we may detect problems that can be solved by applying particular patterns. In this case, the patterns can act as refactoring targets, giving us guidance and direction.
Follow the rules of simple design, avoid overengineering, and refactor continuously. When a pattern solves a real problem, use the pattern as a target. Let it guide you in the refactoring process.
4. Design patterns can improve the readability of your code.
Jack W. Reeves, in his renowned paper from 1992:
“What is software design?”
Suggested that the source code of a software system is the design. He observed that the code is the only entity that, similarly to engineering documents from other disciplines, contains enough information to enable the construction of the actual software product. You can draw diagrams, but they are mere guidelines, ancillary to the actual design.
On the other hand, Eric Evans, in his wonderful book:
“Domain-Driven Design: Tackling Complexity in the Heart of Software”
Taught us the benefits of keeping the source code as a faithful reflection of the domain model. When changes to the code (likely) mean changes to the model and vice versa, the mapping between the two becomes obvious.
These two authors showed us that there exists a tight connection between source code and design.
This has an interesting consequence: when you apply a design pattern, the pattern should be obvious in the code. This will increase the readability of the code, at least for those readers that are familiar with the pattern.
A pattern being obvious in the code does not necessarily mean that the code uses the pattern names. It means that the pattern is easily recognizable.
For example, you can create a method that defines the skeleton of an algorithm and defers some steps to subclasses. Readers that are familiar with Template Method will immediately recognize the pattern, but this does not mean that the method must contain “template method” in its name.
If your code evokes design patterns, the readers that know the patterns will easily understand your intent.
In my opinion, design patterns are as useful nowadays as they have always been, and this post discusses about the four benefits of design patterns that are the reasons behind my belief.
For me, the key observation is that, when you study design patterns, you do not only learn or memorize patterns. You enhance your design vocabulary; you gain general and widely applicable design knowledge; you improve your refactoring strategies; and you enrich the mental toolbox that will allow you to write readable and maintainable code.
These benefits make learning patterns a good investment.