私がWikiで見たアーキテクチャ図は、すべて間違っていた。劇的に間違っているわけではない。静かに、徐々に間違っているのだ。「Auth」と書かれたサービスは半年前に3つのマイクロサービスに分割された。「sync call」と書かれた矢印は、今やキューを経由したasyncになっている。「PostgreSQL」と書かれたデータベースは、某インシデント対応の際に別のものに移行されたが、誰も図のボックスを更新しなかった。
これは怠慢ではない。物理だ。コードは週に何百回も変更される。資料は誰かが思い出したときにしか更新されない。アーキテクチャ図の半減期は、おおよそ1スプリントだ。それを過ぎると、それはフィクションになる。
目的は、決してずれない資料を書くことではない。次のエンジニアを惑わせる前に、そのずれを検知することだ。
なぜ資料はコードより速く陳腐化するのか
コードには組み込みの修正メカニズムがある:コンパイルしてテストに通るか、通らないかだ。資料にはコンパイラもなく、テストスイートもなく、CIゲートもない。間違ったダイアグラムも完璧にレンダリングされる。古くなったADRも、新鮮なものと同じくらい説得力をもって読める。
その乖離は社会的な側面もある。エンジニアがコードを更新するのは、ビルドが壊れるからだ。資料を更新するのは、罪悪感を感じるからだ。罪悪感は、信頼できないスケジューラーだ。
新しいエンジニアが入社してWikiを読むと、システムのメンタルモデルを構築する。そのモデルが6カ月前のものなら、彼らは既存の混乱を増幅させる決定を下すだろう。オンボーディングの摩擦を減らすはずだった資料が、巧妙でコストのかかる誤導の源になる。
3つのフィクションの罠
アーキテクチャ資料が最も速くフィクション化する場所が3つある。
Wikiの墓場。 Confluence、Notion、SharePointにあるアーキテクチャ資料は、リポジトリの外に存在する。コードの変更と関連付けられたコミット履歴を持たない。リファクタリングでサービスが削除されても、Wikiページはデジタルのゴーストタウンのように生き残る。ビルドは失敗しない。アラートは鳴らない。
ダイアグラムのフィクション。 Lucidchartやdraw.ioからエクスポートされ、READMEに貼り付けられた美しいダイアグラムは権威あるものに見える。だがそれは静的な画像でもある。次にアーキテクチャを変更する開発者は、デザインツールを開き、ソースファイルを探し、更新し、再エクスポートし、貼り付け直さなければならない。そのワークフローの生存率は5%だ。
全知のREADME。 すべてのサービス、すべての依存関係、すべてのデータフローを1つのファイルに記録しようとするトップレベルのREADME。それは誰も触りたがらない巨大ドキュメントになる。やがて勇敢な誰かが「このセクションは古くなっている可能性がある」という注記を追加する。そして別の誰かも。そして最終的に、文書全体が「」に包まれ、放棄される。
正直な状態を保つ生きた資料
解決策は、もっと資料を書くことではない。資料を避けられないものにすることだ。
資料をリポジトリに移動する。 資料がコード変更と同じpull requestに含まれていなければ、更新されない。ADR、ランブック、決定ログは、記述するコードの隣、docs/architecture/やdocs/adr/に置くべきだ。レビュアーが資料更新なしのリファクタリングを見たら、マージをブロックできる。
コードからダイアグラムを生成する。 Mermaid、PlantUML、Structurizrは、リポジトリ内のテキストファイルでダイアグラムを定義できる。CIジョブがすべてのコミットでレンダリングする。アーキテクチャが変われば、ダイアグラムのソースもそれに合わせて変わる。デザインツールは不要だ。
<!-- docs/architecture/data-flow.md -->
## Ingestion Pipeline
```mermaid
graph LR
A[Client SDK] -->|HTTP POST| B[Ingest API]
B -->|Pub/Sub| C[Event Consumer]
C -->|Write| D[(ClickHouse)]
このダイアグラムはdiffでレビューできる。パイプラインに新しいKafkaトピックが追加されれば、その変更はコンシューマーを追加する同じPRに現れる。
**「何を」から「なぜ」を切り離す。** コードベースはすでに、システムが何をするかを記述している。コメント、関数名、型が現在の構造を符号化している。資料は、システムがそのような形になった理由に焦点を当てるべきだ。静かにずれていくのは、決定そのものではなく、決定の背後にある論理だ。
Architecture Decision Recordsがこれを捉える。ADRは仕様書ではない。タイムスタンプ付きのメモだ。「この日、この理由のために、私たちはこれを選んだ。以下は私たちが受け入れた制約だ。」制約が変われば、ADRは新しいものに取って代わられる。古い記録は歴史として残る。
## 「何を」を自動化し、「なぜ」を書く
最も正直なアーキテクチャ資料は、手で書かないものだ。
コントローラーコードから生成されたOpenAPIスペックが、APIサーフェスを正確に記述する。TypeDoc、RustDoc、Javadocが内部の型を記述する。`cargo tree`、`go mod graph`、`webpack-bundle-analyzer`で生成された依存関係グラフが、実際のモジュール構造を示す。
より高次のアーキテクチャ制約には、自動化されたアーキテクチャテストが安全網として機能する。Javaでは、ArchUnitが「`domain`パッケージは`infrastructure`に依存してはいけない」といったルールを強制できる。Pythonでは、`import-linter`が同じことをする。Goでは、ASTを走査して禁じられたimportが現れたらビルドを失敗させる小さなテストを書ける。
```java
// This test fails the build if architecture rules break.
@ArchTest
static final ArchRule domain_independence =
noClasses()
.that().resideInAPackage("..domain..")
.should().dependOnClassesThat()
.resideInAPackage("..infrastructure..");
開発者が誤って間違ったパッケージをimportすれば、ビルドは即座に壊れる。アーキテクチャ資料が彼らに警告する必要はない。コンパイラがやってくれる。
誰も認めないトレードオフ
生きた資料は無料ではない。レビュー時間、CIの分数、そして変更が新しいADRを必要とするかどうかについての時折の議論がコストだ。
すべてのシステムがダイアグラムを必要とするわけではない。 3層の単一モノリスにはC4モデルは不要だ。生成された資料を維持する労力は、システムを誤解する痛みに比例すべきだ。間違ったメンタルモデルがデバッグに1日かかるなら、ダイアグラムに1時間投資しろ。5分で済むなら、コメントを書け。
生成された資料も嘘をつく。 コードから生成されたOpenAPIスペックは、ドキュメント化し忘れた内部のエンドポイントも含め、すべてのエンドポイントを記述する。依存関係グラフは、アーキテクチャに違反するimportも含め、すべてのimportを示す。生成された真実は正確だが、常に有用というわけではない。何が重要かを強調するために、人間のキュレーションは依然として必要だ。
ADRは蓄積する。 2年後には、docs/adr/に30のADRがあるかもしれない。ほとんどは無関係だ。解決策は削除することではない。明確に印をつけることだ:status: supersededと、代替案へのリンクを。歴史には価値がある。混乱には価値がない。
動作する最小構成
ドキュメンテーションプラットフォームは不要だ。リポジトリに3つのものが必要だ。
- 決定事項用の
docs/adr/YYYY-MM-DD-title.md。軽量なテンプレートを使え:
# ADR 012: Event Storage Backend
- Status: accepted
- Date: 2026-03-15
## Context
We need durable storage for ingestion events with sub-second query latency.
## Decision
Use ClickHouse for hot storage, S3 for cold archival.
## Consequences
- Fast analytical queries on recent data.
- Complex operational footprint compared to PostgreSQL.
- Migration path defined in ADR 013.
-
システム境界とデータフロー用のMermaidダイアグラムを含む
docs/architecture/*.md。構造的なコード変更と同じPRで資料更新を必須とする。 -
最もコストのかかる不変条件を強制する1つのアーキテクチャテスト。ルールが1つしかないなら、最後の痛いリファクタリングを防ぐものにしろ。システムが成長するにつれて追加すればいい。
FAQ
すべてのマイクロサービスをダイアグラム化する必要があるか?
いいえ。チームが引き継ぐ境界、データが信頼ゾーンを横切る場所、障害が連鎖する場所をダイアグラム化しろ。内部のCRUDサービスのダイアグラムは、通常無駄だ。どのサービスがペイメントゲートウェイを呼び出すかのダイアグラムは、通常価値がある。
チームがすでにConfluenceを使っている場合はどうするか?
重要な資料をリポジトリにミラーリングして、そこからリンクする。真実のソースはgitの中に留まる。Wikiは利便性の層になる。Wikiがずれても、エンジニアは本物のバージョンをどこで見つけられるか知っている。
ADRはいくつあれば多すぎるか?
上限はないが、可読性の限界はある。新しいエンジニアがdocs/adr/を眺めて10分以内にシステムの進化を理解できなければ、インデックスを追加しろ。サブシステムごとにグループ化しろ。廃止された記録を明確に印づけろ。
非技術的なステークホルダー向けのWikiはどうか?
プロダクトマネージャーと経営陣には高次のサマリーが必要だ。ADRインデックスからそれを生成しろ。別の物語を保守しないこと。同じ事実がソースコードから流れ、ADRを通じて、人間向けのサマリーになる。1つの真実のソース、複数のビュー。
1つのADRと1つのテストから始めろ
この週にドキュメンテーション文化を一新する必要はない。最後に混乱を招いたアーキテクチャ上の決定を選べ。なぜその選択をしたのかを説明するADRを1つ書け。自動的に強制されてほしいと願う不変条件を1つ選べ。誰かがそれを違反したときにビルドを失敗させるアーキテクチャテストを1つ書け。
この2つの成果物は正直な状態を保つ。なぜなら、それらはリポジトリに存在し、PRでレビューされ、CIに通るか出荷されないかだからだ。それ以外のすべて、Wikiページ、スライドデッキ、カンファレンスポスターは二次的だ。あれば嬉しい。役に立つかもしれない。おそらく間違っている。