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 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.
- 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.
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".