BT

Facilitating the Spread of Knowledge and Innovation in Professional Software Development

Write for InfoQ

Topics

Choose your language

InfoQ Homepage News Fitness Functions to Ensure Architectural Goals Are Met

Fitness Functions to Ensure Architectural Goals Are Met

This item in japanese

With fitness-function-driven development, we can write tests that measure a system’s alignment with architectural goals, similar to how we use test-driven development (TDD) to verify that features conform to desired business outcomes, Paula Paul and Rosemary Wang write in a blog post, describing the basic ideas of fitness functions, how to get started, and examples of how different architecture qualities can be verified.

Paul and Wang, both working for Thoughtworks, emphasize that independently of functional requirements, architecture standards are in constant evolution with goals and constraints changing and they refer to the book Building Evolutionary Architecture:

An evolutionary architecture supports guided, incremental change as the first principle across multiple dimensions.

To support this evolution, Paul and Wang believe that fitness functions can help in finding how well a system meets specified architecture goals and constraints in an automated way. One example is logging, which often is an afterthought and lacking important information. By leveraging a fitness function, we can ensure that the logging is well-structured and contains enough information to be useful.

The author’s recommendation when starting using fitness functions is to begin by gathering input from all stakeholders to get an understanding of what they consider to be the most important architectural attributes. These should then be grouped into common themes like resilience, security, operability and stability. Sometimes this work exposes conflicting goals; one example is stability and agility, which often are diametrically opposed. Stability is achieved by establishing control over change, while agility is achieved by reducing barriers to enable change. To overcome this the motivation for different attributes must be evaluated and qualities most important for the organization prioritized.

All collected fitness functions should describe their intent using an objective metric meaningful to teams and stakeholders. This will help the teams in measuring technical debt but also to avoid architectural drift. All functions should be drafted in a testing framework and included in appropriate delivery pipelines. All new software will now pass the fitness functions and Paul and Wang see this as a natural extension of continuous integration.

One example of a fitness function is code quality where modifiability, manageability and adaptability can be measured in order to prevent code with too low quality from being deployed to production.

describe "Code Quality" do
    it "has test coverage above 90%" do
        expect(quality.get_test_coverage()).to > .9
    end
    it "has maintainability rating of .1 or higher (B)" do
        expect(quality.get_maintainability_rating()).to < .1
    end
end

Another example is performance. Paul and Wang note that this if often done by a separate team which can extend delivery timelines and with results not always available to developers. Implementing automated performance tests as fitness functions and added to the build pipelines means tests are run early with results immediately accessible.

In addition to these two examples, the authors also provide examples for resiliency, observability, compliance, security and operability.

Paul and Wang conclude by emphasizing that architecture, like business capabilities, can be expressed in code by using fitness functions and mention three benefits they believe will come from using them:

  • They can objectively measure technical debt and drive code quality. They also provide real-time feedback when changes are made in fitness functions due to for instance new security or operational standards.
  • They can inform about coding choices for interfaces, events, and APIs related to downstream processes. When applying the strangler pattern they can be useful to verify that requirements are met when business logic is decoupled.
  • They can communicate architectural standards in the form of code, thus helping developers to deliver features better aligned with the architecture. In the same way users can request a feature change, an architect can request changes to some architecture concern which will then be verified during the build process.

Ben Morris claims in a blog post that what’s important is how we are using fitness functions, not the actual metrics. For him they can provides a base for a more iterative approach to architecture and steer an evolving design towards the desired outcome.

Vijini Mallawaarachchi discusses generic requirements for fitness functions and how to find what functions to use for a given problem.

Tim Sommer writes that fitness functions can be used to add constraints on different characteristics of an architecture, thus guiding the way the architecture evolves.

Rate this Article

Adoption
Style

BT