フューチャー技術ブログ

設計ドキュメント腐る問題、Git管理で運用してみた結果

はじめに

TIG真野です。

秋のブログ週間2023 の3本目は、設計ドキュメントをGit管理して腐らせないようにがんばってみた話をします。

前段として6年前、「我々はいかにシステム開発におけるドキュメント腐る問題と戦えば良いのか」という記事を書いたのですが、その後の試行錯誤はどこにも残していないことに気づきました。普段のフューチャー技術ブログですとちょっと引け目を感じるテーマですが、秋の夜長を楽しむため読み物成分を多めに書くというテーマのこのブログリレーにピッタリな気がするため、この機会をお借りします。

ドキュメントも色々な種別があるかと思いますが、この記事では設計ドキュメントを指すことにします。設計ドキュメントは開発メンバーが参照するもので、ステークホルダーへの説明資料に引用して使うことはあれど、主目的は異なるという前提です。Design Docの場合もありますし、システム構成図、ERD、システム間連携I/F定義書、開発規約、環境構築手順などを含みます。

ドキュメント腐る問題とは

ドキュメント腐る問題とは、設計時に作成した各種ドキュメントがGoogle Driveやファイルサーバ上で陳腐化してしまい、現状の正しい状態を指していない状態を指します。せっかく新規参画者がキャッチアップしようとしてもドキュメントが真実を示していないという、困った問題です。

一部の界隈でこう読んでいる名称ですが、少なからず誰しもが経験してきたことでしょう。

設計ドキュメントをGit管理に寄せる

対策としてここ4,5年ほど、コードと同期すべき設計ドキュメント全てをGit管理に寄せる方針を取ってきました。なるべくテキストベースで設計ドキュメントを記載し、コードと同じくPull Requestでレビューするフローです。markdownlintで設計書の品質を高める の記事にも書いたように、以下のフォーマット/ツールを使っています。

  • Github-flavored Markdown
    • 基本的にフォルダを切ってREADME.mdに書いていきます
    • 参照はGitHubなどのブランディングで見ることが多いです(ローカルのVS Codeなどで見ても良いですが)
    • Widescreen for GitHub のChrome拡張はオススメです。横幅が広くなり視認性があがります
  • PlantUML
    • シーケンス図、業務フロー図はMarkdown中にPlantUMLで記載し、Markdownから![xxx構成図](xxx_構成図.drawio.png) などで画像参照しています
    • 参照はGitHub上からも見れるように、pegmatite というChrome拡張を利用
    • 今ならMermaidを採用するかもしれませんが、ミンさんが作ったPlantUMLのテーマを推したかったのもあり、継続して使っています
  • Diagrams.net
    • システム構成図はDiagrams.net(draw.io)で作成し、.drawio.png の拡張子でMarkdownから参照
    • レビューが難しいような作り込んだ画像のケースは、Pull Request時に差分を赤丸で囲ったバージョンも用意してもらったり、テキストでポイントを書いてもらったりします
  • Web API定義
    • OpenAPI SpecのYAMLファイル
    • 参照はGitHub上からも見れるように、swagger-viewer を利用していましたが、最近動かなくなって対策を検討中
  • ERD
    • A5:SQL Mk-2 の .a5er 拡張子のファイルをコミット
    • ini形式のテキストファイルであるため、差分がわかりやすい
  • その他、DynamoDBなどのデータモデル
    • Markdown中に表形式で表現。A5:SQL Mk-2に寄せても良い気はしています

markdownlintの記事でも書いていますが、単体テストデータ管理や区分値管理など、一部Excelを利用する場面はありますが、このようなファイルを同時に複数のブランチで変更することは今の私の環境においては、あまりありません。したがって、Git上でConflictが発生するのはテキストファイルのみとなり、Conflictの解消に大きな手間はかかりません。

Git管理にしていない成果物

一方で以下のファイルは、Git対象外で管理することが多く、多くはスライドやスプレッドシートで作成しています。理由として、下記の資料は基本的にはワンショットでの作成で、何か状況が変化したとしても大本の資料を修正することはない(腐っても良いというかそれが当たり前)であるためです。

  • ステークホルダーへの進捗報告、仕様相談など
  • テスト計画、テストケース一覧、実施エビデンス
  • チームの振り返り資料(KPT的な)
  • 障害調査、報告

フォルダ構成について

アプリケーション開発と同一のリポジトリで docs フォルダを切って管理しています。

イメージとしては次のようなフォルダ構成です。

.                           # リポジトリルート
├── README.md # 全体のインデックス
├── backend # バックエンドのコード
│   └── ...
├── docs # ドキュメント全般
│ ├── 01. 業務ドメイン
│ ├── 02. システム設計
│ ├── 03. データモデル
│ ├── 04. ProgramDesign
│ ├── 05. システム間I/F
│ ├── ...
│ ├── 91. 環境構築
│   └── ...
├── frontend # フロントエンドのコード
│   └── ...
├── infrastrucutre # Terraform, Ansibleなどの構成管理
│   └── ...
└── ...

ドキュメントのみを管理する独立したリポジトリを作成することも考えましたが、以下の理由でこの形に落ち着きました。

  • 私達のチーム特性やガバナンス上、基本的にはリポジトリの参照/書き込みの権限は設計ドキュメントとコードで分ける必要はなかった
  • あるアプリケーション開発で複数リポジトリのInviteするなどの管理が面倒
  • リポジトリが別だと設計書とコードで同期をとったPull Requestも別になってしまうため、本当の意味での同期が難しくなるため

運用のコツ、やってみた感想

EditorConnfig、Prettierなどのフォーマットと、Markdownlintでのリント、CSpellなどのスペルチェックなどをCIに組み込んでといったテクニカル面の話はここでは割愛して、運用周りで感じたコツのようなものと感想をまとめていきます。あくまで私が経験した中で機能するなと感じた内容ですので、かいつまんで読んでいただければです。Tips的には、ドキュメントをコードから自動生成したり、ドキュメントからコードを自動生成するといったフローを踏むことで強制的に同期させることもありますが、これもテクニカル面が強くなるので割愛しています。

Wiki管理は高速で腐っていった

実は設計ドキュメントをGit管理する前に、数名の小さなチームでしたが一度Wikiで管理できないか試してみました。結果としては全くメンテナンスがされずで、下手をするとGoogle Drive(ファイルサーバ)時代より使うべきではない言葉なので修正してくださいありさまだった気がします。

理由:

  • Wikiだと、設計ドキュメントを作成/更新する際のレビュープロセスを整えるのが厳しい
    • コードと同じようにPull Request上で議論して、より良い物にしていくフローができず、モチベーションが上がらなかったのかなと思いました
    • 逆に開発プロセスと同様の設計ドキュメントをPull Requestベースで行うのは、そのような開発フローに慣れていないメンバーでもそこまで違和感を感じていなかったように見えます
  • Issueに紐づけての管理が難しい
    • 設計ドキュメントの陳腐化に気が付き、Issueだけ起票して対応のタイミングや担当者を別で管理したい場合でも、Wikiの場合は具体的にどのように直したか不明確になりがちでした

GitLab Handbookでも類似の話題があったと思います。同じ結論です。

設計ドキュメントを外部に共有したい時に困らないか?

正直なところ、面倒に思うときがしばしばあります。スライドで作成した場合は、そのURLや成果物ファイルを直接共有できますが、リポジトリ管理の場合は権限付与から実施しないとならないため、少し面倒です。適切な権限設定と、有効期間をどう考えるかは悩みです。

ただし、ステークホルダー向けの資料は従来どおりスライドなどで作成しているため、常日頃からそれなりに適切に議題に出していれば、振り返ってみてもそこまで開発チーム向けの設計ドキュメントを渡す必要があるケースは少なかったです。記憶の中で情報提供で多いのは以下です。

  • AWSインフラ構成図、ネットワーク構成図(どのサービスを利用するかのレビューや、監視運用などガバナンスチェックなど)
  • API定義(これはOpenAPI Specを使っているため、そのままYAMLを渡したりHTMLを渡していました)
  • ERD定義(A5:SQL Mk-2 はERDをPDF出力できるためそれを渡していました)

コードを修正したとき、どのドキュメントを一緒に直すか分からない問題

同期を取らないドキュメントを修正せず、コードだけ直してPull Requestに出しちゃう問題です。しばしば発生します。参画歴が浅いメンバーどころか、立ち上げからいる自分ですら見落とすときがあります。例えばバックエンドのWeb APIで、どのAPIがどのDBにCRUDするかを、プログラム詳細設計に書いていたとします。SQLに結合テーブルを追加してテストを直すので手一杯で、ドキュメントのアップデートが追いつかないと行ったケースです。

対策としては次がありますが、自動化しない限りはレビュアー含めて全員でチェックする必要があります。がんばりましょう。

  • SQLを解析してCRUD表を自動生成する/チェックする
  • Pull Requestのテンプレートに、設計ドキュメントも修正したみたいなチェックボックスを追加する
  • 開発規約の作業フローに、そういった同期を取るべきリソースを記載し、ルール化しておく

設計ドキュメントとコードを同じPull Requestで出すのに慣れ過ぎると、設計レビューがおざなりになりがち

チームの開発規約をきっちり定義すれば防げるかと思いますが、設計書とコードを同期をとるために同じPull Requestでレビューするのに慣れると、粒度が大きい改修内容であっても、コードが実装された状態で設計ドキュメントもレビューすることになります。DBにカラムを1つ追加くらいで内容に議論の余地がなければその方が効率的ですが、設計レベルで手戻りがあるケースが何度か発生しました。

そのため、以下のような方針が推奨であると、開発規約に以下の流れを推奨すると追記しました。

  1. 設計ドキュメントのみのPull Requestを作成して、チーム内レビューを通すこと
  2. 1が終わった後に、コード改修を実施したPull Requestを出すこと

小さなものも含めて、全て設計ドキュメントレビューとコード改修のPRを分離すると、それはそれで不効率であるため、判断は各メンバーに委ねるレベルにしていますが、大規模開発になると一律分離するといった判断にも繋がってくるかなと思います。

これの効果ですが、レビュアーとしても次の観点で有益でした。

  • 設計ドキュメントとコードが同じPull Requestに無いので、設計内容に集中してレビューできる
  • 設計上、必達ではないもののWANTで直して欲しい内容があっても、すでにコードが実装されていて手戻りになるため、スケジュールを盾にApproveせざるを得ない状況がある。最初に設計レビューだけすると、これらの不健全な状況を防ぐことができる

ごく一般論ですし、言うまでもなく当たり前の話ですが、設計→レビュー→実装→レビュー のステップは分けましょうといった内容です。下手に全てGit管理なので、人によっては設計という行為が実装と概念が混ざってしまい、こういう必要な手順をスキップしてしまう人もでてくるんだなといった所感です。

結局人で管理する部分が残るのであれば、陳腐化しちゃいますよね

はい、自動生成系、静的解析での整合性チェックを完全に整えない限りは、必ず設計ドキュメントは陳腐化します。ただ、改善するチャンスはいくつかあると思います。

例えば、私は以下のタイミングで設計ドキュメントをよく修正します

  1. 新規参画者向けにオンボーディングする場合
  2. 自分が開発していた機能を、だれかに引き継いでもらうタイミング
  3. あるメンバーが開発していた機能を、自分などが引き継ぐタイミング
  4. だれかに機能仕様などの質問を受け、設計ドキュメントのURLだけ渡して終わらせたい場合

1, 2, 4は自分自身がだれかに状況を説明すると思うのですが、その際に設計ドキュメントを使うようにします。そうすると、説明を通して過不足や話しにくい部分、陳腐化している部分に気がつくことができます。また、説明を受けているメンバーからの質問も、ドキュメントをアップデートするチャンスです。

良いドキュメントの状態をキープできると、その後の開発生産性や開発者体験にプラスに働きますので、最初は直すべき部分が多くて大変かと思いますが、継続して良い状態になるよう手入れしてきましょう。

「あとでドキュメントを直す時間を取ろう」は大体、そんな時間は来ません。直すべきは、直したほうが効率が上がるその都度のタイミングだと思いますので、ドキュメントを直すと自分も楽になる範囲内でキレイにしていきましょう。

意識するのは、設計ドキュメントのURLを送るだけで説明できる余地を増やすことだと思います。これもGitLab Handbookの考え方に近しいと思います。

drawioで作るコツ

実践Drawio 記事がおすすめです。個人的には「3.2. Lineジャンプ」は必ず設定して欲しいと思っています。

レイヤー化はシンプルな図であれば不要かと思いますが、次の背景色は必ず設定したほうが良いと思います。これがないと構成図が透過になり、ダークモードのエディタなどで見る時に不便と感じる時がありました(もちろん、出力時に背景を透明にするにチェックを入れなければ良いのですが..)

チームメンバー以外に作成した構成図などを共有することがほとんど無い資料に関しては、基本的にタイトル、作成者、作成日、更新者などのヘッダは不要かと思います。

PlantUML vs draw.io

シーケンス図などはどちらでも活用できるため、最初はどちらで書こうか迷うこともあるかもしれません。

基本的にはPlantUMLで書けるものは、全てPlantUMLで書くべきだと思います。テキストベースであるため、おそらく少し慣れればdraw.ioより生産性が高いのと、細かいインデントなどの好みの違いが出にくいため、レビューもスムーズだと思います。何より、いったん作ってしまえばその後の改修での、git diffが見やすいため、レビューやトレーサビリティでも優位なためです。

とはいえ、複雑度が高いものには余計に時間がかかるため、一点もの構成図などは素直にdraw.ioを使ったほうが良いかなと思います。

docs配下の画像でどれがdraw.ioで編集可能か分かるように

基本的には拡張子を .drawio.png.drawio.svg にするようにしています。ときには報告資料で作成したスライドの図表をそのまま、設計図に転用したい場合もあります(xxxの会議での決定事項です、といった背景説明の時にゆうこうなため)。その場合は xxx.png といった拡張子にして、区別するようにしています。

チケットに記載した内容と設計ドキュメントで内容が重複する

しばしば、チケットに課題や背景、対応案などしっかり記載すると、設計ドキュメント側と重複する内容になりうることがあります。このケースだと、何かしら背景部分にアップデートが入ると、チケット・設計ドキュメントのダブルメンテになり、冗長です。

この場合は、チケットのリンクを設計ドキュメントに貼って省略するでよいでしょう。もし、設計開発上、差分や注意事項があれば追記すると良いと思います。その対応が後日、別メンバーへの引き継ぎなどで困る場合は、改めてチケットの内容を振り下ろすなどすると良いと思います。これはその機能の粒度やニーズ(ユーザーの関心事が大きく、改修頻度が多いかどうか)にも依存してくると思います。

Markdownで表を作るのが面倒

分かります。私は初回の表は、スプレッドシートで作成したのち、tablegeneratorというWebツールで、Markdown変換しています。

業務システムだと列数がとにかく多くなってくるため、コツとしては絵文字などを上手く取り入れ、視認性が高く、楽しいドキュメントにすることだと思います。

例えば、「参照可能/参照不可」 といった内容をセルに書くのではなく、「✅、✔、✘、❌」 といったアイコンで代用できないか考えます(凡例をつければよいのです)。

楽しく見せるというのは設計ドキュメントを維持管理する上で重要なモチベーションとなります。GitHubなどで有名なリポジトリのREADMEを見ると、各種バッチを付けたり、ターミナルの動画を駆使したり工夫が満載です。ぜひそういった技を取り入れていくと良いかなと思います。

ドキュメントのレビューで、表現が伝わる/伝わりにくいでやり取りのホップ数が増える

設計ドキュメントをこまめにアップデートしていると、その表現だと伝わりにくいといったレビューコメントが発生します。どうしても差分だけ見てコメントするとそのような感想になりがちですが、全体を通して読むと文脈上は自明であることも多いため、そういったレビューコメントを付けられても困惑してしまうことが多いです。

そのため、設計ドキュメントについても、できる限りsuggestionを用いることを徹底しています。コードより人それぞれの受け取り方が異なりやすいため、どう直してほしいかがダイレクトに伝わります。

image.png

tocは腐る

toc(Table of Contents)をREADMEに手動で書いてくれる人がいます。しかししばしば陳腐化して本文と同期が取れなくなった設計ドキュメントを見てきました。チームルールとして一律、書かないようにするのが良いと思います。

もし、必要な場合は[GitHub]README.mdの目次生成をAction「toc-generator」による自動化で楽しよう | DevelopersIO のような仕組みで統一すると良いと思います。

気になったらすぐ直す習慣を

1ファイルだけであれば、鉛筆マークから直接編集→Pull Requestまでブラウザで完結して作業できます。

image.png

おそらく、設計ドキュメントを参照する場合、大半はブラウザで参照していると思うので、エディタに切り替えなくて済むため、便利です。

ドキュメント修正の敷居はなるべく高くせず気軽に直していく文化をチームで作れると良いと思います。

やってみた結果

運用のコツや所感で書いたように、ナレッジはいくつかあるものの、基本的には設計ドキュメントをGit管理することのメリットは大きいように思えます。

開発の制約として、テキストベースの設計書が許容できないなどといった前提がなければ、これからもこのような形式を採用すると思います。

まとめ

設計書をテキストファイルで作成し、Git管理することで、ドキュメントの陳腐化を防げないかトライしてみました。

最終的には開発メンバー各々の意識に支えられる面もありますが、コードをレビューするのと同様に設計レビューを行えるため、フローに載せやすさはあります。

自動生成、静的解析などCIでワークフローをより強化させやすい面も気に入っています。この方向で数年はドキュメント腐る問題にあらがってみたいと思います。

次は斎藤さんの初心者が暗号の基礎と歴史を勉強して見たです。