“.. the high-level language embodies the constructs wanted in the abstract program and avoids all the lower ones, it eliminates a whole level of complexity that was never inherent in the program at all” – Fred Brooks, No Silver Bullet
High-level programming languages (over assembly) increased programming efficiency by more than 5x (No Silver bullet, p. 5). Patterns provide the same benefit by creating an even higher level of design.
Fredrick Brooks asserts in that the need for programmers will never disappear. There will always be a need to understand the problem being solved. Advances like AI and object-orientation are tools that allow us to abstract details and design at a higher level.
Patterns are a powerful tool for just that. Patterns are “descriptions of communicating objects and classes that are customized to solve a general design problem in a particular context” (Design Patters, p. 3)
More simply, patterns are a shared vocabulary for common problems and their solutions.
Patterns can be applied from local decisions to the entire system structure. A rich pattern vocabulary enables designers to choose the granularity of design to discuss without losing shared understanding or requiring excessive detail.
For example, rather than explaining an arrangement of hinges, planks, glue, screws, a knob, etc, the sum is called a door. Similarly, saying “I used the command pattern” conveys a structure and problem-type better than describing all the parts.
Further, consistent naming improves verbal and code comprehension. The pattern only needs to be explained once and can then be compactly referenced. Even if the reader is not familiar with the pattern, the standard naming lets them look it up and understand a large chunk of code faster than if they had to infer the structure from its parts.
Teaching & Learning
Patterns can also raise the ability of the whole community.
Patterns refine the knowledge of experts in a way that is intentionally teachable. This means they also serve to explain different design decisions without need for complex and contextual examples, which not everyone will have access to.
This allows designs to disseminate and design discussions to move to a higher level. For example, few programmers think twice (anymore) before using patterns like Id fields in a DB, iterators for safe list traversal, or factories for dependency inversion.
Patterns can be discussed from many angles, but a definition should include a
- Problem(s) solved
- Solution form
Here are some foundational patterns.
|Command||Decoupling action declaration time from execution time. I.e. undo/redo, actions queues, callbacks||Encapsulate actions as objects that expose a consistent handle. Typically, all command objects implement Run().|
|Strategy||Algorithm steps can be implemented in different ways and used interchangeably.||Create a common interface for the swappable algorithm steps. Step implementations are consumed via the interface.|
|Singleton||State of an object is important. I.e. caching, slow object load time, concurrency conflicts||Only expose the singleton object through a single global point of access (e.g. a static class).|
|Façade||Provide a simple and specific interface to a set of general or complex components. E.g. config access, database access||Create an intermediary object / module that exposes a limited set of interactions and hides the original components|
|Decorator||Attach additional responsibilities to a component dynamically. Often used to separate core functionality from shared concerns. E.g. authentication, logging, UI transforms||Create an object that implements the same interface as the original. It performs the added functionality then passes to the original object.|
|MVC (Model View Controller)||Need to represent or manipulate common data in several ways. E.g. user interfaces, data transforms||Create separate components for data (Model), the presenting the data (Views), and operating on the representation (controller). Controllers connect models to views, managing the flow and state to keep logic separate from the data.|
|Layering||Differentiate distinct groups of functionality. Typically, used to create order with a large number of components.||May name components according to layer or contain each layer in a namespace. In general, each layer has a distinct responsibility and rules for how it can communicate with other layers. Rules can be conventional or enforced by static analysis.|
There are numerous quality books on patterns. However, the seminal classic is Design Patterns by Erich Gamma, Richard Helm, Ralph Johnson, and John Vlissides. The book is referenced enough that the authors are known as the Gang of Four or GoF. It lays out the foundational patterns and many patterns books follow its format.
Patterns improve efficiency by forming a common vocabulary and enabling us to design at a higher level. Their common vocabulary also facilitates design discussion and knowledge transfer.
- Design Patterns, Gang of Four
- Patterns of Enterprise Application Architecture, Martin Fowler
- Pattern-Oriented Software Architecture, Frank Buschmann et. al.
- Agile Principles, Patterns, and Practices, Robert Martin
- No Silver Bullet, Fred Brooks
- The Pragmatic Programmer, Andy Hunt & David Thomas, section 29