ドキュメント運用について考える機会があったので、そのとき考えてたことをダンプしてみる。 実際に運用しているわけではないので机上の空論だが、文字に起こしてみることで何か得られないかと思いやってみる。
ドキュメントを運用する目的 (WHY)
私がドキュメントを読みたくなるタイミングは大体次のように分類される。
- ある時点での意思決定を知りたいとき
- 新たな実装するときに、その時点で決まっている仕様や設計を確認したいとき
- コードの意図が分からず、なぜこのような実装になったか知りたいとき
- 具体例
- PRD
- Design Docs
- パッチ作業の本番環境への作業手順書
- などなど
- 現時点での最新の仕様の確認したいとき
- PRJ に新しく参加するとき
- デプロイされている API の Spec を確認するとき
- 具体例
- API 仕様
- データベーススキーマ
- プロジェクト憲章
- Getting Started
- 現在のアーキテクチャ図
- デプロイ方法
- 画面遷移
- などなど
前者は差分を表すドキュメントであり、後者は言わば差分を適用し終えた最新のドキュメントである。
この 2 種類のドキュメントを適切に用意できればハッピーになれるので、これらのドキュメントを継続的に用意することがドキュメントを運用する目的になる。
ここからは本来の意味とは少しずれるかもしれないが、ある時点での意思決定を表すドキュメントをフロー型と呼び、最新の仕様が書かれたドキュメントをストック型と呼ぶ。
考えていること
改めてどういうときにドキュメントを読むのかを考えてみると、前者は実装のタイミングで読むのに対し、後者は実装前のフェーズで読むことが多いという発見があった。
これは GitHub 上で開発をしていることを考えると、差分である PR を作るときに差分のドキュメントが欲しくなり、PR を作る前の段階で最新の仕様を知りたくなるのはとても自然に感じる。
逆に言えば、差分が知りたいのに差分がなかったり、その逆がなかったりすると、開発フローとドキュメントの相性が悪くなり、「欲しいドキュメントがない」という状態になってしまう。そのため、ドキュメントを運用を頑張るなら GitHub の開発フローとうまく噛み合った運用フローを考える必要がありそう。
目的を達成する上で実現したいこと (WHAT)
共通
- できるだけ人間のコストが低い
フロー型ドキュメント
MUST
- ある時点での意思決定が書かれている
- コードから関連するドキュメントに到達できる
- きれいに整備せず書き捨てでも良い
WANT
- どんどん気軽に書き捨てられる仕組みがある
ストック型ドキュメント
MUST
- 常に最新のドキュメントが読める
WANT
- 自動で最新の状態が維持される
- コードを読まずとも簡単にドキュメントを発見できる
ソフトウェア開発において最も貴重なのは人間なので、人間の工数はできるだけ吸い取られないようにする。できるだけ機械に寄せていく。
考えていること
フロー型のドキュメントは書くときはトップダウン(執筆 → 実装)の流れになり、読むときは(実装 → 執筆)の流れになることが多い。そのため、フロー型のドキュメントはコードから検索できるようにするようにするのが望ましそう。
また、フロー型のドキュメントはストック型に比べて存在することが大事なので質より量が大事なので量が多くなる。そのため、テキスト検索では目的のドキュメントを見つけるのは難しい。もちろん検索システムが優れているドキュメント管理サービスを使えば良いが、そもそもコードを読んでいるときにドキュメントを読みたいのであれば、コードから直接検索できるようほうが合理的に感じる。
ストック型のドキュメントを常に最新のドキュメントを維持するのはとてもコストが高いので、できるだけ自動化できるようにし、自動化できないものは人間の手によって更新し続けられる仕組みを用意する。それができないものはフロー ß 型として管理するようにしたい。 そうなると、必然的にストック型のドキュメントの量は減っていきそう。 これは検索性が上がり、最新のドキュメントに保つコストが減るのでポジティブに捉えて良さそう。
ドキュメントの管理方法 (HOW)
フロー型ドキュメント
- フロー型ドキュメントは使い捨てで良いのでしっかりと書く必要はないなら、いっそ issue や JIRA チケットなどタスク管理ツール側に全部書いてしまい、そのリンクをコミットメッセージか PR の説明文に貼る運用にする
- フロー型ドキュメントは検索で引っかかることよりもコードから辿れることが重要なら、"ドキュメント"として用意するのをやめ、議論の過程をそのままリンクするようにすれば、ちゃんとドキュメントを作る手間もなくなり良さそうに見える。
- ただし、口頭で議論してしまうと何も残らないので、ある程度議事録のメモを残すことが必要そう。(要件を考えれば Slack に関してはリンクを貼るだけで良いかも)
- もう少し頑張れそうな(きちんと書くべきだと思う)ときは、ドキュメントとして書き起こして、そのリンクをコミットメッセージか PR の説明文に貼る運用にする
- もちろん、書くべきだと思ったときはドキュメントとしてまとめても良い。
- フロー型ドキュメントとして整理しているので、更新しなければならないこともないので継続的なコストは低い。
まとめると、"コミットから辿れれば何でもええや"という考え。
ストック型ドキュメント
実現すべきことはコードの変更とドキュメントの更新が同期されることである。
これを実現するためには、
- OpenAPI や Protobuf など自動生成ツールが用意されているものがあればそれを使う
- 関連するコードを変更したにも関わらず対象のドキュメントが更新されていない場合は CI を落とす
などをすれば可能そうである。できるだけ機械にやらせることで人間のコストも低く抑えられる。
なお、CI で落とすタイプのドキュメントは数が多くなりすぎないように注意する。いくら CI でチェックできようが最終的に直すのは人間である。CI で何度も落とされるとモチベも下がるし、ドキュメントの数が増えると人間のコストがどんどん増えていく。
考えていること
正直なところ、「俺の考える最強のドキュメント管理ツール」が世の中に存在していないように感じる。そのため、HOW の部分はあまりしっくり来ていない。 上手いこと最新の状態が更新し続けられる仕組みが欲しいが、既存のツールにはそういった機能がないものが多い、、、
ストック型に関しては、必要以上に頑張らずにプロダクトのコアな部分だけをストック型でメンテし続けるようにし、それ以外はフロー型として整理してしまい、更新を諦めるほうが長く運用を続けるには良いかもしれない。
フロー型は「とりあえずリンクを貼れ」の一言に尽きる。
まだ検討が足りていないところ
ドキュメント管理ツール
git はブランチとマージを使うことでフロー型とストック型を同時に扱える素晴らしいツールである。一方で、よく使われるドキュメントサービスはこのような仕組みを用意していることが少ない。ブランチとマージができるドキュメントサービスを使うことで、フロー型のドキュメントからストック型のドキュメントを生成するといったことができるようになり、より運用を楽にできるのではないかと考えている。
人間がストック型のドキュメントを更新する場合は、差分のレビューが完了するまでドキュメントを更新したくないが、それをしようとすると別の差分を表すドキュメントを作成することになる。 結果としてストック型のドキュメントを作っているはずが、フロー型のドキュメントを作ることになってしまう。 更に、フロー型のドキュメントを作っただけで満足してしまい、レビューが終わってもストック型ドキュメントが更新されないことも多い。わざわざ 2 つドキュメントを作るのはしんどい。
また、たとえこのようなツールが存在したとしても、git とドキュメント管理サービスの同期が取れてないと不整合が起こる可能性もある。 ドキュメントは git でコードと一緒に管理するのが一番幸せなのかもしれない。
何をストック型ドキュメントとして書くべきか
WHY の部分で例を上げてみたが、これらを全て書くべきかどうか、他にも書くべきものがないかどうかがわからない。
書くドキュメントが増えれば増えるほど、コストがかかる。かといって書く量が少なすぎればドキュメントとして役に立たない。この塩梅をどうすべきか難しい。
仕様変更が積み重なった複雑な仕様はどう整理すべきか
仕様変更のたびにフロー型のドキュメントを作成している場合、それらを追えば最新の仕様は分かるが、それを追うコストはとても高い。
こうなってしまった仕様はどのタイミングでストック型のドキュメントは作るべきなのだろうか。もしくは作らないべきなのだろうか