Once upon a time, Design Patterns was a big thing. In current times, perceptions have shifted and the industry has mixed feelings about them. I've thought a lot of blogging about design patterns was worth it or not. I used a lot of patterns in my life, there were moments when I was completely okay with design patterns, and other times not so okay. I got some mixed feelings but today I think they are fine. IMHO there are some fairness and some misconceptions. There are hundreds of Design Patterns, there are patterns for everything you can imagine. Usually when people complain about patterns they are talking about OOP patterns, more specifically from the
90s book from the GOF.
Patterns are not limited to OO, there are functional programming patterns, system programming patterns, OS patterns, cloud computing patterns, frontend patterns, and mobile patterns. Lots of these patterns are very similar, at the end of the day not all problems are that different, and are all about ideas and concepts.
Cons
Let's start with the biggest cons, complexity, and performance. Feb 2023, Casey Muratori made a big splash on the internet with his blog post and video, calling out clean code, OOP, and design patterns. Months later, there was a good discussion between Casey and Uncle Bob. Yes, some design patterns will lead to worse performance. However, performance is relative, what is fine for one use case might not be for another use case.
Complexity is another possible issue. You might be wondering why say "possible"? Well, because is not 100% fact that you use design patterns you will get more complexity. Usually, it can happen, depending on the talent density of your company and how much the engineers are seasoned or not, complexity stricks for sure.
Complexity is a difficult matter because it does not solely happen due to design patterns but to other factors.
Complexity happens due to many factors: bloated features, unrealistic pressure to release (feature factories), Bad architecture decisions, lack of proper principles, binary coupling, and many other factors and issues.
Every time you have a problem there is a dilemma...
You have a problem, you know some design patterns, Do you apply the pattern or do you build a custom solution? Such Delima can happen multiple times a day when you are coding and solving the problem, The tricky thing here is that there are multiple dilemmas - for instance:
- Do I use a pattern or try to code something custom as minimal as possible?
- IF decide to use patterns, which one to use?
- When you decide to do something there is a possibility to do it wrong, are you doing it right? Meaning: is this the kind of problem this pattern should be really applied?
Design Patterns at the end of the day are like recipes. Like cooking recipes, song recipes, and knitting recipes, at the end of the day, they are not that different from algorithms. Because algorithms are recipes. Decades of engineering might lead us to better algorithms, so why not leverage that? Unless you have very good reasons and skills, I would not recommend writing your own sorting algorithm. Why patterns should be that different?
One reason could be that patterns shine where your programming language has gaps. For instance, a very common design pattern in Java is the
singleton pattern, to have a single instance of an object, In Scala, this is a built-in feature, there are classes and objects, and the
object is a singleton by default, no frameworks required.
Another reason is that bad decisions with patterns will backfire. Leading to unfulfilled promises of better communication, accidental complexity, premature optimization, and just waste. Adding patterns just for the sake of using patterns is a very bad idea.
It's possible to mitigate these cons by coding POCs, Let's say you don't know if you use composite or chain or responsibility for a workflow problem, well, you can do multiple POCs. One POC with composite, the other with chain, and the other without patterns at all. Compare and run tradeoffs.
Pros
Now, let's look into the pros. There are several pros, however, this pro only happens if you apply the patterns properly, meaning, you apply patterns when the problem has the right fit for the pattern and you do it correctly.
Design Patterns are recipes that have been applied over the years, Unfortunately, you do not easily find code samples for new languages, however is all about ideas and concepts that can be and should be applied to most languages.
Design patterns provide solutions and leverage to common problems, they are design building blocks, which can be done with elegance and if done right, reduce the cognitive load, making it easier to make sense of the design and code and therefore improve communication.
If you know how to use a
Builder, just saying the word "builder" is enough for you to know what I'm talking about, this saves time in conversations and reading the code.
Software Architecture and Design
Patterns are important for
software architecture and design. Knowing patterns allows you to be a better engineer and a
better architect. Basic patterns allow you to have ideas and evolve to more advanced patterns like the
Tolerant Reader or
Lazy Loading used in frameworks like Spring, Hibernate, and even in frontend frameworks like React for instance.
Patterns are standards. I have some issues with the word standard because people take anti-patterns, and bad code, bad decisions that are everywhere and call standard but besides that, patterns are standards. Now, sometimes standards will let you down, will introduce inefficiencies, and will not be the right solutions, some problems require different solutions, especially problems at scale. When the standard is right, you gain leverage but might lose flexibility. By deciding to design something custom you might gain flexibility but with the cost that will increase cognitive load since people will need to make sense of your code.
Now, your solution might not be simple, but that might be okay depending on the use case and the performance gains. Is hard to generalize this thing because every single problem and use case is different.
Don't blame your tools
One could argue design patterns are not tools. They are skills, however skills are tools too. Being an engineer or software architect you are the product, you need to get better. To produce better solutions you need to improve. There are many tools we can give in your toolbox. Design patterns should be another tool. Would you use a hammer for everything? No. The same should be true for design patterns.
Design Patterns was big in the 90s and early 2000s because OOP was big as well. Success and mainstream often lead to lots of misuses. The very same happened to
agile, and is a wasteland now, this is a good reason to not blame your tools, just because there are a lot of people doing it wrong does not mean is bad. The real learning would be improving the decision criteria on when to use and when not to use a pattern.
Lots of bad PR design patterns have to do with people using OOP wrongly as well. OOP is fine, and classes are fine. Sometimes your design skill needs to evolve, How can you tell something is good or bad without experimenting with it? Nothing beats experience and practice.
In case you want a conclusion... Should we use design patterns? Yes but with caution. Make POCs first, ask for a senior engineer or architect to review, learn other patterns, try to fix the problem without any pattern, show code to others, have design sessions, and promote the right learning culture. Code all patterns you can by yourself, go deep, make tradeoffs analysis, and always have an open mind. When someone is talking good or bad about something always ask why and what is the context.
Cheers,
Diego Pacheco