Why did we do it that way?

Have you ever joined a project and not soon after questioned why things are the way they are? Why was this language (or framework) chosen over another? Why do we (or don't we) organize things into microservices? Why are errors handled the way they are? What drove the choice of database, or API design, or external service?

These questions always come up. It's a natural part of understanding a new work environment. It happens every time. And I don't like being in the position of saying "I'm not sure why this was done/used" in the course of fixing something or implementing something new.

It is just as much an issue for those who have been on a project for any length of time. Why did we make a particular decision six months ago? Not being able to recall enough detail about past decisions isn't usually a deal-breaker for moving forward, but it can significantly help provide context and understanding behind the evolution of a project to the current state. That helps make further changes without breaking or un-intentionally invalidating past decisions.

We make decisions all the time. Some are big, some small. Some have big implications, some not. Projects that try to design/plan a lot up front make decisions early (sometimes with extensive documentation) but validate them later. Other projects decide just-in-time and may not document them at all.

I have seen such decisions documented in formal Word documents, Wikis, User stories (as additional details to the story), email, etc. What has been most useful is making sure they are easy to find, easy to add, and reasonably consistent in format.

A Lean Experiment

If, like me, you are looking for a lean approach to experiment with you might consider the Architectural Decision Record (ADR). These are simply text files checked-in to a project's repository with a simple format that can be as sparsely or densely detailed as needed.

As described, ADRs seem to have just enough information: Context of the decision, the Decision itself (once made), Status (proposed, accepted, rejected, superseded, or deprecated), and Consequences of the decision. Since there are potentially some relationships between decisions (such as superseding) there is some maintenance effort needed to properly revise past decisions so the worth of that tradeoff should be part of any experiment using them.

In my experience, they are probably just as valuable in making a decision as in documenting for the future. The process of describing the Context helps in framing the decision and writing a the Consequences for a proposal help communicate information not only for approval but for generating additional work items or changes that may result.

A very public example of these that I have seen recently is in the Arachne Framework, a web development framework for Clojure. The project has a dedicated repository of ADRs since the project itself is composed of multiple repositories. Some of the records already present include:

Note that since this is a relatively young open source project (at the time this article was written) many of these ADRs documented proposals. By the time you read this, some of these may be accepted or even superseded.

Trying It Out

I have been recommending these as an experiment to teams I work with and using these on projects with overall positive results. There is even a handy command line tool by Nat Pryce to help create/manage ADRs.

So, whether you are a solo developer or a full team and have been considering a simple way to track decisions, consider experimenting with ADRs or something similarly lightweight.

I'd love to hear experience reports or other approaches that have worked for you.

Published: 2016-10-27

Tags: design