At work we have "design decision documents" (DDDs). Others call the "architecture decision records" (ADRs). In short, you record a problem, its possible solutions, and which one you picked. This method can be lightweight and easy, so it is a great way to start working more systematically on any software architecture. I recommend writing them. ThoughtWorks recommends to adopt them since 2017.
Why decision records?
Important about decision records is that they document a decision made at one point in time. This means they require no maintenance (apart from archival) and this is a big argument why they are so lightweight. If you make no decisions, there is no effort.
At the beginning of a software project you make a lot of high impact decisions quickly. You pick a programming language, framework, libraries, version control system, folder structure, tools, and methods. Usually these choices are made haphazardly. Trying to make them all thoughtfully is futile. However, you should be able to write them down with a rational.
Another strength of a lightweight process shows up when a project is under pressure. You don't have the capacity for rigorous decision making like building a prototype. Writing down the decision should still be possible. Deadline pressure or lack of capacity are valid arguments in a decision record so you might document that you accept the technical debt to meet a deadline. At least, a few years later people know why you made stupid choices.
You could even record decision long after the decision were actually made. While the best time to write it was right before the decision was made, the second best time is now.
Having decision records is useful to communicate a decision to many people. This includes new people joining months later. Here it pays off if you can write well. I have seen Powerpoint slides which are incomprehensible without the original author but still considered "documentation". This is tragic. Such diagrams are more of a memory aid than documentation. Hence, I favor well written prose.
Decision records also serve as historic documentation when someone questions the decision. You can revisit the argumentation and check why the decision looks stupid now. Did the circumstances change? Then there is no reason to blame anyone. Was something overlooked? Now we might learn something: How can you prevent to overlook similar things in the future?
A decision record is frozen once a decision is made. The only exception is declaring it obsolete. This has three implications:
- If something changes about a decision, write a new record instead of modifying the old one.
- The record is not the place to track the implementation. You probably have an issue tracker for such stuff.
- Only one decision per record. If you try to make multiple at once, the risk is that only one is made. Now the record is in an ambiguous half-frozen state.
Tooling does not matter. You can use a wiki, Word, Markdown, or whatever. Just ensure that you can link to individual records.
Lightweight Template
As a running example, let us decide about which SQL database technology we use.
Once you have collected a few decision records, you appreciate a summarizing header. After a title like "SQL Database Tech", I like to see a short table like this:
Status | Approved on 2020-10-18 |
---|---|
Decision | Option 2: PostgreSQL |
Roll-out | #353 |
Primary author | Linus Carmack |
The status tells you if a decision record is still a draft, valid, or obsolete. If valid, it should also have a date since when. I also like to link it to some meeting notes where the decision was made but that depends on your organization. Likewise, for obsolete decisions link somewhere for a rational, like another decision record.
The second field is an ultra-short version of the decision made. It is for people who already know the record, so one or two words should be enough. Use whatever name people use when discussing the solutions. Internal jargon is ok since it is just a name like "PostgreSQL" in our example.
The roll-out field links to a ticket. Once a decision is made, it is not instantly implemented. While the status field here describes the status of the decision, this links to where the implementation status is tracked.
Primary author contains a single name to provide a contact. It also says "primary" to suggest that others can contribute. If you want to document all authors, don't use the header.
Now comes the first prose section of the record, which describes the problem. A reader should get all relevant context here and probably links for more details. Keep the solution space as wide as possible. For our example, we should explain why we are already committed to SQL and NoSQL is no option. Also, it should explain why an explicit decision is necessary and to defer it by abstraction is no option.
If a problem requires multiple decisions then you might get multiple decision records with similar problem descriptions. Or maybe you should think more what the actual problem is. Sometimes people mistake the reason to make a decision with the problem to solve. For example, "customer wants to know what database tech we will use" is not a problem. The problem is to store data persistently.
Next comes a section which describes all potential solutions to the problem. This section usually has the most contributors and is revised the most. Describe every solution in as much detail as you can. For our example, the usual options would be SQLite, MySQL, and PostgreSQL. Maybe even commercial ones. A little over-specification does not hurt. You could describe how you would deploy and host PostgreSQL on its own server.
Cross check that the solutions actually solve the described problem. Surprisingly often I found mismatches. Sometimes the problem was described too constraining. Sometimes some text had to be shifted from problem to solution or vice versa. And sometimes we had forgotten to consider an aspect of the problem.
I despise use a table for the solution descriptions. It conflicts with my preference for prose. If you write longer text or even include diagrams, the table becomes to wide to be readable. So a table makes you write short bullet points and those are harder to comprehend.
The third section is about evaluation and making the decision. It helps to keep a list of evaluation criteria somewhere to pick the relevant ones. If you have nothing, browse through the Wikipedia list of ilities. I try to keep this section short and prefer to describe details (like pros and cons) in the previous section. Here a table is appropriate to compare the solutions. I like to only put + and - signs into the cells and order the rows by importance. From the table, it should be obvious which solution is picked. Ideally, you only take a quick look at the first two rows and pick the solution with the most + symbols.
To summarize a table of contents looks like this:
- Header
- Problem description
- Potential Solutions
- SQLite
- MySQL
- PostgreSQL
- Decision
Optional extensions
The header could contain more fields like revision, executive summary, id, decision makers, or whatever.
A section or table about the stakeholders can make sense under some circumstances. For example, a safety or security expert might be relevant or not for the decision.
The problem description section can be split up into assumptions, constraints, requirements, related things, and whatnot. I avoid overly formal templates because if a section makes no sense it encourages people to skip entire sections. This is not a habit to encourage.
Likewise the potential solutions or the evaluation can be formalized more to include mandatory risk evaluation, cost estimates, and whatnot.
You could include meeting notes around a decision within the record. This only makes sense if meeting notes are not already captured otherwise.
In a political setting, you could capture the opinions of each stakeholder separately. This way a worried party can have their objections on record with their name attached instead of an anonymous downside description.
Maybe a glossary makes sense? On the other hand, decision records should probably not that long to require one.
Even more lightweight
You could trim decision records down even more if you don't describe alternative solutions. Instead you only describe the one you picked eventually. Such records are still valuable since they capture the rational. However, if a new proposal comes up later, you don't know if it was considered originally and dismissed for some valid reasons. Anyways, you might use this lighter approach at the beginning of a project when a lot of decisions must be made quickly. Incomplete records are better than none.
One last advice: The first ten decision records will be crappy. Get them done sooner than later.
Joel Parker Henderson maintains a repo with templates and examples.