Design Patterns - The holy grail?
In this article I will present to you the concept of Design Patters, why were they created, which problems they solve, and how YOU can be a better developer if you learn about them. Let´s get started!
What is a Design Pattern?
Let´s see some "formal" definitions from my favorite book about this topic (Design Patterns: Elements of Reusable Object‑Oriented):
"Each pattern describes a problem which occurs over and over again in our environment, and then describes the core of the solution to that problem, in such a way that you can use this solution a million times over, without ever doing it the same way twice". Later on, they say that every pattern has 4 essential elements: A name, a description of the problem it solves, the solution itself, and the consequences.
If we look online for another definition to not rely only on one source we can find something like this: "In software engineering, a software design pattern is a general, reusable solution to a commonly occurring problem within a given context in software design. It is not a finished design that can be transformed directly into source or machine code. Rather, it is a description or template for how to solve a problem that can be used in many different situations."
OK, so with those definitions in mind, let's do a summary more down to earth and easy to understand. Design patterns are solutions for repetitive problems we find while developing software. Each pattern has a name for reference, the problem for which it should be applied, and a high-level solution that you have to adapt and implement to your system.
GREAT! You already have an idea of what a Design Pattern is. Before moving on I want to recommend you read the whole book because it is a great lecture and you will learn so much from it.
The book is: Design Patterns Elements of Reusable Object‑Oriented from Gamma, Helm, Johnson and Vlissides
Why do we need Design Patterns?
The short answer is to make our life easier. A more explanatory answer is to avoid losing time re-inventing the wheel and discussing how to solve problems that are well documented and have standardized and proven solutions.
Why should YOU invest time learning them and/or teaching them to your team? Because it adds another level of abstraction. Once you have a team of devs that know Design patterns you will be able to talk about problems and solutions at a higher level of Software design. You don´t have to go to low-level design details like: "We will need a superclass for the standard behavior of clientsDebt and then subclasses for each type of client with its particular logic and compose that to our client class" instead you can just say: "Here, for calculating clients debt we will implement a strategy" and everyone will have in mind what that means without going into details, and there is also almost no space for misconceptions or errors in translating that design idea to implementation. This saves time, analysis, complexity, and will also make your solution cleaner and more scalable if the patterns are applied correctly of course.
How to learn Design Patterns?
I hope by this point you already see the great value that Design Patterns can add to you so the next logical step is to learn them. Of course, I won´t be able to do a summary of a 400 pages book in 1 article but I will give you some introduction here and pointers so you can dig deeper into this fascinating topic.
Design patterns can be classified into 3 classes:
- Creational Patterns: They are used to abstract the instantiation process. They make a system independent of how its objects are created, composed, and represented.
- Structural Patterns: These are concerned with how classes and objects are composed to form larger structures. They add flexibility and are great for making independently developed libraries work together.
- Behavioral Patterns: The last category is concerned with algorithms and the assignment of responsibilities between objects. These not only focus on objects or classes but also the patterns to communicate them. They are characterized by complex control flow that´s difficult to follow on run-time.
Now we can go through a list of the design patterns I like the most with a short definition and use cases. You can use this as a guide to see which design patterns you find the most useful to then dig up a little and fully understand them and hopefully implement them very soon ;)!
My 8 favorite Design Patterns for starters
Builder (Creational) Separates and encapsulates the construction of a complex object. Builders will expose the different steps to create said complex object and each builder type will have its specific configuration. Reduces coupling, centralizes and isolates the construction code, only when all the steps are done the user can access the final built product.
Singleton (Creational) Ensures a class only has one instance. Provides a global point to access it. This one is "easy" commonly used and some consider it an anti-pattern (not good practice). Be aware of it!
Adapter (Creational) Converts the interface of a class into a new interface that matches what a client object expects. It allows classes to work together that otherwise couldn´t because of incompatible interfaces.
Decorator (Structural) Attachs additional responsibilities, features (decorators) to an object dynamically. It allows us to add functionality to objects without having access to their class definitions. This pattern is a little complex but helps you a lot to get your head around patterns in general and complex designs. Please give it a read and try implementing it!
Proxy (Structural) Provides a placeholder for another object to control access to it. It´s like a middleman that will provide access to another object by passing the message to it. This pattern allows us to defer the cost of the creation of an object, encapsulate some validations and other similar use cases.
Command (Behavioral) Encapsulates requests or actions (commands) as objects, letting you parameterized clients with different requests, defer the moment of creation from the moment of execution of said actions and support undoable operations.
Observer (Behavioral) Defines a model with an observable object and interested observers and when the state of the observable changes all the observers are notified of said change to take action.
Strategy (Behavioral) Defines a family of algorithms, encapsulate each one, and make them interchangeable by having a common interface to the client. This is my favorite pattern for starters, it has many many use cases and improves your code a lot. Please give it a try!
To learn more about these patterns or all the others that developers and designers use, go ahead and search in Google/Youtube for more details or read the recommended book. But most importantly don´t only watch and read, APPLY IT. The pattern will fully click in your brain once you implement it and see it working.
That will be it for this article, I hope you liked it and learned a couple of things. Let me know if you enjoyed it and would like me to go into further details about this topic. You can also connect with me on Twitter where I´m active every day producing programming-related content. Thanks for reading!