質の高い技術文書を書く方法

大学や大学院で論文の書き方を鍛え上げた人たちには遠く遠く及ばないが、僕の様なはぐれもの1でも最近は Amazon 社内で文書の質が高いと評価してもらえるまでにはなった。Software Engineer として、コードでのアウトプットはもちろん大事だけど、文書のアウトプット(およびそれによって得られた実際のアウトプット)は同じだけ重要である2。今回は自分が最近どういうところに気をつけて技術文書を書いているのか、ということについて数年後の自分が忘れてないことを確かめられる様にまとめておく。

そもそも文書とは?

英語だと document。ここで指す(技術)文書とは、人間が読む文体で書かれた技術に関連する情報、といったものだ。具体的に言うと以下の様なものを想定している:

  1. 新しいプロジェクトの骨子を説明する資料
  2. 会議の叩き台となる 1 枚ペラ
  3. 本番環境に変更を加えるにあたっての包括的な情報や具体的な手順
  4. 技術仕様を網羅的に説明した一連の文章

おそらく皆さんが「ドキュメント」と聞いて一番に思い浮かぶものは一番最後の例(4.)だろう。各種サービスやソフトウェアにはこうしたドキュメントは必須だ。ただ、技術を実際に使えるものにしていくにあたって、それはどちらかというと最後のフェーズ(および運用フェーズ)で高い価値を発揮するものである。自分たち一介の技術者(開発者)にとっては、そのフェーズに持っていくまでをどうするかの方が日々の仕事では大きなウェイトを占めているのではないだろうか(少なくとも僕の場合はそう)。

このエントリでは、どちらかというと 1,2,3 の様な、何かを前に進めるに当たって書くべきである document を中心に自分の書き方を解説していくが、同じ原則を 4 や他の document にも当てはめることはできるはずだ。

tl;dr - これを抑えておこう

  • 文書から得られるアウトプットが明確で、読み手のレベルによらず一定に伝わること

この一文に大体このエントリで伝えたいことが集約できている。質の高い技術文書とは、誰が読んでもハッキリとした輪郭で必要十分な情報が伝わるものである。

文書の使い方

そもそも 1,2,3 の様な文書をどのように使うかだが、基本的には頭から読んでもらって、議論をしたのちに次のアクションを決める、といった形になる。Amazon ではミーティングの際にこうした文書を全員で黙って 15 分程読んだ後に議論を始める、というのがよく語られているが、僕が所属するチームでは大概のミーティングでまさにそれをやっている。質の高い文書は上に書いた様にアウトプットが明確で、読み手全員に一定に伝わるので、全員のレベルを短時間で揃えた上で議論を開始できるため非常に効率が良い。手順書の様なものは全員が揃って同時に読む必要はないが、必要なレビュアー達に明確に情報が伝わって的確にレビューしてもらって approve してもらうことが目標になるので、文書として見ると気をつけるべきことは大体同じだ。

僕は Amazon に入る前はあまりこういう形で文書を使ってこなかったけれども、今ではこの手法なしに仕事を進められる気がしない。

文書を書き始める前にすること

文書から得られるアウトプットをまず定める

質の高い文書を書くコツのまず第一であり最も重要なことは、最初にアウトプットを定めることである。つまり、この文書を初めから最後まで読んだ人は一体どんな情報を得られるのか?ということを文書を書く前に決めるのだ。これは Amazon の”working backwards”そのものだ。

“Working backwards” from customer needs can be contrasted with a “skills-forward” approach where existing skills and competencies are used to drive business opportunities. The skills-forward approach says, “We are really good at X. What else can we do with X?” That’s a useful and rewarding business approach. However, if used exclusively, the company employing it will never be driven to develop fresh skills. Eventually the existing skills will become outmoded. Working backwards from customer needs often demands that we acquire new competencies and exercise new muscles, never mind how uncomfortable and awkward-feeling those first steps might be.

Amazon’s 2008 Letter to Shareholders

我々が書く文書の customer は読み手であり、読み手が何を期待しているのか?を最初に定めることで新しい価値を届けられる。技術文書は往々にしてここでいう”skills-forward”になりがちであるが3、そうした文書は読んだ相手には”So what? (だから何?)“となってしまうことが多い。これは読み手にも書き手にも時間の無駄である。そうではなくて、そもそも相手が求めるもの、別の言い方をすればこの文書を読んだ相手に正確に届けなければならない情報、例えば決断に必要十分な情報を最初に定めることができれば、読み手に伝わる情報がブレることもなく、読み終わった後に必要なアクションをすぐに始めることができる。読み手にとっては、必要最小限の時間で最大限の情報が得られることはこれ以上ない価値になる。4

また、最初にアウトプットを正確に定められれば、その時点で文書の 50%以上は完成している。残りのプロセスはそれをサポートするのに必要十分な情報を集め、それを伝わりやすい順番で構築することだが、ゴールはすでにわかっているので無駄な作業をすることなく文書を仕上げることができる。

アウトプットの例としては、「プロジェクトを進めるにあたってチーム 1 とチーム 2 がこういう観点で競合してしまっているが、アプローチ A を取れば目標を達成するのに十分な時間をもって競合を解消できるので A を採用したい。別のアプローチ B は時間がかかりすぎるので今は現実的ではない。」といった感じ。場合によってはそれが自分の中でもはや自明で他の人に伝えるために書き下す時もあるし、そうでなくてこのアウトプットを考えるのに相応の時間がかかるケースもある。いずれにせよ、アウトプットの策定なしに質の高い、読み手に価値のある文書を書き上げるのは難しい。

もちろん、書き進めるうちに最初に決めたアウトプットが変わってしまうこともよくある。自分も、最初は結論 A をサポートするために情報を集め始めたところ、実はもっと良さそうな結論 B が見つかってしまったことはままある。その場合には、一度作業を止めて最初に戻って、そもそもなぜ結論 A だったのか?ということを見直していく。結論 B が正しい場合にはそれをサポートするようにまた文書を練り直すし、時には実は一見良さそうに見えた結論 B には欠陥があることが分かる場合もある。いずれにせよ、文書を作る過程に於いて一貫して「アウトプットがなんなのか?」を問い続けることが最も大切なことである。

アウトプットは課題の定義から始める

具体的なアウトプットは文書毎に当然異なるが、重要な共通点として、そもそもその文書がもたらすものによって一体どんな課題を解消しようとしているのかをまず定めることが重要だ。これは working backward の本質でもあり、この過程で、一見解くべき課題に見えた A が実は根本的には B を解消しないといけないという事実が分かったり、実はそもそも課題なんて存在しなかったということが分かることもある。

正しい課題とは正しい問いかけから始まる。その課題を解くことでお客さんはどういう利益を得られるのか?なぜ他の課題よりこちらが重要なのか?正しい問いを繰り返した先にある課題は本当に解く価値のあるものだし、間違った問いから生まれたありもしない課題というものはとても危険だ。

The most serious mistakes are not being made as a result of wrong answers. The true dangerous thing is asking the wrong question.

-Peter F. Drucker

文章を書きながらすること

読み手を常に想像する

上の章では「読み手」と一括りにしたけれども、実際の読み手は複数存在する。例えば自分のチームメンバーの時もあるし、マネージャ陣の時もある。場合によってはもっと上のレベルかもしれないし、他のチームかもしれない。いずれのケースでも、自分が書いている文書の読み手を正確に把握して、彼らが読んで伝わる様に書く必要がある。

これは読み手の気持ちになって文書を書くと良い。具体的な人物を想像するケースが多いが、あまりそれに縛られ過ぎず、同等の人が読んだ時には誰にでも伝わる様に書いておくと、例えば新しく入った人が読んだ時や、情報共有として当初自分が想定してなかった人へ文書が渡された時にも情報が正しく伝わる可能性が高まる。そのためには、自分にとっては自明と思える様な、「なぜ自分たちのシステム・チームが存在するのか、どういう役割なのか」といったことを最初に書くことが多くなる。一見無駄に思えるけれども、読み手のレベルを本題に入る前に揃えておくことは、その文書から期待する情報を読み取ってもらうためには必要なことになる。5

僕が、この人は文書を書くのが上手だなと思う人は、読み手に応じて同じ内容でも丁寧に書き分けていて、情報の解像度を意図的にコントロールしている。それは想定する読み手に対して必要十分な情報量というのを知っているので、無駄のない最適な量を提示することができるからだ。その意味で、質の高い文書を書くためには読み手をよく知っているということも必要な条件になってくる。なので、新しくチームに入った人がいきなり質の高い文書を書き切るのは難しいかも知れないが、数ヶ月して読み手のことが分かってくると(もちろん合わせて既存の質の高い文書から学ぶと)、格段に質の高い文書が書ける様になるはずだ。

また、そういう人は文書の中で読み手に求める期待値もちゃんと書いている。例えば語彙集みたいな章に対して「もしあなたが〇〇に詳しければ次の章は読み飛ばして構いません」という注釈がついてたり、冒頭に「この文書の想定読者は △△ です」と書いてあったりする。読み手がどのように文書を辿っていくかがきちんと想像できていると、こういう誘導を入れることは自然と行う様になる(必ず入れるべしという意味ではない)。

文書の目的を冒頭に簡潔に書く

文書の冒頭はあらゆる読者が一番最初に目にするところだ。そこに置くべき最も重要な情報は、この文書が一体なんのために存在しているのかを瞬時に判断できることだ。例えば、「この文書の目的は、課題 A に対する解決策の方向性を決定することである。」「この文書は機能 A に関する技術的な詳細を記述したものである。」といった感じだ。具体的な内容はこれから書くので含める必要はないが、この一文があるだけで文書の期待値を大まかにコントロールできる。それによって、例えばこの文書が自分の求めるものではないということが分かった読者は、全体を読み込む時間を浪費せずにすぐに別の文書を探しにいくことが可能になる。文書を読み込む人に対しても、あらかじめ全体感を想像させることができるので、読みやすくなる。

アウトプット(結論)を先に書く

本題を語り始める段階では、まず最初に結論から始めることが多い。提案文書であればそもそも提案が何なのか、変更手順書であれば変更が何でそれがなぜ必要なのか、といった文書を書く前に定めたアウトプットそのものに近しいものを最初に提示することで、その後の文書を読むに当たって、読み手に著者は結局どうしたいのか、を最初から意識させることができる。

これはよく日本語話者が英作文をしていると言われることだが、日本語話者の文書は(言語の性質や文化の性質上)往々にして結論を一番最後に書きがちだ。その構成自体は僕も嫌いではないし(ずっと日本語文化圏で育ったので)、読んでいく中でのワクワク感や最後の答え合わせは気持ちよい時もある。ただ、技術文書を読む時間を効率的に使うためには、結論が先にあった方が読み進めた後での驚きが少なくて済む。もしも結論が最後にしかないと、そこに至るまでの道に少しでも破綻があれば、頭に疑問符を抱えまくったまま読み進めないといけない。一方で最初に結論が分かっていると、その後の情報に多少のアラがあっても大意は外さずに読み進められるし、抜けている部分はフィードバックとして伝えやすい。

これも、読者のレベルを揃えてから先に進めるというモチベーションからきている。こうすることで、文書を読んだ後に議論をする際にも、細かいアラは後回しにして、与えられた情報でそろえた土台から結論そのものを真っ先に議論することができる。

文書によっては、要素の説明無しに結論を記述するのが難しいこともある。そういった場合には先にいくつかの事実や提案内容を書いた文書もよく目にする。ただ、自分はそれでもなんとか簡潔に結論をまとめて先出しする方が読みやすいと考えているし、その過程で論理のアラを見つけられたりもする。エレベーターピッチじゃないけど、短く説明できないものは、そもそも何か大事なものが欠けている可能性もあるのだ。

具体的な数値を文章で説明する

技術文書には多くの場合何かしらの数値について語ることになる。例えば、API のレイテンシを改善する話だったり、ジョブの実行時間を短くする話だったり。その際に具体的な数値を出して説明することが、読み手によりクリアなイメージを持ってもらうために重要なことになる。例えば「レイテンシがとても速くなります」ではなくて「p99 のレイテンシが 100 ms から 10ms になります」といった具合だ。「速くなる」のイメージは読み手によってブレるが、具体的な数値で書いてあればあるほどブレがなくなる。6

その際にもう一つ注意したいのが、単に図表を貼って終わりとしないことだ。読み手はあくまでも自然言語を頭から順番に読んでいる(パラグラフリーディングも含めて)ので、示したい情報抜きに図表だけが存在していると、読み込みが途切れてしまって図表を読み解く必要がでてくるし、繰り返しになるがその図表から読み取れる情報にバラツキがでてしまう。図表はもちろん効果的なので活用すべきだが、文書としては図表がなくても通じる様に、そこから読み取って欲しい情報をズバリ自然言語でも書いておくことが、正確に情報を伝えるためには必要だ。忙しい人に正確に情報を伝えたい時ほど、メトリクスをバーンと見せる行為よりも文章で伝えたい内容を書いた方が良い。図表およびその出典をリンクしておけば、その数値を再検証したい人は辿って確認していくこともできる。

箇条書きを濫用しない

箇条書きは短文で済むので文書を速く仕上げることができる一方で、行間を読むことを読み手に強制する。例えば、インデントの意味や、項目の順番の意味、実は 2 つの項目がつながって一つのことを書いている、などなど。これは何度も繰り返すが読み手によって得られる情報がブレてしまいがちだ。効果的なポイント以外では無闇に使わず、文章で伝えたい内容をハッキリと書いた方が良い。

細部にまで目を配る

質の低い文書、つまりアウトプットが不透明な文書は往々にしてその見た目も汚かったり、細部が雑だったりする。よくあるのが、似た様な過去の文書からコピペしてきたものの修正が不十分でコピペ元の情報が残っていたり、参照してあるリンクが壊れていたり、typo があったり、といった様なことだ。そんなの些細なことに思えるかも知れないが、読み手はあなたの文書を論理的に理解しようとしているのであり、こういったノイズは論理的思考の妨げになる。文書を書き上げたら、細部にエラーがないかを確認してから公開するのはエチケットだ。7

文書を読んだ後の議論をスムーズにするために

選択肢は可能な限り網羅する

技術文書では、ある技術の選択を提案するケースが多い。例えば、ある機能を実装するのに〇〇というアルゴリズムを利用するとか、本番環境に変更を加える際に △△ という手順で行う、といった内容だ。この時に、自分がオススメする選択肢 Aだけに対して長々と説明を行なっても、読み手の「なぜ B ではなく A なのか?」という問いに全く答えることができない。また、もし A と B を並べて比較した説明をしたとしても、明らかに検討すべき C が抜けてしまっていると、同じ様に「なぜ C を検討しないのか?」という疑問が残ったままになってしまう。

これは結構ハマりがちな罠で、書いている自分にとっては A が最高なのでそれで行きたいという思いが強くなってしまって、A の良さと注意点の説明ばかりしてしまいたくなる。だが、読み手が知りたいのは「なぜ A なのか?」という情報だ。それを正しくサポートするには、A そのものの説明だけではなく、その他にとりうる選択肢についての情報を提示してあげることが必須になる。そうでないと、A が最適 or 最善な選択なのかどうか判断がつけられない。

比較の方法はケースバイケースだが、一貫した項目で全選択肢を網羅することが多い。よくある比較表ができあがるイメージだが、図表の章で述べた様に、比較表は補助として比較のメインは自然言語で行った方が正確に伝えられる。

比較項目としては、その選択が One-way door なのか Two-way door なのか(一度進んだら戻れないのか、それとも戻ってやり直せるのか)は重要な要素になることが多い。なぜなら One-way door な決断を下す際は非常に慎重になる必要があるからだ。

また、選択肢の網羅性も疑問の余地を少なくするためには重要だ。例えば過去に同じ課題に対して取られた・検討された選択肢というのは含めておくべきだ。いわゆる MECE (Mutually Exclusive, Collectively Exhaustive)にできると良いが、あまりそこを完璧にすることに時間を使いすぎる必要はない、なぜならほとんどの選択肢は明らかに棄却されるケースが多いからだ。

ただ、この網羅性を上げるのは結構面白くて、当初 A がいいと思って選択肢 B,C を並べてて、最後の選択肢として突拍子もないというかそんな選択肢もあるのか、みたいなものを入れてみたところ、予想に反していい感じの選択肢になってしまったことがある。また、今回採用しなかった B や C についても文書の中で検討した内容は、数ヶ月後や数年後に同じ様な問題に当たったときにも役に立つ可能性があるので、決して無駄にはならない。

自分の意見を表明する

上とは逆のパターンでハマりがちなのが、網羅的に選択肢は並べたものの、結局どれを選択すべきなのかが明示されてない文書だ。何かを前に進めるための文書であれば、単に選択肢を並べただけでは何も起こらない。自分ならどれを選択するのか(条件付きでも構わない)を明示しておかないと、その後の議論の進行が成り行き任せになってしまう。

決断を下したいのであれば、1 つの選択肢を第一候補として、何も異論がなければそのまま、そうでなければ理由を添えて別の選択肢へ、という進行にした方が合意を取りやすい。Amazon には Have Backbone; Disagree and Commit. という行動指針があって、後者のケースでは自分としては選択肢 A がいいと思うとしっかり提案したが、議論の結果選択肢 B に合意したのであれば、以降は選択肢 B に commit していく、といった形の行動になっていく。なので自分の提案が棄却されたからといってその文書が無駄になることはなく、決断の過程の非常に重要なパートを占めている。

長くなりすぎない

文書が全体が長すぎると、そもそもミーティングの時間内(議論の時間を除く)に読みきれない。現場の技術者が日々扱うレベルだと、15-20 分程度で読み切れるボリュームが理想的だ。文書というのは書き込めば書き込む程正確さを増すのでどうしても細かく書きたくなってしまうが、真に詳細な部分はコードレビューや変更手順レビューで確認していけばよいはずだ(実際コードを書いてみて初めて分かることというのももちろん多い)。質の高い技術文書はこの解像度のコントロールが適切で、かつ場合によって様々な別の文書にハイパーリンクしていくことで、足りない情報を必要に応じて補える様にしている。細かすぎるが書き留めておきたい情報は、Appendix という形で本体とは別で添付しておくのも一つのやり方。

変更手順書の様な文書は、手順の部分はもちろん詳細に記述することになるけれども、それ以前の概要の部分には同じ原則が適応できて、無駄を削ぎ落として必要十分な情報(なぜこの変更が必要なのか?等)が伝わる様にまとめあげる必要がある。

まとめ

長々と書いてきたけど、結局僕が重要だと考えるのはこれ:

  • 文書から得られるアウトプットが明確で、読み手のレベルによらず一定に伝わること

Footnotes

  1. 大学は半端に卒業、大学院は何もせずに退学している https://blog.riywo.com/2009/02/27/120733/

  2. と僕は考えるけど、そうじゃないという意見はもちろんあって構わない。

  3. 例えば「技術 A はとても優れているのでこれを採用します」という文書は、なんで A は優れてるの?A を使うと何が得られるの?A じゃない B はどうなの?といった疑問を読み手に残す。

  4. 時間とは最も貴重な資源であるのでそれを浪費しないことはとても重要な価値

  5. チーム内限定の文書であっても実は個人によって認識が少しずつずれていることもあるので、やはり前提を揃えるという意味でも、100%自明でないことは簡単にでも自分の理解を記述しておくことには大いに意味がある。

  6. この例でもまだ、p99 の計測範囲が 1 分間なのか 1 時間なのかといった情報が削ぎ落とされているが、伝えたい情報としては十分なケースはある。

  7. エラーをゼロにしてから出せという意味ではないが、可能な限り少なくする努力を払った方が良い。