Book review: Building Evolutionary Architectures

Key Takeaways
           Three primary aspects of evolutionary architecture: fitness functions, incremental change and appropriate coupling

  • Design for change on multiple dimensions (technical, data, security and operational)
  • Combine DevOps (Continuous Delivery) practices with fitness functions to verify the architecture     
  • Migrate to another architecture for good reasons (for example better team structure and operational isolation), not because “it’s the current trend”

Building Evolutionary Architectures is a promising title for a book. I was also triggered and wanted to read the book. This is a review of the book with my own humble opinion. First a short description of the chapters is given.
Chapter 1 - Software Architecture
A definition of evolutionary architecture is described, which states that it supports guided, incremental change across multiple dimensions. These changes are guided by so-called fitness functions, which provides an objective integrity assessment of some architectural characteristics. In this case architecture aims, the “-ilities”. The dimensions being technical, data, security and operational.
Chapter 2 - Fitness functions
There are several categories of fitness functions, examples:
Atomic vs Holistic (singular context or shared context, assessing one or more aspect(s) of architecture. Examples: unit test verifying modular coupling, security and scalability
Triggered and Continual (so the way they are executed)
Static vs Dynamic (fixed outcome expected vs shifting results)
Automated vs Manual
Domain specific
it is advised to identify these fitness functions as soon as possible.
Chapter 3 – Engineering incremental change
This chapter is mostly of getting the DevOps in place. This is of course an important aspect of doing evolutionary architecture. It goes into continuous delivery and deployment pipelines. And putting fitness functions into the pipelines to verify the architecture. It describes some deployment pipeline patterns.
Chapter 4 – Architectural coupling
Describes the fundamental aspect of architecture: how the pieces are connected and rely on each other. It begins to describe the concepts of modules (logical grouping of code), components (physical packaging of modules). Examples of components: library (with compile time dependency), service (i.e. soap/http).
Another aspect is the functional cohesion where an architectural quantum is an independently deployable component with high functional cohesion, which includes all the structural elements required for the system to function properly. For example in a monolithic architecture this is the entire application. In a microservice architecture this is a microservice and all its dependent parts.
Architectural styles are described:
* Big ball of Mud (system with highly coupled components with no modularity)
* Monoliths (unstructured and modular monoliths)
* Layered architecture
* Microkernel (consisting of core system with plugin components, i.e. Eclipse)
* Event Driven Architectures (type broker or mediator)
* Service Oriented Architectures
* Microservices
* Serverless architecture, types: BaaS (Backend as a Service) and FaaS (Function as a Service)

The book also mentions the service-based architecture style which is most similar to microservices but differs in granularity (larger context), monolithic database and integration middleware. These styles are scored against Incremental change, guided change with fitness functions and appropriate coupling. Microservices is scored as the best architecture for an evolutionary architecture.

Chapter 5 – Evolutionary data
Data is an important dimension when building evolutionary architectures. It describes some parts of database design to consider: evolving schemas, expand/contract pattern.
It is further stated that the database world is far behind the software development world (like tooling in test, refactoring, pipelines).
Transaction is another important form of coupling which architects must consider. Therefore transactional boundaries contexts must be limited,
Chapter 6 – Building evolutionary architectures
This chapter describes the techniques to build an evolutionary architecture. It has three big steps:
1) Identify dimensions affected by evolution (so the dimensions to protect)
2) Define fitness functions for each dimension
3) Use deployment pipelines to automate fitness functions
This is easier on greenfield projects than on existing architecture. Architects face the following problems:
* Highly coupled systems
* COTS (Commercial off-the-shelf) applications don’t support evolution well (most of the time)
* Decomposing a monolith is not only about breaking the classes into smaller pieces, but breaking transactional contexts is hard.
Some partitioning techniques to break up a monolith into services are: business functionality groups (Conway’s Law), transactional boundaries, deployment goals (some departments may want to deploy more often than others)
The following guidelines for building EA are discussed:
* Remove Needless Variability (example: immutable infrastructure refers to systems defined entirely programmatically)
* Make decisions reversible (examples: blue/green deployments in DevOps, feature toggles)
* Prefer evolvable over predictable (the unknown unknowns do appear in each project, there is no crystal ball)
* Build anticorruption layers (abstracting functionality within a semantic API, i.s.o. depending on a syntax of a particular API)
* Use Service Templates (technical aspects that are common, i.e. logging, monitoring)
* Build sacrificial architectures (throw away poc’s and learn from it)
* Mitigate External Change (pull external library changes and control)
* Prefer Libraries to Frameworks (libraries introduce less coupling, frameworks call your code)
* Prefer continuous delivery to snapshots
Chapter 7 – Evolutionary architecture pitfalls and antipatterns
Antipatterns are defined in this book as solutions that initially look good but turn out to be a mistake. Several are discussed:
* Vendor King (architecture build around a vendor product)
* Last 10% trap (first 90% are easy within package software, platforms and frameworks)
* Code reuse abuse (reuse costs a lot and practically no reuse, focus on usability)
* Inappropriate governance (in modern environments do not govern on a single technology stack, servers are cheaper these days)
* Reporting (example: operation through layered architecture, but reporting directly coupled to database directly. Possible solution: event streaming also for reporting database)
Chapter 8 – Putting evolutionary architecture in practice
The last chapter describes the steps required to implement a EA, because it has impact on factors not only concerning software.
There are also organizational factors. Organize domain-centric teams which are cross-functional teams, leading to different roles: business analysts, architecture, testing, operations, data.
Organize around business capabilities i.s.o. technical architecture.
Model the work around products rather than projects. Projects lead to isolation of operational aspects, whereas by thinking of software as a product, the team stays associated with their product.
Use consumer driven contracts to test that integration points between providers and consumers of services are not broken. Culture is also a relevant factor that often needs to be changed within teams. Creating a culture of experimenting (examples: bring ideas from outside, spikes, encourage explicit improvements, create innovation time, connect developers with end-users).
Also some strategies on where to start with EA are discussed. Low-hanging fruit (maybe already fairly decoupled components that implement fitness functions and incremental change). Another is to select highest value first.
The book ends with some reasons why companies should decide to build an EA. One of the reasons is that otherwise a company will likely to fail as more agile startups address the changing ecosystem better. Some other reasons are scalability, fast cycle time to get a competitive advantage and possibilities to choose better suited architectures for different parts.

The book is a good read, however it does not describe new concepts (at least for me). Do not expect deep technical solutions. It does a good job of describing high level concepts. For me the concept of a fitness function was new, at least the name. The idea behind the concept (automatic testing) is not new of course, but it introduces a new level on architecture level. I also like amount of patterns and the advices the book describes.
In the end it gave me some good new insights and tools regarding evolutionary architectures. Reading about architecture is the easy part, doing it still remains a pretty complex job after all, but a job I like.

No comments:

Post a Comment