🔥

チームの技術的意思決定を記録する:ADRの実例と運用のリアルな話

2024/12/23に公開

この記事はCommune Advent Calendar 2024、シリーズ2の22日目の記事です。

Frontend Techleadの野口です。

はじめに

こんにちは!今回は普段なかなか表に出てこない「技術的な意思決定をどうやって記録しているか」というお話をさせていただきます。

このトピックを取り上げようと思ったきっかけは、私自身の経験にあります。今年の年初に入社して、既存のコードベースを見ていく中で、「なぜこの技術スタックを選んだんだろう?」「この設計判断の背景には何があったのだろう?」といった疑問が次々と浮かんできました。

その都度、社内で詳しい人を探して聞いて回るのですが、これが意外と大変でした。当時の判断に関わった人を見つけ出し、さらにその人の記憶を頼りに話を聞くというプロセスは、思いのほか時間がかかります。「もっと効率的な方法があるはずでは?」─── そんな思いから、私たちのチームでADR(Architecture Decision Records)を書く文化を定着させようと取り組んでいます。

ADRの基本構造

ADRは以下の要素で構成されます:

  • 決定事項の概要
  • 決定を行う前提となる状況
  • 詳細な検討内容と理由
  • 想定される影響

ADRの運用プロセス

ステータス管理

ADRは以下の4つのステータスで管理します:

  1. WIP (Work In Progress)

    • 検討段階の提案
    • 自由な更新が可能
  2. INREVIEW

    • レビュー依頼中のステータス
    • レビュワーからのフィードバック募集
  3. ACCEPTED

    • 承認済みの提案
    • 実装・運用変更の開始が可能
  4. REJECTED

    • 却下された提案
    • 却下理由を含めた記録として保持
    • 現在は採用されていない判断を明確に示す
    • 「なぜその選択肢を採用しなかったのか」の根拠を残す
    • 類似の提案が出たときの参考資料となる

REJECTEDステータスは特に重要です。ADRを書いた後、その決定が実際に採用されているかどうかを判断する際の重要な指標となるためです。例えば、「このアプローチは検討したけど採用しなかった」という情報は、後からコードベースを見る人にとって非常に有用です。また、似たような提案が再度上がってきた際に、過去の検討結果を参照できる点でも価値があります。

レビュープロセス

効果的なレビューのために以下の要素を重視しています:

  1. レビュワーの選定基準

    • 該当技術領域の専門家
    • テックリード
    • 影響範囲に含まれるチームのメンバー
  2. 承認要件

    • 2名以上のapproveを必須とする
    • 重要な技術的懸念の解消を確認

実際のADR事例:ステータス遷移の実例

以下の2つのADRは、あるプロジェクトで実際に検討された関連する提案です。技術的な判断がどのように変化していったのか、実例としてご紹介します。

事例1:git-hookの最適化(→ REJECTED)

最初に検討されたのは、git-hookの運用見直しに関する提案でした。

# fix husky git-hook actions
No git-hook LintingのためREJECTED

## 概要
- `husky`によるpre-push時のビルドチェックが端末によって低速なため削除したい
- pre-commit時のlint, formatはpush時にチェックすれば良いため、pre-pushのイベントで実行する

## 前提
`husky`によってgitでのアクションをフックとしてlint, formatなどを行っている

`husky`で利用されているイベントは以下の2つ
`pre-commit`: コミット前に何らかのアクションを実行する
`pre-push`: プッシュ前に何らかのアクションを実行する

ファイルの差分は`lint-staged`で検出し、`husky`と組み合わせて

## 詳細
`pre-push`時のビルドチェックがローカルマシン依存で低速実行になってしまう。

これはCI上での実行が確認できていないときの名残であり、CIで同様のタスクが実行されている現在、ローカルとCIの二重実行になっている。

高速な開発の阻害要因となるため、`pre-push`のビルドチェックを削除したい。

また、`pre-commit`時のに行われているlint, formatは最終的にマージされる段階で修正されていれば良く、`pre-push`時に行えば開発、レビューの観点で頻度を少なく、効率化できる。

これらによって行われる最終的な修正としては、
`husky`での`pre-commit`のアクションの内容をそのまま`pre-push`に上書きし、`pre-commit`を削除する。

この提案は検討中(WIP→INREVIEW)でしたが、社内でbiomeが導入される動きが出てきたため、より包括的な改善案を検討することになりREJECTEDとなりました。このREJECTEDステータスのADRは、「なぜgit-hookの部分的な改善ではなく、より抜本的な改善を選んだのか」という判断の記録として機能しています。後から見返したときに、この判断の背景(biomeの導入)が明確に分かるため、現在の構成の理解に役立っています。

事例2:静的解析プロセスの改善(→ ACCEPTED)

事例1の検討過程で新たな選択肢が出てきたことを受け、より抜本的な改善案として提案されました。

# No git-hook Linting

## 概要
huskyで行われているlint, formatを行わない

## 前提
- 現状、huskyによる静的解析が行われている
- lint, formatはbiomeを利用している
- nxを用いたビルドチェックがpush前に実行される
  - CI上で同等のものが行われている

## 詳細
commit, pushを行う際にコードに対して静的解析が行われている。
以下はその問題点。

### 単純に時間がかかる
コミット時に静的解析を行う場合、
`コミット回数 * 静的解析にかかる時間`が費やされることになる。

### CIに同等の静的解析が用意されている
無意味なダブルチェックになっている。

### DraftのPRが作りづらい
開発のSpikeとしてとりあえず参考としてPRを作る際にも、厳密なコードチェックを行うため、マージする予定のないラフなコードがPRにしづらい。
都度`--no-verify`オプションをつけることになり、非常に手間。

### ローカル環境の問題
2024/05現在、端末のスペックはお世辞にも良いものとはいえないため、静的解析の実行速度は早くない。~~それをやらせるなら高い端末をくれ~~[^1]

### formatはsaveOnFormatで実行できる
vscodeの設定でファイルを保存した際にformatを実行できる。
webstormなども同様。git-hookでformatを実行する必要がない。

以上からgit-hookで静的解析を行うべきではない。

[^1]: 執筆時点(2024/12)では、開発端末の刷新が進み、この問題は大幅に改善されています。ただし、このADRで示された「CIでの一元的なチェック」という方針は、環境への依存を減らし品質を担保する観点から、現在も有効な判断として評価されています。

この提案は以下の理由からACCEPTEDとなりました:

  • biomeによる高速な静的解析の実現
  • 開発体験の改善
  • CIでの確実なチェック体制の確立

効果的なADR作成のポイント

  1. 適切な粒度の設定

    • 重要な技術的決定に焦点を当てる
    • 過度に細かい実装詳細は避ける
  2. 明確な記述

    • 決定事項の簡潔な説明
    • 具体的な根拠の提示
  3. コンテキストの保持

    • 決定に至る背景の明確な記録
    • 代替案検討の過程の文書化

おわりに

「また面倒な文書作成か...」と思われるかもしれません。確かに、新しい取り組みを始めるのは常に大変です。しかし、冒頭でお話しした私の経験のように、技術的な判断の背景を後から探る手間を考えると、きちんと記録を残しておくことの価値は非常に大きいと感じています。

実際に私たちのチームでADRを導入してみると、新メンバーの立ち上がりがスムーズになっただけでなく、前述の事例のように、技術の進化に応じて柔軟に判断を更新できるようになりました。判断の理由が明確に記録されているため、変更の過程も追跡しやすくなっています。

ぜひ皆さんのチームでも、ここで紹介した実例や運用方法を参考に、チームに合ったADRの導入を検討してみてはいかがでしょうか?

コミューン株式会社

Discussion