The above is a partial set of “ilities” we need to consider while building software. We usually prioritise them depending upon the context we are working on — the kind of product we are building, the customers we are serving, the domain of the product etc. We also need to make sure that they are matched while we deliver our software — either through automated tests as part of the delivery pipeline or through manual testing.
One of the essential requirements for implementing Continuous Delivery is the ability to adapt to changes so quickly and deliver them in small batches. Aforementioned includes changing architecture using one or more of the below techniques:
The book Building Evolutionary Architectures refers to this as Evolvability, i.e. the ability to support guided, incremental change across multiple dimensions. The book uses the analogy of a unicyclist carrying boxes and trying to balance and also reestablishing the balance while adding more boxes.
Visualize a unicyclist carrying boxes: dynamic because she continues to adjust to stay upright and equilibrium because she continues to maintain balance. In the software development ecosystem, each new innovation or practice may disrupt the status quo, forcing the establishment of a new equilibrium. Metaphorically, we keep tossing more boxes onto the unicyclist’s load, forcing her to reestablish balance.
In many ways, architects resemble our hapless unicyclist, constantly both balancing and adapting to changing conditions.
The changes can be due to anything — the changes in the business strategy/requirement or internal changes, e.g. using Docker for deployments, moving from one framework/architecture to another.
The book goes on explaining why it is termed “evolutionary” than, say adaptive, incremental or reactive.
To build architectures that truly evolve, architects must support genuine change, not jury-rigged solutions. Going back to our biological metaphor, evolutionary is about the process of having a system that is fit for purpose and can survive the ever-changing environment in which it operates. Systems may have individual adaptations, but as architects, we should care about the overall evolvable system.
An architectural fitness function provides an objective integrity assessment of some architectural characteristic(s).
- As defined in Building Evolutionary Architectures
These are the functions that denote what matters to us in the architecture allowing us to make the right trade-offs during the development of the system. These are the selected “ilities” — we referred during the beginning of this post — which we keep as a guideline to make decisions depending upon the domain, technical capabilities of the team and a bunch of other factors.
For example, in case of the product that we are building, Good Karma, we wanted to provide the ability for the users to”get things done” from their mobile phone. And to help us distribute and iterate faster, we decided to have a mobile optimised site over having a mobile app.
We decided to use SMS over Push Notifications because the support for Push Notifications outside mobile app is limited even with Service Workers. We had trade-offs with this approach say, limited formatting of the message in the SMS, rigidness w.r.t to the templates for transactional SMSs etc. But we decided to leverage those constraints in our favour.
And going forward, any technical decision that we make needs to be evaluated against these fitness functions. And these fitness functions define what matters for the architecture of the software we are building.
Ideally, these should be tested as part of the delivery pipeline. But sometimes it is difficult to automate. But it is recommended to automate the same as earlier as possible, rather than relying on manual testing.
The rest of the book talks about how to implement changes incrementally and how to create a modular architecture. The book also has a section about evolutionary data — about Evolutionary Database Design. I will cover those in my upcoming posts.