Tighten Evolution Strategy

Updated:

 Note: This is a preview release and subject to change. Feedback welcome! Contact Information and Background (PDF)

also known as: Increase Lifetime Guarantee, Strengthen/Stretch Lifetime Commitment

Context and Motivation

An API runs in production. Its compatibility and extensibility characteristics are expressed in the form of one or more evolution patterns, including Experimental Preview, Aggressive Obsolescence, Limited Lifetime Guarantee, and Two in Production. These patterns differ in the way and the frequency the provider is able to introduce breaking changes.1

Evolution Pattern Map

As an API provider, I want to expand and extend the lifetime, stability, and support guarantees of an API endpoint with its elements (operations, messages) so that existing and new clients can use the API longer.

Stakeholder Concerns (including Quality Attributes and Design Forces)

#maintainability
During their lifetimes, API versions have to be supported and evolved. Security patches are applied, bugs are fixed, and so on. The effort for such activities might not be proportional to the guaranteed lifetime but certainly is related and somewhat coupled to it. Related (sub-)concerns are compatibility and extensibility.
#cost
Effort comes with cost. Operational and capital expenditure, including budget for training, evolution (including documentation), and operations increase as lifetime guarantees are extended.
#flexibility
The more lifetime guarantees are given and the longer the committed time spans are, the less freedom remains with respect to changing product vision and corresponding API designs (for instance, the role of an API in the organization).

According to “Interface Evolution Patterns — Balancing Compatibility and Extensibility across Service Life Cycles”, evolution patterns are confronted with desired qualities such as:

  1. Enhancing compatibility and developer experience
  2. Allowing the provider and the client to follow different life cycles, e.g., a provider can roll out a new API version without breaking existing clients
  3. Minimizing changes to the client forced by API changes
  4. Making it possible for the provider to improve and extend the API and change it to accommodate new requirements
  5. Guaranteeing that API changes do not lead to semantic ‘misunderstandings’ between client and provider
  6. Minimizing the maintenance effort to support old clients [Lübke et al. 2019]

Initial Position Sketch

The following provider specification does not yet define any life cycle guarantee (notation: MDSL):

API provider SampleAPIProvider1 
  offers SomeDemoContract 
    at endpoint location "http://www.testdomain.io:80/path/subpath"
    via protocol HTTP binding resource SampleAPIProvider1Resource

Clients are not clear about what they can expect from the provider:

This “refactoring”2 targets API endpoints and their API Descriptions (including business and technical contract between a provider and its clients). It may also affect any Service Level Agreement (SLA) that accompanies or is part of such API Description.

Smells / Drivers

Lack of trust and confidence
Client developers decide not to use the API because it comes across as unstable and subject to change often (or disappear).
Client community smaller than expected
The provider receives less client traffic than expected and hoped for. Client feedback indicates that the API functionality is appreciated, but API usage is not considered a viable design option due to missing stability and support guarantees.

Instructions (Steps)

The following transitions and combinations of evolution patterns to increase guarantees make sense:

  • Upgrade from no guarantee to Experimental Preview.
  • Transition from Experimental Preview to Aggressive Obsolescence.
  • Become more assertive and switch from Aggressive Obsolescence to Limited Lifetime Guarantee.
  • Change from any other life cycle pattern to Two In Production.
  • Refine from Two In Production to its N in Production variant (with N equal to or greater than three).

Target Solution Sketch (Evolution Outline)

The life cycle guarantee is not an architectural element but a documentation item first and foremost.

Some Interface Definition Languages (IDLs) have dedicated support for such metadata (for instance, OpenAPI and MDSL); in other documentation formats, lifecycle and version information usually goes into more general description fields or comments.

Example(s)

When applying this refactoring, an MDSL contract changes from:

API provider SampleAPIProvider1 version 1.0.0
  offers SomeDemoContract 
    at endpoint location "http://www.testdomain.io:80/path/subpath"
    via protocol HTTP 
  binding 
    resource SampleAPIProvider1Resource
  provider governance AGGRESSIVE_OBSOLESCENCE

to:

API provider SampleAPIProvider1 version 2.0.0
  offers SomeDemoContract 
    at endpoint location "http://www.testdomain.io:80/path/subpath"
    via protocol HTTP
  binding 
    resource SampleAPIProvider1Resource
  provider governance LIMITED_LIFETIME_GUARANTEE

The Evolution Patterns on the MAP website feature real-world known uses of the patterns (and their introduction over time).

Hints and Pitfalls to Avoid

Apply this refactoring when existing clients complain, for instance about a lack of planning horizon and effort to catch up with API updates.

When applying the refactoring, perform a cost-benefit analysis. Communicate changes early, clearly, and continuously. Minimize incompatible changes and apply semantic versioning when releasing.

Do not over-commit but find a balance between conflicting concerns, for instance those of external stakeholders and those of the API development team.

This refactoring is the opposite of Relax Evolution Strategy.

Introduce Version Mediator can be applied if lifetime guarantees are weakened and some clients are unable to migrate to a newer, incompatible version. And Introduce Version Identifier might have to be applied before this one so that clients can learn about versions and their (in-)compatibilities.

MDSL specifications have an optional SLA section and a provider governance element in the API provider part. This is explained on the MDSL website.

References

Lübke, Daniel, Olaf Zimmermann, Cesare Pautasso, Uwe Zdun, and Mirko Stocker. 2019. “Interface Evolution Patterns: Balancing Compatibility and Extensibility Across Service Life Cycles.” In Proceedings of the 24th European Conference on Pattern Languages of Programs. EuroPLop ’19. New York, NY, USA: Association for Computing Machinery. https://doi.org/10.1145/3361149.3361164.

  1. Alternatively (but only justified in rare cases), the provider might decide not to do so at all and guarantee an Eternal Lifetime Guarantee

  2. We use double quotes here because this design tactic actually does not change the API structure, but a quality property of it. Note that tightening is the opposite of relaxing; a reverse “refactoring” Relax Evolution Strategy exists as well.