Getting started on a new project might be a daunting task even for experienced developers. You need to learn about the system design, understand the codebase and how everything maps to features exposed to users.
This is one of the main reasons we write documentation.
The goal is to speed up the ramp-up on the project, because of course the faster you learn the system, the sooner you will be able to contribute to it.
There is also a less obvious outcome coming from having good docs.
Developers ramping up on an existing project are like a breeze of fresh air. Having little context on the project, allow them to see it in a different light; a light that could help evolve and improve the system in ways you did not see.
Here is the thing, in my experience, we rarely document a very important aspect of our systems: its evolution, how it got to be what it is and what decisions led to its current state.
Without documentation to address architectural decisions, new developers onboarding with a project are left in a very bad position.
It is hard to understand why something was done the way it is and more importantly, it's hard to know if it can be changed.
You look at some piece of code/design diagram/class diagram and you do not quite get why it was done that way.
You might think that a different approach would improve it.
There are two ways in which this situation can evolve from here:
- you think who did it had very good reasons, you just can't see them. You decide not to change it.
- you think who did it had no clue. You change it with what you think is better and after three debugging sessions and two coffees, you revert it.
Both stories lead to a disaster.
In the first case, the team might miss out on some big improvements. In the second, you waste time and energy, maybe even impact some customers along the way.
After this somewhat long introduction, I hope I have convinced you we need a better way to document evolutionary decisions that drive our software.
This is what Architectural decision records (ADR) are all about.
ADR
ADR define a way to document architectural decisions in a way that allows the readers to track their evolution.
This is not the new shiny thing, it's a pretty old idea.
The first reference I found online is from an article published in 2011 by Michael Nygard (author of the book Release it!). Sadly the page seems to have been removed.
Using ADR
- document each decision in a record
- keep the records version controlled together with the code
- have each record share the same template
- every time you make a decision or revert a previous one, create another record
That's it. Easy.
There is no standard or convention about the folder name which is going to contain the records or the template used for the records.
That being said, there are several proposals but you are free to use the one that suits you the best.
For example, this is how I do it:
I create a folder named adr in the root of the git repo.
Something like this:
/adr
000_template
001_use_springboot
002_build_rpm_with_fpm
003_revoke_decision_to_use_springboot
004_use_XYZ_instead_of_springboot
/src
/com
...
The file named 000_template contains the template used to create the records. It's convenient to keep it there so that new records can be created by copying the template file.
The template I use is the following:
## Title here
Date:
### Status
Accepted | Rejected | Suspended
### Context
### Decision
### Consequences
It's very simple, but I found it very effective.
The other files are named after their content. For example 002_build_rpm_with_fpm might contain:
## build_rpm_with_fpm
Date: 2018, 19 Nov
### Status
Accepted
### Context
rpmbuild is a tool that builds an rpm given a spec file.
It is pretty low level, so different solutions have emerged to abstract away some of the details.
There are many solutions available in the wild.
### Decision
Use [fpm](https://github.com/jordansissel/fpm) to build the rpm.
The alternatives considered:
#### RpmBuilder
__Pros:__
- Already wired with the internal tooling
__Cons:__
- Requires some heavy lifting to build the directory structure necessary to build the rpm
- Very poorly documented and it does not seem to be used
#### fpm
__Pros:__
- Hide the details necessary to build the rpm
- Nice documentation
- Used by other teams
__Cons:__
- Some custom build logic is necessary to make it work in harmony with the build system.
__Link:__ https://github.com/jordansissel/fpm
### Consequences
The package structure is intuitive and it is going to represent exactly the folder structure installed by the rpm.
Build logic is very easy to understand and modify.
Conclusion
Use ADR to document your architectural decisions. You'll help people working on the project and yourself. As a famous quote says: "any code of your own that you haven't looked at for six or more months might as well have been written by someone else".
Happy coding!
Additional resources
Top comments (5)
We've dabbled with these on my team. So far so good and should be valuable resources to point to as new folks rotate through.
Hardest part for me at least is just determining when a decision is important enough to record.
Nice!
About deciding if a record should be written or not: my bias is to write more records rather than less.
Our own solutions always seem obvious, thus not worth documenting.
But we are the worst judge of that.
When in doubt I also share it with other teammates or people who might not have all the necessary context.
Ultimately, because the records are versioned controlled, they can be reviewed as part of the Code review process.
Thanks for the post, this is a great idea. So many times I’ve stared at code wondering what was the thinking behind a design choice. A little explanation can go a long way to making those decisions understandable.
Has any of you guys done this in a blog / static website like context?
I got myself a static website with jekyll. Haven't included a template of ADR yet (just opened a ticket after reading this post), but explanations to the why of decisions made. In consequence, using github pages or something similiar the ADR is next to the git repository and nicely readable.
Because of jekyll's overhead files the documentation repository is a submodule of the code base.
After reading the MADR approach, the website is clearly a bit more overhead and could lead to a discussion whether the accessibility of a html page instead of md files is worth the hassle.
I just open-sourced a project that let's you publish your ADRs as a static website:
Log4brains - github.com/thomvaill/log4brains
This is a CLI + web UI that lets you manage and publish your ADRs from Markdown to a static website, with search, history flow graph and other useful features.
This is a beta, so your feedback is very welcome!