仕様書が腐るのは、書き手のせいではない
半年前の仕様書を開いたら、画面の項目名が実物と違っていました。図に描かれた処理の流れは、いつの間にか作り替えられています。更新履歴はリリース当日の行で止まったままで、その後の障害対応も、運用しながら足していった仕様も、1行も入っていません。書いた本人はもうそのチームにいません。ソフトウェア開発に関わっていれば、一度は見た光景ではないでしょうか。
こうなると、たいてい「更新ルールを決めよう」「直したら必ず反映しよう」という話に落ち着きます。ただ、私たちはこれを書き手の怠慢だとは考えていません。同じ人が、コードでは毎日きちんと差分をレビューし、変更の理由を履歴に残しているからです。人が変わっていないのに結果が変わるなら、違っているのは仕組みのほうです。
この連載では、AsciiDoc + Kroki + Vivliostyle で仕様書を書く環境を実際に組み立てていきます。初回となる今回は、手順ではなく「なぜこの構成にしたのか」という設計判断の部分を話します。
仕様書が腐る、3つの構造的な理由
更新されなくなった仕様書を観察すると、原因はおおむね次の3つに分かれます。
1. 差分が読めない
バイナリ形式の文書は、何がどう変わったかを機械的に取り出せません。結果としてレビューは「全文の読み直し」になります。30ページの文書で1行直しただけでも、レビュアーの負担は30ページ分です。これが数回続くと「軽微だからレビューは省略」という運用が生まれ、そこから先は誰も全体像を把握していない状態になります。
2. 図が本文と別管理
図は作図ツールで描き、書き出した画像を本文に貼り付けます。この運用がいちばん壊れやすい部分です。編集可能な原本ファイルは個人のPCか、どこかの共有フォルダにあり、数か月後には行方不明になります。原本がなければ図は直せないので、本文だけが更新され、図は古いまま残ります。しかも読み手は、たいてい本文より図を信じます。
3. レビューが属人化
「なぜこの仕様にしたのか」という判断の経緯は、たいていチャットや会議の口頭に残っていて、文書の中にも履歴の中にもありません。半年後に「この制約は何のためですか」と聞かれて答えられる人がいなくなり、怖くて触れない記述だけが積み上がっていきます。
「コードと同じ土俵に載せる」という原則
この3つは別々の問題に見えますが、たどると1点に集まります。文書が、コードと同じ版管理の仕組みに乗っていないことです。
本文がバイナリ形式のままでは、リポジトリに置いたところで中身の差分は読めず、レビューは全文の読み直しに戻ります。図の原本は作図ツールの中や個人のPC、共有フォルダといった版管理の外にあるため、本文と一緒には動かず、図だけが古いまま取り残されます。変更の理由もチャットや会議という版管理の外にあるため、文書と一緒には残らず、判断の経緯が失われます。
ならば、立てるべき原則はひとつで済みます。仕様書をコードと同じ土俵に載せる。 具体的には、仕様書をプレーンテキストで書いてコードと同じリポジトリに置き、変更はプルリクエストで出して差分でレビューし、図も本文と同じコミットに含めます。この3つが満たせれば、あとはチームがコードですでに回している仕組み――レビュー、履歴、CI――をそのまま流用できます。新しい運用ルールを増やさずに済むことが、この原則の最大の利点です。
なぜ Markdown ではなく AsciiDoc なのか
テキストで書くだけなら Markdown で十分です。実際この記事も Markdown で書いています。それでも仕様書に AsciiDoc を選んだのは、次の4点が効いてくるからです。
includeによるファイル分割:他のファイルを本文に取り込めます。章ごとにファイルを分ければ、レビューの単位もコンフリクトの範囲も章単位に収まります。- 相互参照:「第3章参照」と書く代わりに、章や図に付けた ID を参照できます。章を並べ替えても番号がずれません。
- 属性(変数):製品名やバージョンを1か所で定義して本文から参照できます。改版のたびの一括置換が要りません。
- 表現力:セル結合を含む表、注記、脚注、多階層のリストが標準の記法で書けます。仕様書では意外と頻繁に必要になります。
誤解のないように書いておくと、Markdown が劣るという話ではありません。1枚で説明できる文書なら、Markdown の手軽さは魅力的です。 分割と相互参照が効いてくるのは、章立てされていて、複数人が並行して直し、何度も改版される文書です。仕様書がちょうどそこに当たる、というだけの判断です。
なぜ図をコードで書くのか
図をテキストから生成すれば、さきほどの「図が本文と別管理」がそのまま消えます。図のソースは本文と同じファイル(または隣のファイル)に置かれ、同じコミットに乗り、レビューで差分として読めます。
[plantuml,login-flow,svg]
----
@startuml
User -> App: ログイン要求
App -> Auth: 資格情報を検証
Auth --> App: アクセストークン
@enduml
----
矢印を1本足した変更が「1行の追加」として見えます。これが画像の差し替えとの決定的な違いです。
図の記法は PlantUML だけではありません。シーケンス図は PlantUML、構成図は Graphviz、というように用途で使い分けたくなります。ここで Kroki を挟むと、多数の記法を1つのエンドポイントで扱えます。記法ごとに処理系をローカルへ入れて回る必要がなく、新しい記法を試すコストがほぼゼロになります。
なぜ HTML で終わらせず、PDF まで出すのか
閲覧するだけなら HTML で足ります。それでも PDF を出すのは、現場に次の要求が残っているからです。納品物として提出する、押印して保管する、版数を固定して「この版で合意した」と示す――いずれも、内容が動かない成果物であることを前提にした要求です。
レビューの場面でも PDF は効きます。「12ページの図3」と言えば全員が同じ場所を見られますが、HTML にはページ番号がありません。閲覧環境に依存しないことも重要で、相手のブラウザやネットワークの状態に関係なく同じ体裁で読めます。
ですから HTML を捨てるわけではありません。普段の確認は HTML、節目の成果物は PDF。 同じ AsciiDoc から両方を出す、という位置づけです。
この構成で捨てたもの
利点だけを並べても判断材料になりません。この構成で確実に失うものを挙げます。
- WYSIWYG がない:書いている画面と仕上がりが一致しません。体裁の確認はビルド後になります。
- 非エンジニアが直接編集しづらい:Git の操作とテキスト記法が前提になります。編集を依頼したい相手がいる場合、ここが最大の障壁です。
- ビルド時間がかかる:図の生成と PDF 組版は一瞬では終わりません。文書が育つほど、保存してすぐ確認、というわけにいかなくなります。
- 環境構築の初期コストがかかる:最初の1本を出すまでに、編集から PDF 出力までを通す環境を用意する必要があります。
短命な文書や、非エンジニアが主に書く文書なら、この投資は回収できません。長く生きる文書に限って効く構成だと考えています。
次回から、実際に作っていきます
次回はまず、AsciiDoc 形式のファイル1つから A4 の PDF が1本出るところまでを作ります。その次に Kroki で図を本文と同じソースから生成できるようにし、最後に表紙・目次・改ページで納品できる体裁を整えて、複数の文書をまとめてビルドできるところまで進めます。
どの回も、動く最小の状態から始めて少しずつ足していきます。手を動かしながら、自分の現場に合うかどうかを判断してみてください。
この回で使ったツール
- AsciiDoc — 技術文書向けの軽量マークアップ言語
- Kroki — テキストの図式記法を画像に変換するサーバー
- PlantUML — テキストから UML 図などを生成する記法
- Graphviz — グラフ構造を記述して図を生成するツール
- Vivliostyle — CSS で組版して HTML と PDF を生成するツール