はじめに
この記事は 株式会社TRAILBLAZER Advent Calendar 2025 の記事です。
TRAILBLAZERでフロントエンドエンジニアをしている田原です。
ADR (Architecture Decision Records) は、アーキテクチャ上の決定とその理由を記録するドキュメントです。「なぜこのフレームワークを選んだのか」「なぜこの状態管理ライブラリにしたのか」といった判断を残すためのものとして知られています。
ただ、実際の開発では「アーキテクチャ」と呼ぶほど大げさではない、でも後から見返したときに意図がわからなくなりそうな判断が日々発生します。
この記事では、そうした判断に対してADRを「実装前」と「実装後」の2段階で書く運用を試してみた経験を共有し、実装におけるプラックボックスを少しでも無くしていく取り組みについてご紹介します。
課題感について
フロントエンドの実装をしていると、こんな場面に遭遇することがあります。
- 実装を進めてから「やっぱりこっちのアプローチの方が良かったかも」と気づく
- PRレビューで「なぜこの設計にしたの?」と聞かれて、口頭で説明する羽目になる
- 数ヶ月後に自分のコードを見て「なんでこうしたんだっけ...」となる
要するに、決定の経緯が残っていないことと方針の説明がなされていないことが原因と考えられます。
コードには「何をしているか」は書いてあっても、「なぜそうしたか」「他に何を検討したか」
は書いておらず、あるのはその結果に対してのみです。
コメントによる補足も手段としてありますが実際問題可読性の観点から記述量には限界があります。
やってみていること
実装前:ドラフトとして書く
実装に入る前に、まずADRのドラフトを書きます。
この段階では完璧である必要はなく、以下のような内容を整理します。
- Context: 何を実装しようとしているのか、背景は何か
- 選択肢: どんなアプローチが考えられるか
- 仮決定: 現時点でどれを選ぼうとしているか、その理由について
この時点では「仮」なので、実装中に変わっても問題ありません。
むしろ、書き出すことで実装者側が考慮・観点漏れに気づくことが目的の一つでもあります。
実装中:判断が変わったら追記
実装を進めていくと、当初の想定と違う事情が出てくることがあります。
- 思ったよりユースケースが複雑だった
- 既存コードとの兼ね合いで別のアプローチが必要になった
- パフォーマンス上の問題が見つかった
そうした場合は、ADRに追記・修正を加えます。「当初はAを予定していたが、〇〇の理由でBに変更」といった経緯を残しておきます。(所謂、証跡ですね)
実装後:最終形としてcompact化
実装が完了したら、ADRを最終形として整理します。議論の過程で出た細かい話は削ぎ落とし、以下の点を明確にします。
- 最終的に何を決定したか
- なぜその決定に至ったか
- 却下した選択肢とその理由
- 影響範囲
実際の例
ある機能の実装で、クライアントサイドでの状態管理が必要になった場面を例に挙げます。
実装前のドラフト
## Context
特定の状態をブラウザ側で永続化する必要がある。
サーバー側での管理は今回のスコープ外。
## 選択肢
1. localStorage
2. IndexedDB
3. Cookie
## 仮決定
localStorage を採用予定。
理由:実装がシンプル、要件を満たすには十分。
実装中の追記
## 決定変更
localStorageではなくIndexedDBを採用する。
理由:
- 保存するデータが複合キーを必要とする構造だった
- 将来的にデータ量が増えた際の拡張性を考慮
実装後の最終形
## 決定事項
IndexedDBを使用したクライアントサイド管理を採用。
## 理由
- 複合キーによるデータ管理が必要
- サーバー側実装が不要
- 将来的な拡張性を確保
## 却下した選択肢
- localStorage: 複合キーの表現が煩雑になる
- Cookie: 容量制限、リクエストへの付与が不要
## 影響範囲
- 対象コンポーネント一式
- ユーティリティ関数の追加
このように、検討から決定までの流れが1つのドキュメントに集約されます。
生成AIとの相性について
ここがメインといっても過言ではありません。
コンテキストの階層化問題
Claude Codeなどの生成AIに実装を手伝ってもらう場合、プロジェクト全体の方針は CLAUDE.md のようなファイルに書いておくことが多いと思います。
ですが個別具体の実装タスクには、そのタスク固有の背景や制約があります。
毎回全体のコンテキストだけを見せても、細かい判断の意図は伝わらず、様々な手法でmemorizeしてもうまく伝わらないときがあります。
その観点を踏まえて以下のような階層でADRを書くことで「全体方針 + 今回のADR」という形でAIに文脈を渡すことが可能になります。
AGENT.md(全体方針)
├── 技術スタック
├── コーディング規約
└── 共通のルール
ADR(個別の文脈)
├── この実装の背景
├── 検討した選択肢
└── 決定とその理由
AIとの壁打ちがそのまま記録になる
また、実装前のドラフトを書く段階で、AIに壁打ち相手になってもらうことにより
出てきた選択肢をそのままADRに書き込む。採用・却下の判断もその場で整理できます。
一度実装が終わり過去の経緯を遡りたいときなど後日、同じAIに同じADRを渡せば
当時の議論の文脈を再現することも可能です。
各種設計書との違い
やっていることは近い認識ですが以下の点で異なると思っています。
- 実装が終われば形骸化していくことが多い
(運用・保守・アップデートがうまく行われていることが少ない) - ドキュメントとして物量が単純に多い場合があり個別具体への実装経緯へのアプローチが大変
- このアプローチによるADRはRepositoryの中で管理するので生成AIによるアクセスが楽
やってみての所感
良かった点
-
手戻りが減った
実装前に選択肢を洗い出すことで、「やっぱり別の方法で...」が減った -
レビューがスムーズ
PRにADRのリンクを貼っておけば、設計意図について共通認識が取れる -
再利用できる
似た実装をするとき、過去のADRを参照できる -
ADRだけレビューしてもらう
ADR段階でのFBを受けることが可能になるので実装方針とのズレが少なくなる
気をつける点
-
粒度の判断
どのレベルの決定にADRを書くか、まだ手探りの状態であり
チームでの運用と呼べるものまで行っていない -
更新を忘れがち
実装中に判断が変わったときADRへの反映を忘れることがある為
ここについては生成AIに対してルールに記載するなどで対応していく必要があります。
まとめ
ADRを「実装前」と「実装後」の2段階で書く運用を紹介しました。
- 実装前にドラフトを書くことで、思考の整理と考慮漏れの発見ができる
- 実装後にcompact化することで、決定事項が明確になる
- 生成AIとの協業でも、個別の文脈を渡す手段として有効
本来ADRは「アーキテクチャ上の決定」を記録するものですが、もう少し広く「後から経緯を知りたくなりそうな判断」に適用しても良いのではないかと思っています。
まずは小さく試してみて、自分やチームに合う粒度を探っていくのがおすすめです。
最後に
本記事を最後まで読んで頂きありがとうございます![]()
TRAILBLAZERでは一緒に働くメンバーを募集中です!!
皆さまからのご連絡お待ちしております![]()