Architectural Styles - The Tailor-Made Pattern Language
In our previous post, we discussed how the business problems we tackle through software architecture seldom align perfectly with just eight sizes (the conventional architecture patterns). More often than not, any system’s architecture that adheres to a specific pattern tweaks it significantly. This deviation brings forth two critical challenges that the Tailor-Made approach seeks to resolve:
Firstly, the prevalent tendency to oversimplify diverse and distinct systems filled with numerous modifications leads to miscommunication and ambiguity in portraying the architecture’s intricacies. Secondly, relying on a pattern-based language holds value only if there’s a unanimous consensus regarding the pattern’s definition.
We have already shown that an architecture can essentially be defined by its constraints it is, consequently, imperative to embrace Dr. Roy Fielding’s notion of the “architectural style.” Such an adaptation ensures clearer pattern definitions and more transparent architectural communication. Moreover, it unlocks a vast spectrum of architectural styles, moving beyond the confines of the standard eight patterns.
This post is part of a series on Tailor-Made Software Architecture, a set of concepts, tools, models, and practices to improve fit and reduce uncertainty in the field of software architecture. Concepts are introduced sequentially and build upon one another. Think of this series as a serially published leanpub architecture book. If you find these ideas useful and want to dive deeper, join me for Next Level Software Architecture Training in Santa Clara, CA March 4-6th for an immersive, live, interactive, hands-on three-day software architecture masterclass.
To eliminate the vagueness surrounding patterns and to communicate the breadth and specifics of an prescribed architecture more effectively, the Tailor-Made approach is to champion the concept of architectural styles.
“An architectural style is a coordinated set of architectural constraints that restricts the roles/features of architectural elements and the allowed relationships among those elements within any architecture that conforms to that style.” —Dr. Roy Fielding
D. E. Perry and A. L. Wolf introduced the idea of an architectural style in their 1992 piece, “Foundations for the study of software architecture.” They defined it as an abstraction comprising element types and formal aspects from an assortment of specific architectures. The significance of this concept lies in its ability to encapsulate key architectural decisions. With our emphasis on shaping architecture through the composition and amalgamation of architectural constraints, every unique assemblage of constraints births a new architectural style.
Fielding, while advancing existing work, scrutinized the term “style.” When we discuss someone’s coding style, we often allude to their personal preferences and conventions (tabs vs spaces, variable naming conventions, etc.). Using “style” might insinuate that a particular style emanates from individualistic stylistic choices. However, a deeper understanding of “style” emerges when we delve into architectural usages from diverse eras and locales. Here, styles reflect design constraints — be it available resources, construction methodologies, societal norms, or even the specific requirements or whims of local leadership. In essence, in building architecture, styles are the manifestation of design constraints. Numerous scholars have further accentuated this perspective, viewing the convention set used to interpret architectural descriptions as defining an architectural style.
In our context, any distinct mix of constraints leads to the creation of a novel architectural style. In this series we will introduce various architectural styles. Tailor-Made Software Architecture focuses on devising an architecture tailored to synchronously align with your project and organizational needs. It’s anticipated that in most scenarios, you’ll be crafting novel architectural styles by blending constraints, other architectural styles, or even a mix of both. This new style would be christened and documented formally, enabling crystal-clear communication regarding its definition.
Since referring to a named set of constraints as a style makes it easier to communicate the characteristics of common constraints, we use architectural styles as a method of abstraction, rather than as an indicator of personalized design. -Dr. Roy Fielding
Abstract Styles - Patterns
A great deal of software architecture literature focuses on component patterns (e.g. microservices, event-driven, etc.), but we generally lack a singular definition of any of these. Consequently, diverse sets of architectural styles that share superficial topographical similarities become lumped under a single label. To compound matters, this superficial look purely at topography creates an environment creates a poor lowest-common-denominator definition of any given pattern. Pick a dozen implementations of the 8-9 common architectural patterns in the wild and you will see a dozen “flavors” of that pattern. Each implementation differs based on extensions, tweaks, modifications, or omission of some number of architectural constraints. Without a mechanism to precisely describe any definition or implementation of an architecture (ultimately an architectural style), we may miss core make-or-break constraints of a pattern and where, decision points or optional constraints come into play, we lack a mechanism to evaluate the impact of any decision or variation at design-time.
To address this problem, the Tailor-Made Model defines each of the common and widely-used patterns by a core set of constraints. Further building on the work of Perry and Wolf we numerically weight the trade-offs, this weighting has been calibrated and tuned based on the architecture scorecards published by Neal Ford and Mark Richards in their 2020 book “Fundamentals of Software Architecture.” It is important to point out that these are merely the core constraints, not the totally of constraints an architect might ultimately apply when deriving their Tailor-Made architectural style. Every pattern can–and should–be extended additional constraints. As such, they are merely abstract styles. Abstract styles, much like abstract classes in the OO paradigm, act as expressions of general/root concepts from which more specific styles may be derived. It is important to note that an abstract style is not necessarily a comprehensive definition of the pattern. Complex patterns like microservices or event-driven require a number of decisions to be made in the form of optional constraints, each with different trade-offs (e.g. an event-driven architecture can utilize queues or pub-sub; persistent or transient, etc.). These optional constraints extend the abstract style, but don’t necessarily define it hence they belong in concrete, derived styles and not in the root/abstract style. The core constraints of an abstract style only represent the minimum set of constraints to realize the general strengths and weaknesses of the pattern. e.g. take away separation of concerns constraint and technical partitioning constraint of the layered monolith and it ceases to be a layered monolith; it becomes a big ball of mud. Likewise, take away the independent deployability of the microservices style, you no-longer have microservices - you have a distributed monolith.
This extends our set of tools for architectural composition to include not only fine-grained constraints, but also coarse-grained styles. Although an architect may entirely define an architectural style entirely by set of constraints, generally well-established patterns form a more productive starting point; that is, they are style templates that we can extend and modify to define a tailored architecture for any given system.
In the upcoming posts of this series, we will first define each pattern as a style defined by its core constraints. These styles will serve as foundational keystones for architectural design, which can be further elaborated upon through supplementary constraints. While doing so, we’ll delve deep into each constraint, shedding light on the architectural compromises they entail as well as making explicit the team, organizational, and environmental dependencies they carry.