Software architecture patterns - Layered, Event-driven, Microkernel, Microservices, Space-based and CQRS

Last updated Oct 1, 2022 Published Oct 17, 2020

This is a short post on the book Software architecture patterns by Mark Richards, published by O’Reilly. The book catalogs five architectural styles: Layered, Event-Driven, Microkernel, Microservices and Space-Based. For each of them the author goes through six aspects and rank them [1], that collects a broader named:

  • Overall agility
  • Ease of deployment
  • Testability
  • Performance
  • Scalability
  • Ease of development

It covers in high level scenarios for each pattern to be used and also diagrams that helps the reader to understand the details. Therefore, the book does’t have code examples or concrete implementations, which might open the definition to different implementations. Furthermore, for building up this material I used heavily the content provided by the original author. For each architectural style I used the original definition, and in addition to that, I merged my thoughts on each one of them.

Software architecture in general is perceived something that is far away from developers, which I strongly disagree.

Layered

Components within the layered architecture pattern are organized into horizontal layers, each layer performing a specific role within the application. Popular frameworks for any language that uses the MVC (3 layers) as a foundation usually are bound to the layered architecture.

One of the powerful features of the layered architecture pattern is the separation of concerns among components.

The layers of isolation concept means that changes made in one layer of the architecture generally don’t impact or affect components in other layers, which in the MVC style follows this definitions. The view is the layer that display data and receives the user interaction, the controller handles the data from the view, and the model interacts with the database.

Web frameworks that follows this approach:

  • Laravel
  • CakePHP
  • Codeigniter

Event-driven

The event-driven architecture pattern is a popular distributed asynchronous architecture pattern used to produce highly scalable applications

The event-driven architecture pattern consists of two main topologies, the mediator and the broker. The event-driven architecture pattern is a relatively complex pattern to implement, primarily due to its asynchronous distributed nature.

Microkernel

The microkernel architecture pattern (sometimes referred to as the plug-in architecture pattern) is a natural pattern for implementing product-based applications. A product-based application is one that is packaged and made available for download in versions as a typical third-party product.

The core system of the microkernel architecture pattern tradition‐ ally contains only the minimal functionality required to make the system operational.

Perhaps the best example of the microkernel architecture is the Eclipse IDE. However, once you start adding plug-ins, it becomes a highly customizable and useful product. Another example is wordpress, users can download as many plugins as needed. Pat Kua [2] in his talk named the following softwares that were built using microkernel architecture:

One great thing about the microkernel architecture pattern is that it can be embedded or used as part of another architecture pattern.

For product-based applications, the microkernel architecture pat‐ tern should always be your first choice as a starting architecture.

Microservices

The microservices architecture pattern is quickly gaining ground in the industry as a viable alternative to monolithic applications and service-oriented architectures.

The first of these concepts is the notion of separately deployable units, perhaps the most important concept to understand with this pattern is the notion of a service component. Designing the right level of service component granularity is one of the biggest challenges within a microservices architecture. James Lewis and Martin Fowler defined those components as: “a component is a unit of software that is independently replaceable and upgradeable”.

Another key concept within the microservices architecture pattern is that it is a distributed architecture, meaning that all the components within the architecture are fully decoupled from one other and accessed through some sort of remote access protocol (e.g., JMS, AMQP, REST, SOAP, RMI, etc.).

While there are literally dozens of ways to implement a microservices architecture pattern, three main topologies stand out as the most common and popular: the API REST-based topology, application REST-based topology, and the centralized messaging topology.

Spaced-based

In any high-volume application with an extremely large concurrent user load, the database will usually be the final limiting factor in how many transactions you can process concurrently. The space-based architecture pattern is specifically designed to address and solve scalability and concurrency issues.

This pattern gets its name from the concept of tuple space, the idea of distributed shared memory. High scalability is achieved by removing the central database constraint and using replicated in-memory data grids instead.

The space-based architecture pattern is a complex and expensive pattern to implement. It is a good architecture choice for smaller web-based applications with variable load (e.g., social media sites, bidding and auction sites).

CQRS - Command Query Responsibility Segregation

Command Query Responsibility Segregation is focused on splitting the write data from the read data, allowing the decoupling of those two operations [3]. Microsoft documentation, compares how the CRUD (Create, Read, Update and Delete) operations fit in a CQRS architecture, in the a few points should be taken into account. The first is that CRUD usually operates in the same entity, all the operations are made in the same system, from their own documentation:

For example, a data transfer object (DTO) representing a customer is retrieved from the data store by the data access layer (DAL) and displayed on the screen. A user updates some fields of the DTO (perhaps through data binding) and the DTO is then saved back in the data store by the DAL. The same DTO is used for both the read and write operations.

Microsoft’s Cloud Design Patterns: Prescriptive Architecture Guidance for Cloud Applications under the section Design Patterns

Having both operations in the same entity, is, some how, standard for most applications that start from scratch, using a boilerplate. For example, in java, springboot by default uses JPA, in PHP, Laravel uses Eloquent, and in javascript, the typed ORM project. All of those tree, operates in a CRUD fashion by default.

Microsoft depicts the following disadvantages of CRUD:

  • Mismatch of read and write operations, adding columns (when talking about relation databases) when writing will affect reading, even tough they are different operations.
  • When working in parallel, conflicts can happen when locking the data to be updated - read can be out dated until the operation finishes.
  • Security can be an issue, as read and write operations are subjected to the same entity - both will share the same security properties at the same time.

References

  1. [1]R. Mark, Software Architecture Patterns. O’Reilly Media, Inc, 2015.
  2. [2]P. Kua, Evolutionary Architecture by Patrick Kua. Devoxx, 2017 [Online]. Available at: https://youtu.be/iDYAtys2oK0
  3. [3]Microsoft, “Command and Query Responsibility Segregation (CQRS) Pattern,” 2015 [Online]. Available at: https://docs.microsoft.com/en-us/previous-versions/msp-n-p/dn568103(v=pandp.10)?redirectedfrom=MSDN. [Accessed: 04-Dec-2021]