A few years ago, my team started to write ADRs. We had several green projects and we were all responsible for the architecture of these new systems. We had also the ability to choose the tech stack – at least to some extent. Obviously, we did not want to contaminate this happy time by spending it writing extensive documentation that almost nobody likes writing and almost nobody reads. We have decided to go with ADRs and this was the way to go! Right now, more and more projects in the company adopt this approach and it really makes our life easier.
What are Architectural (or Architecture) Decision Records (ADRs)?
As stated on the Homepage of the ADR GitHub organization:
An Architectural Decision (AD) is a software design choice that addresses a functional or non-functional requirement that is architecturally significant. An Architecturally Significant Requirement (ASR) is a requirement that has a measurable effect on a software system’s architecture and quality. An Architectural Decision Record (ADR) captures a single AD, such as often done when writing personal notes or meeting minutes; the collection of ADRs created and maintained in a project constitute its decision log.Architectural Decision Records | adr.github.io
To put it simply, ADR is just a document (i.e. in a form of a Markdown pushed to the repository together with the code) that says why we have chosen a given approach or technology and what are the consequences of that decision (i.e. how the system/people are going to benefit from that). It shall be kept simple, short, and easy to read. All documents create a decision log thanks to which we can quickly understand the timeline and impact of these decisions. What is interesting, ADRs are listed as “adopt” from ThoughtWorks’s Technology Radar from 2018 (technology-radar-vol-18-en.pdf (thoughtworks.com)). The ADR page also promotes using ArchUnit for testing your architecture, about which you can further read here: Guard your architecture by ArchUnit.
How to write this?
There are multiple templates for ADRs – you can see them as well as examples here: Architecture decision record (ADR). Personally, I like the one from Michael Nygard (do you recall his great book – “Release it!”?). We use also this template in our teams and because of its simplicity, it works for us. The template in the Markdown format from Michael looks like this:
# Decision record template by Michael Nygard This is the template in [Documenting architecture decisions - Michael Nygard](http://thinkrelevance.com/blog/2011/11/15/documenting-architecture-decisions). You can use [adr-tools](https://github.com/npryce/adr-tools) for managing the ADR files. In each ADR file, write these sections: # Title ## Status What is the status, such as proposed, accepted, rejected, deprecated, superseded, etc.? ## Context What is the issue that we're seeing that is motivating this decision or change? ## Decision What is the change that we're proposing and/or doing? ## Consequences What becomes easier or more difficult to do because of this change?
Based on the above template, we can imagine an example like this:
# Language used in the project ## Status Accepted ## Context We need to decide what programming language we are going to use in this project. The application is going to run on a server with Java, therefore we shall stick to languages that operate on JVM. We consider the below languages: - Java - Scala - Groovy - Kotlin ## Decision Production code: Kotlin Test: Groovy We decided to use Kotlin for the production code and Groovy for tests. As we are restricted to using JDK8, we went for Kotlin as it offers more features than Java8 and the transition from Java to Kotlin shall be fluent for developers. Kotlin can work together with Java and it is yet another advantage of this language. Scala, on the other side, seems to be more complicated with a steeper learning curve. Its ecosystem is also different from what we have used so far. Therefore, to keep things simpler, we decided to try Kotlin. We also think that Spock is the right framework to write tests - very easy and convenient to use. Therefore, we are going to use Groovy for tests. ## Consequences Developers will need to spend additional few days learning Kotlin, however, we believe it shall pay off in the longer perspective. Kotlin's features shall make the code simpler and easier to maintain. Kotlin is still pretty similar to Java, therefore the code shall be well understood also for developers that have not used that before.
You can also use dedicated tools for writing ADRs, i.e. Command-line tools for working with Architecture Decision Records, however, I never had such a need. Of course, all architectural decisions for that tool are written as ADRs – you can see a live example of such an architectural log here: adr-tools/doc/adr. Decision records ideally should remain immutable once accepted. If the decision has to be changed in the future, a new file can be created with a link to the former ADR.
Why are ADRs a way to go?
There are various reasons why writing simple ADRs is much better than extensive documentation i.e. in Confluence or (please no!) – Word document sent by an email:). Here are a few that just came to my mind:
- ADRs written as markdowns can be pushed to the repository and are a perfect subject for a code review. We have
git blameto get further info on who has written the ADR and when – so can ping that person for more information when needed
- They can sit together with the code – no need to search for Confluence (or another KB) links. Or even worse – emails with the documentation!:x
- They are short – reading the rationale of the decision can be a matter of seconds
- writing one is also easy and templates are really simple
- We can quickly understand the architectural decisions of other projects maintained by other teams. This can save a lot of time if we encounter a similar problem.
- Fewer questions during onboarding of new team members – at least in terms of the used tech stack and architectural solutions
- We can document ongoing discussions. VCS helps a lot in such cases too.
- We can document decisions that we have NOT made as well. It is equally as important.
- As ADRs stay together with the code, there is a higher chance that developers will remember to add new ADRs (compared to the maintenance of external resources)
- They can be written for the past too!
- We can always raise a bug in your VCS UI for a particular ADR 🙂
- Sometimes we think that some architectural decisions do not make sense. With ADRs, their context, and description of why this particular solution has been chosen, things start to look differently
Shall I use ADRs?
ADRs are easy to write and even more easy to read. Despite that, I still see that not that many projects adopted this practice. It is much more difficult to understand some decisions in these projects without ADRs. Even if the architectural documentation exists, usually it is scattered in various places, often outdated and forgotten. If you have not written ADRs yet, start doing that. I am sure you will like it and you will see the benefits pretty soon. If other teams also adopt this practice, you will get the possibility to quickly understand decisions in their projects. In this case, you will see benefits even sooner. Architectural Decision Records are definitely helping the knowledge to flow – even after a minimal time investment in writing them.