In the past few months, I have been learning software design patterns and reading the book Head First Design Patterns: A Brain-Friendly Guide 1st Edition by Eric Freeman and Elisabeth Robson. Here I’d like to share what I’ve learned.
Table of Contents
What is a Design Pattern?
From Wikipedia: “A pattern is a regularity in the world, in human-made design, or in abstract ideas. As such, the elements of a pattern repeat in a predictable manner. In computer science, a software design pattern, in the sense of a template, is a general solution to a problem in programming. A design pattern provides a reusable architectural outline that may speed the development of many computer programs.”
The goal of applying design patterns in software engineering is to solve a problem. If you can solve a problem effectively without a design pattern, don’t force it. For example, if your problem is to print
Hello World!, you don’t need a complex pattern to do so (see more in anti-patterns later). Most complex problems we encounter have been solved by others in the past. There is nothing new under the sun. Design patterns are discovered, not created, by software engineers who found themselves encounter a recurring problem, reflected on their experience, and summarized a reusable template solution, so that others don’t have to reinvent the wheel.
Knowing when a pattern applies is where experience and knowledge come in. It is important to be able to first recognize design patterns in existing code, understand the context they are applied, and the problems they aim to solve. As we are more familiar with design patterns and their application, we can start to introduce a pattern to our design when we realize a simple solution may not meet our needs, or remove a pattern that provides extra flexibility that is no longer needed.
One of the biggest benefits of design patterns is the power of shared vocabulary. A design pattern is a highly condensed abstraction that carries rich meaning and implication. Discussing software design from the perspective of design patterns can help keep us from diving too deep in the implementation details. It is also more concise and efficient to use design patterns when communicating architecture design with peers. Furthermore, by following naming conventions in design patterns, our code can be more readable and easier to debug.
OO principles and OO patterns
You probably have heard of some OO principles before, such as Open-closed principle or Dependency Inversion Principle (see Design Principles). OO principles are guidelines, not rules, that help avoid having a bad design. OO patterns apply OO principles and provide reusable solutions for recurring problems.
While design patterns tell us how to solve a problem with a GOOD solution, anti-patterns tell us how to solve a problem with a BAD solution. An anti-pattern always looks like a GOOD solution, but then turns out to cause undesired behaviors when it is applied. Some anti-patterns are:
- Spaghetti code: very unstructured and difficult-to-maintain source code, caused by several factors, such as volatile project requirements, lack of programming style rules, and insufficient ability or experience.(Wikipedia)
- Golden hammer: assuming that a favorite solution is universally applicable. “If the only tool you have is a hammer, to treat everything as if it were a nail”. (Wikipedia)
Recognizing anti-patterns and avoiding them also requires experience and knowledge.
Software design is a matter of taste
When people say “Software design is a matter of taste“, what they mean is NOT that “design is subjective preference”. There is a huge difference between subjective preference and taste. Taste in this context means “The ability to recognize and appreciate what is beautiful, excellent, or appropriate.” As this definition suggests, first it is an ability that is learned, not innate. Second, it emphasizes on both verbs recognize and appreciate. Third, the adjectives beautiful, excellent, or appropriate can be translated into software design as clean and efficient code. In practice, we always need to make trade-offs between flexibility and complexity, safety and transparency during design, and most of the time, there is no unique BEST solution. Discussing pros and cons of design patterns in application not only improves our understanding of the problem we try to solve but also deepens our appreciation of patterns.
Software design is both art and science.
I am writing a design pattern tutorial with examples and real-production use cases, and will be sharing this tutorial later.