Why a pattern language for microservices?
Find critical and often overlooked aspects of a solution to a problem.
Back in 1986, Fred Brooks, author of The Mythical Man-Month, said that in software engineering, there are no silver bullets. In other words, there are no techniques or technologies that if you adopted would give you a 10X boost in productivity. Yet 30 years later, developers are still arguing passionately about their favorite silver bullets, absolutely convinced that their favorite technology will give them a massive boost in productivity.
A lot of arguments follow the Suck/Rock dichotomy, which is a term coined by Neil Ford. They often have this pattern: If you do X then a puppy will die. Therefore, you must do Y. For example, synchronous vs. reactive programming, object-oriented vs. functional, Java vs. JavaScript, REST vs messaging. Of course, reality is much more nuanced. No technology is a silver bullet. Every technology has drawbacks and limitations, which are often overlooked by its advocates. As a result, the adoption of a technology usually follows the Gartner hype cycle.
The underlying reason for these polarized and hyped arguments about technology is that humans are primarily driven by their emotions. Jonathan Haidt in his excellent book The Righteous Mind: Why Good People Are Divided by Politics and Religion uses the metaphor of an elephant and its rider to describe how the human mind works. The elephant represents the emotion part of the human brain. It makes most of the decisions. The rider represents the rational part of the brain. It can sometimes influence the elephant but it mostly provides justifications for the elephant’s decisions.
We—as in the software development community—need to overcome our emotional nature and find a better way of discussing and applying technology. A great way to discuss and describe technology is to use the pattern format. As presented in my video course, Event-Driven Microservices, a great way to discuss and describe technology is to use the pattern format. A pattern is a “reusable solution to a problem that occurs in particular context”. This is already a major improvement because it introduces the idea of a context. Thinking about the context of a problem is important because, for example, a solution that solves the problem at the scale of Netflix might not be the best approach for an application with fewer users.
The value of patterns goes far beyond requiring you to consider the context of a problem. They force you to consider other critical yet frequently overlooked aspects of a solution. A commonly used pattern structure includes three especially valuable sections: forces, resulting context, and related patterns.
The forces section describes the issues that you must address when solving a problem in a given context. Forces can conflict so it might not be possible to solve all them. For example, code must be easy to understand and have good performance. Code written in a reactive style has better performance than synchronous code, yet is often more difficult to understand. Explicitly listing the forces is useful because it makes it clear what issues need to be solved.
The resulting context section describes the consequences of applying the pattern. It consists of three parts: the benefits of the pattern including the forces that have been resolved; the drawbacks of the pattern including the unresolved forces; and the new problems that have been introduced by applying the pattern. This provides the reader with a more complete and less biased view of the solution, which enables them to make better design decisions.
The related patterns section describes the relationship between this pattern and other patterns. One kind of related pattern is the pattern that motivates the need for this pattern. Another kind of related pattern are patterns that provide alternative solutions to the same problem. For example, the Monolithic Architecture pattern and the Microservice Architecture pattern are alternative ways of architecting an application. You pick one or the other. The third kind of related pattern are those patterns that solve problems introduced by applying the pattern. For example, if you apply the Microservice Architecture pattern you must then apply numerous other patterns including service discovery patterns and the Circuit Breaker pattern. The explicit description of related patterns provides valuable guidance on how to effectively solve a particular problem.
A set of related patterns often forms what is termed a pattern language. I’ve been developing a pattern language for microservices. The goal is to help you decide whether microservices are a good choice for your application, and, if they are, help you use microservices effectively. You can see the pattern language by visiting microservices.io. It is very much a work in progress and it would be great to get your feedback.