The first principle of evolutionary architecture is support for incremental non-breaking changes. Microservices architecture is one great example of such an architecture, Rebecca Parsons and Neal Ford claims describing characteristics and principles of evolutionary architectures. They both believe that microservices meet the principles of an evolutionary architecture because of the strong bounded context principle which comes from Domain-Driven Design (DDD).
Ford, as well as Parsons working for Thoughtworks, notes that their work with a definition is still in progress, but that it currently is defined as:
An evolutionary architecture supports continual and incremental change as a first principle along multiple dimensions
Evolutionary architectures share many characteristics, of which Parsons and Ford describes a few:
- Modularity and Coupling: Support for modularity, often at the technical architecture, enables separating components along well defined boundaries. This in turn simplifies making non-breaking changes, an important benefit for a developer making those changes. In contrast, they note that the Big ball of mud architecture is lacking this modularity and therefore doesn’t support evolution.
- Organized Around Business Capabilities: Modularity at the domain level is increasingly done using Domain-Driven Design (DDD). Partitioning along domains in microservices is significantly different compared to SOA where partitioning strictly is done along technical layers.
- Experimentation: Parsons and Ford notes that this is one of the superpowers that evolutionary architectures deliver to the business. Changes to an application becomes trivial allowing for A/B testing and Canary releases, among others. Also, a microservices architecture can be designed to allow for several versions of the same service to run at the same time. This allows for experimentation and ultimately enables usage of Hypothesis-Driven Development.
Another way of looking at evolutionary architectures is through principles. These principles describe characteristics of either architectures or methods for designing an architecture. Principles focusing on when architectural decisions are made include:
- Fitness Functions: An architectural fitness function specifies important characteristics of a system. Examples include levels of uptime, throughput, availability and security needed. One way of visualizing is using a radar chart for the various functions used.
- Bring the Pain Forward: Doing things in a project that may cause pain earlier and more often will more rapidly identify the issues causing this and will encourage automation to remove the pain. Continuous delivery practices like deployment pipelines and database migration are examples that make evolutionary architecture easier.
- Last Responsible Moment: The time when decisions occur is a major differentiator between traditional and evolutionary architecture. In a traditional architecture, decisions about e.g. structure, technology stack and communication patterns are taken early, before writing code. In an evolutionary architecture, we wait for the last responsible moment before making decisions. Deciding when that moment occurs can be hard but this is where fitness functions can provide guidance. Decisions with a significant influence on the architecture or with an impact a critical success factor for the project should be made earlier.
Parsons and Ford concludes by stating that architecture isn't an equation but rather a snapshot of an ongoing process, emphasizing how critical operational awareness is to evolutionary architecture, reffering both to Continuous Delivery and the DevOps movement.
Ford recently did a webinar talking about evolutionary architectures.
At QCon London 2015 Parsons held a presentation about the same subject.
Jimmy Bogard wrote 2010 a blog post about Evolutionary Architecture.