はじめに
開発部の 有澤 です。
数ヶ月ほど前に、社内アプリケーションの開発責任者(いわゆるプロダクトマネージャー)になりました。 役割を通じて、ステークホルダーと関わることが増え、既存システムに機能を加える機会が増えてきました。
私は新たな要望に応えるため、既存システムと新規機能を比較し、「どのような設計で実現できるか」を検討する機会が増えましたが、 その過程で一つの懸念が浮かびました。
システム設計書は時間と共に風化する
私がこれまでに触れてきたシステム設計書には、さまざまな形式がありました。
- Excel
- PowerPoint
- ナレッジベース
- コードベース
- 人の頭の中
- GitHub Issue
- Pull Request
- Commit メッセージ
- Slack メッセージ
- 紙
これらはチームや組織の状況に応じて形が変わるもので、どれが優れているかは一概に言えません。
しかし、共通する課題があります。それは、時間とともに「リンク切れ」「検索不可」「消失」などの問題が発生し、情報が風化する点です。 また、これらの情報が分散しているため、仕様を再確認する作業がまるで「地層から化石を掘り起こし、全体像を再構築する」ような作業が必要だったりします。
私はこういった情報の復元に慣れていますが、面倒であるのは確かです。
このような状況を自分も生み出してしまうのかと思うと、どうにか解決したいと考えるようになりました。
未来人はシステム設計書で何を知りたいのか
未来の開発者が何を知りたいかを完全に予測することは難しいです。
ですが、自分やチームが「何が必要か?」を考えたり、話し合ったりはできます。
自分やチームが必要なものが書かれていれば、少なからず未来人は意思決定の参考になるはずです。
考えるに、以下のようなことだと定義しました。
- なぜこの設計を採用したか?
- 他に代替案はなかったか?
- この設計はシステムへ適応済みか?
- 適応したかった設計はあるか?
- 大小限らず、発見した技術的負債はあるか?
これらをまとめると、「意思決定の判断材料」として機能する情報
が必要だと考えました。
この情報があれば、未来の開発者がシステム変更時にスムーズな判断を下せるようになるはずです。
ADR を採用しました
ADR は比較的軽量なフレームワークだったのもあり、こちらを採用することにしました。
とはいえ ADR のテンプレートにしっかり準拠するのではなくて、 必要な情報を箇条書きで書ける独自テンプレートを使用することにしました。
ドキュメントを書くためのフレームワークを調べたところ、以下がありました。
- Design Doc
- システムや機能の詳細な設計を記録したドキュメントで、特定の技術的なソリューションや実装について深く掘り下げているのが特徴。
- https://www.industrialempathy.com/posts/design-docs-at-google/
- Architecture Decision Records (ADR)
- システム設計における重要な意思決定を記録するための簡潔なドキュメント。
- https://adr.github.io/
- Lightweight Architecture Decision Records (LADR)
- ADRの簡易版で、より軽量な記録形式。小規模なプロジェクトや頻繁な意思決定の記録に適してそう。
- https://github.com/peter-evans/lightweight-architecture-decision-records?tab=readme-ov-file
ADR の配置
PHP アプリケーションのルート直下に doc/adr/ を作成して、その中にマークダウンファイルを格納しています。
エディタ上で閲覧・編集が簡潔するので開発者的には嬉しいですし、 バージョン管理されるため、ドキュメントがロストしにくくなります。
PHP Application (root)
└── doc
└── adr
├── 2024-08-23-依存ライブラリの見直し.md
├── 2024-11-29-◯◯機能の縮小.md
├── 2024-12-17-ADRの導入.md
├── 2024-12-18-◯◯機能の再設計.md
└── README.md
└── public
└── config
└── .dockerignore
└── etc...
アプリケーションデプロイ時にドキュメントが増えることを避けたい場合は、.dockerignore で doc/ を無視することを推奨します。
ADR のテンプレート
必要な情報を最小限に集めたいので、以下のテンプレートを定義しました。
## 背景(Background)
- 問題の概要と目的。
- システムが解決しようとする課題。
## 目標と非目標(Goals and Non-Goals)
- 目標: このプロジェクトで達成すべきことを具体的に記述。
- 非目標: このプロジェクトでは対応しないことを明確にしてスコープを限定。
## 提案内容(Proposal)
- 問題を解決するアプローチ。
- 技術的な選択肢や、それぞれのメリット・デメリット。
## 技術設計(Technical Design)
- システムのアーキテクチャ。
- データベース設計やAPI仕様の詳細。
- PHPフレームワークや主要ライブラリの選定理由。
## 代替案(Alternatives Considered)
- 他に検討したアプローチと採用しなかった理由。
- リスクとトレードオフ(Risks and Tradeoffs)
- 現状では想定しづらいリスクや、トレードオフについて明記。
# マイルストーンとスケジュール(Milestones and Timeline)
- プロジェクトのスケジュールと各フェーズのゴール。
- 未解決の問題(Unresolved Questions)
- 現段階では結論に至っていない内容。
そもそも、ドキュメントを書くことは開発者のオーバーヘッドです。 見出しに対して文字を埋めることを強要せず、必要な情報だけを書ける柔軟な形式を理想としています。
ADR の内容
まずは「ADRを導入した際の意思決定」を書くのがスタートに丁度よいです。 実際の物よりもボカシていますが、以下のように書きました。
# 2024-12-17 ADRの導入
## 背景(Background)
- ◯◯ の設計や機能を変更する上で、変更箇所や理由、意思決定が継承されづらい状況であることが懸念だった。
## 目標と非目標(Goals and Non-Goals)
### 目標
- ADRを導入することで、意思決定を継承する。
- 初期段階で完璧なADRは目指さないで、まずは簡単な形で導入を目指す。
### 非目標
- なし
## 提案内容(Proposal)
- ADRを導入
- コードと一緒に保管される形容なら、プロダクトが生き続く限り残るのでベストと判断した。
- エディタ内で完結することもDX的に良い。
## 代替案(Alternatives Considered)
- Notionやその他のナレッジベースで管理すること
- リンク切れを起こしたり、そもそも形容として形骸化しやすいので避けた。
ADR のメンテナンス
「必要だと思ったり、便利だと感じる人が増えたら必然的に良いADRが残るはず」と期待しているので、 メンテナンスに関するルールは定義していません。
また、ドキュメントをバージョン管理することのデメリットの一つとして「Pull Requestをレビューする必要」がありますが、 doc/ ディレクトリ配下はレビュー不要とすることで、ドキュメントのメンテナンスのハードルを下げても良いと感じています。
所感
書いた自分でも後々思うのは、代替案が書いてあるのは凄く便利です。
新たに機能を開発した後「なぜこうしなかったのか?」と話が上がることは、プロダクト開発においてよくあります。 その際に自分の記憶が曖昧になっていたり、そもそも自分が退職してしまった時に説明できないのは問題だと感じていたので、 ADR を通してプロダクトの持続可能性を高められたら嬉しいです。