blog-thumb

Framing ADR Context

The purpose of a system influences the architecture, but system architects are often involved after the business need is identified. The business case is often lost in technical documentation, because those points are lost in slides prepared by the business. Maintaining a complete story in technical documentation betters odds of projects aligning to purpose. Let’s consider how to describe and model a system before recording architecture decisions.

Architecture Decision Records (ADR)

  • are a best practice for documenting why an architecture is chosen.
  • are evidence of due diligence in the selection process.
  • are important for future maintainers of a system.

More context available in Recognizing ADR Value

We’ll contextualize systems using an approach insprired by the C4 Model. Our key takeaway from C4 is thinking about the system at multiple levels. This method decreases the information to communicate in a single diagram. Another technique we’ll borrow from C4 is modeling instead of diagramming. We’ll use textual templates and annotations to achieve our model. This representation will keep our model approachable to business stakeholders.

Centralization

First, let’s consider where system documentation should live. Preserving information involves ensuring records can endure time and change. Therefore, the most necessary features are change management and vendor neutrality. Visual editors and tooling that archive information inside vendor products are a recipe for data loss. Without naming specific products, let’s just say many popular commercial wikis are a mistake. Consider yourself lucky if you haven’t lost documentation in upgrades or vendor migrations. At the least, you’ve likely experienced formatting issues you learned to tolerate. Preventing documentation loss involves not giving away control for convenience.

Keep it simple. Text files are a vendor neutral medium to capture information. They are also versionable in the same tools software is built. In addition, modern source control tooling is built for collaboration on open standards. All that said, let’s proceed with a dedicated git repository for documentation. We’ll format with markdown and lean towards managing docs as code.

Contextualization

C4 Model has, you guessed it, four levels:

  • Context - big picture from a customer perspective
  • Containers - subsystems such as apps and products
  • Components - moving parts of an application
  • Code - details of each moving part

We can model these in well known templates from the agile methodology:

  • User stories capture customer intent for a system.
  • Behavior Driven Development describes interactions of people and systems.
Customer Context

User stories are, not suprisingly, focused on user needs. The common template follows a "As a _, I want _, so I can _." format. This structure provides a big picture view of the problem space. Context is the first C of the C4 model, and our context is customer focused. Let’s try modeling with user stories.

As a $UserLabel,
I want to $ActionLabel $ContainerLabel,
so I can $ContainerValue.

The $ placeholders above can be completed as:

As a `contributor`, I want to _maintain_ the Lexical.cloud catalog,
so I can `spread awareness of options for cloud architecture`.

Resulting in a visualization of:

flowchart TD
%% entities
  U1["Contributors"]
%% groups
  subgraph G1["Users"]
    U1
  end
  subgraph G2["Lexical.cloud
   - Spread awareness of options for cloud architecture
  "]
  end
%% relationships
  U1 -->|maintain| G2
%% styles
  classDef cluster fill:white,stroke:grey,stroke-dasharray:5
Containers & Components

The "Given _, when _, then _." structure of behavior-driven dev (BDD) can further this representation. Containers and Components, the next Cs from C4, will dive further into the previously defined context. Containers are groups of components and other containers. The nesting can go multiple levels deep. Beyond components is only code, the final C of C4, represented in traditional software methods.

Given $ContainerLabel $ComponentLabel,
when  $ComponentLabel $ActionLabel $ComponentLabel
or $ComponentLabel $ActionLabel $ContainerLabel,
then $ContainerLabel $ActionLabel $ComponentLabel.

The $ placeholders above can be completed as:

Given `Lexical.cloud` is a `community data` project,
when `contributors` _maintain_ the `community data`,
then `community data` _populates_ the `frontend` and `backend`.

Resulting in a visualization of:

flowchart TD
%% entities
  U2["Contributors"]
%% groups
  subgraph G1["Users"]
    U2
  end
  subgraph G2["Lexical.cloud"]
    G3
    G4
    G5
  end
  subgraph G3["Community Data"]
  end
  subgraph G4["Frontend"]
  end
  subgraph G5["Backend"]
  end
%% relationships
  U2 -->|maintain| G3
  G3 -->|populates| G4
  G3 -->|populates| G5
%% styles
  classDef cluster fill:white,stroke:grey,stroke-dasharray:5

Correlation

Let’s consider the benefits of documenting a system backstory as code:

  • Problem and chosen solution are captured for future system maintainers.
  • Reusable services can reference solutions and purposes being served.
  • Evolution of system goals is chronicled beside strategy and implementation.
  • Shared vocabulary and visualization enables discussion with various stakeholders.

In short, documenting context clarifies past and present state for future decision makers. ADRs do the same for decisions made in a given context. Combining these methods better explains why a decision was reached. See this in action on Lexical.cloud’s project docs.

What Next?

Let’s continue exploring ADRS with this series of articles:

Thank you for reading!
More articles coming soon.