「プロダクトとしてのドキュメント」を目指してドキュメンテーションへの考え方をアンラーンする

この記事は、「株式会社エス・エム・エス Advent Calendar 2023」3日目の記事です。

qiita.com


介護事業者向け経営支援サービス「カイポケ」の開発をしている @koma_koma_d です。

私が所属しているチームは、介護事業所の業務のなかの一部の領域を扱う箇所の開発を担当しています。最近、このチームの置かれている状況に変化があり、それに伴って(他にも様々な変化が必要になっているのですが)ドキュメンテーションについての方針転換がありました。この方針転換は、私個人にとってもこれまでの働き方を一部改めるきっかけになるものでしたので、今回の記事では、その方針転換について紹介したいと思います。

これまでのチームの状況

私たちのチームが担当している領域のシステムは、大雑把にいうと、ユーザーが触るアプリケーション(サーバーサイドレンダリングをベースとする典型的なWebアプリケーション)と、その更に裏側で動作するバックエンドのアプリケーション(WEB API+非同期処理を担うワーカー)の2つの部分に分かれています*1

私たちのチームが担当する業務は、カイポケの他のコンポーネントで作られたデータを入力とするのですが、基本的にはこれらの2つのコンポーネントで完結します。したがって、カイポケの他のチームのメンバーは私たちのチームの担当する業務ドメインについての知識をほとんど持つ必要がなく、ユーザーから見える仕様もこれら2つのコンポーネント間のAPIの仕様もほぼ自由に変更することができました(もちろん仕様を変える際は対ユーザーのコミュニケーションは不可欠ですが)。この自由度を活かして、新しい機能を追加したり、そのために内部API仕様を変更したりを活発に行なってきました。

カイポケリニューアルプロジェクトの進行に伴う状況の変化

しかし、ここ数ヶ月の間で、状況が変わってきました(予定通りではあるのですが)。それは以前から動いているカイポケのリニューアルプロジェクトの進行に伴うものです。

careers.bm-sms.co.jp

このリニューアルプロジェクトでは、既存システムとは別の新システムを開発しており、私たちのチームが担当する業務ドメインについても、別のチームが開発をしています。しかし、先述の2つのコンポーネントのうち、後者のバックエンドのアプリケーションについては、既存システムと新システムとが共用します。リニューアルプロジェクト側では、ユーザーが触るWebアプリケーション*2だけを新規開発し、そのアプリケーションから私たちのチームのシステムのWeb APIを利用するわけです。

この状況の変化により、これまで私たちのチームだけが知っていれば良かった知識の一部を、他チーム(リニューアル側の開発チーム)にも知ってもらう必要が出てきました。その中には、業務ドメインに関する知識と、内部APIの仕様の知識の両方が含まれます。このことが、ドキュメンテーションの方針に変化を強いることになります。

これまでのドキュメンテーションの考え方

基本はチーム内向けのドキュメント

私のチームでは、ドキュメンテーションツールとしてesaを主に利用しています。esaはMarkdownで書くことのできるツールで、個々の記事がバージョン管理されるほか、フロー情報とストック情報を分ける機能などがあります。esa以外には、ソースコードに近い情報はGitHubリポジトリ上のコメントやREADMEなどで記述しているほか、内部APIの仕様についてはOpenAPI Specification(コードから自動生成しています)から作成したドキュメント*3があります。

このうち、内部APIの仕様についてはチーム外の人が見ることを意識していましたが、esaに書かれるドキュメントについては基本的にチーム内の人(未来の自分たちを含む)が読むことを想定して書いてきました。もちろん仕事をしている中で別のチーム(開発チーム以外を含む)に向けて情報共有をすることはありましたが、そのときに適切な情報が伝わればよいケースがほとんどで、メンテナンスされるようなドキュメントとして書いていなかったり、必要が生じたタイミングで書くという形で書いていたため網羅性の乏しいものになっていました。

読み手としてチーム内の人を想定する場合の考え方

読み手としてチーム内の人を想定する場合、ドキュメントを書く際に意識することは少なくて済みます。まず、チーム内の人であれば、コードを読むことで得られる情報など、既に関連する部分の知識を持っていることを前提としてドキュメントを書くことができます。コードを読んだ方が正確に・詳細に把握できる事項についてはドキュメントを書かないでおく選択を取ることもできます。

また、(新規参画したメンバーは別ですが)過去の経緯がある程度頭に入っていることも期待できるので、ある時点で書かれたフロー情報的なドキュメントを見たときにそれが書かれた文脈を想像してもらいやすいですし、必要に応じてgitの履歴やGitHubのPull Requestの履歴とも紐付けて読んでもらいやすくもあります。

このような背景から、ドキュメンテーションに対する考え方は、(チームとして明確に意識していたわけではありませんが) 「多少読みづらくてもよいので、とにかくたくさん情報を残しておく」 という方に寄っていたように思います。また、私個人の経験としても、チーム開発におけるドキュメンテーションの最初の壁は「共有されてもいい情報がドキュメンテーションツール上に書かれない」ことだと感じていたので、「書くハードルを下げる」「些細なことでもとにかく書いておく」ということを重んじてきました。個人で何か作業をしたときや調査をしたときも気軽にドキュメンテーションツールに書いておくことで、他のメンバーや将来の自分の参考になる情報をなるべく増やすという考え方ですね。現在のチームの前に所属していたチームでは、この考え方に基づいたプラクティスが上手くワークしていたこともありました。以下の記事で紹介している「転ばぬ先の杖」がそれです。

tech.bm-sms.co.jp

「書き手の書きやすさ重視」のアプローチ

このアプローチは、「書き手の書きやすさ重視」のアプローチということもできます。もちろんドキュメンテーションはそもそも読み手のためのものなので、書き手の書きやすさを重視することも究極的には読み手のためではあるのですが、読み手にとっての利便性のうち、情報量を増やすことにフォーカスしており、「簡単に情報にアクセスできる」「わかりやすく情報がまとまっている」という部分は犠牲にしている側面があります。読み手は検索やリンク(esaにはバックリンクを表示する機能もあります)の機能を駆使してドキュメントを「漁る」ことで、必要な情報を得ることになります。

生じてきた課題

しかし、先述の状況の変化により、課題が出てきました。

チーム外向けのドキュメントだけでは足りない

まず第一に、従来からチーム外向けを意図して書いていたドキュメントでは、全く情報が足りないということを本格的にリニューアル側の開発が始まってから痛感しました。これは見立てが甘かったと言ってしまえばそれに尽きるのですが、どう想定と違ったかを少し紹介したいと思います。事前のイメージは「Web APIのクライアントとなるリニューアル側の開発チームは、OpenAPI Specificationベースのドキュメントと、それを補足するようなドキュメントがあれば開発できるだろう」というものでした。しかし実際に開発が始まってみると、私が想定した以上に細かく、実装に近い仕様や業務ドメインに関する知識を質問されることが多かったのです。

内部APIのモジュールとしての性格

こうなってしまった理由を考えてみますと、私たちの開発している内部APIのモジュールとしての性質に思い至ります。私たちのチームで開発していた内部Web APIは、情報の隠蔽を志向しているというよりは、クライアントであるユーザー向けのWebアプリケーションで求められるユースケースを最大限実現できるようにすることの方を優先して作られていました。

もちろん、内部APIとして切り出す意味がある程度の複雑な機能をAPIの裏側に持っている(データベースやオブジェクトストレージ、KVS、非同期処理を実現するためのメッセージキューなども独自で持っています)のですが、非同期処理の過程のステータスの遷移などの情報はあまり隠蔽せず、APIで露出させることでクライアント側で画面に表示したり制御に利用したりできるようにしています。『A Philosophy of Software Design』における表現を使えば、「機能は多いが、インタフェースも多い(複雑な)」、DeepともShallowともいえないモジュールだということです。『A Philosophy of Software Design』については、以前個人ブログの方に書いた記事や、NTTコミュニケーションズ社のブログ記事も参考にしてください。

ky-yk-d.hatenablog.com

engineers.ntt.com

チーム外の人も、API仕様以上の知識に関心がある

このようなモジュールとしての性質から、クライアントの開発者はこの内部APIを使って開発をする際に、かなり多くの知識にそもそもOpenAPI Specificationベースでドキュメント化されているAPI仕様の段階で触れることになります。その上で、そこに露出している知識を最大限に理解した上で実装をしようとすると、OpenAPI Specificationでは書ききれていない情報、ほぼ実装の詳細に関わるような内容や、背後にある詳細な業務知識までも知りたくなってしまうようでした(そもそも私たちのチームではそこも把握した上でユーザーの触るWebアプリケーションを実装しているわけです)。

チーム内向けとして書かれていたドキュメントをチーム外の人が読む

チーム外に向けて書いていたドキュメントだけでは足りないとなると、他チームのメンバーとしては個別に私たちに質問するか、私たちがチーム内向けに書いたドキュメントを読むかして情報を得ようとします。私たちのチームとしてもリニューアルプロジェクト側の開発が滞りなく進むように支援することの優先順位は高く設定しているので、もちろん質問してもらっても大いに構わないのですが、すぐに応答できないこともありますし、双方にとって効率的でないこともしばしばです。したがって、やはりドキュメントで完結する部分を増やすことは重要になります。

チーム外の人にはチーム内向けのドキュメントは理解しづらい

それでは、チーム内向けとして書かれていたドキュメントをチーム外の人が読もうとすると、どんな困りごとが出てくるのでしょうか。第一に、ドキュメントを読むだけでは理解できないということがあります。これは先述したような、チーム内であれば期待できる前提知識や、コードを読むことによって得ることのできる情報を、チーム外の人は持っていないからです。もちろん他チームであっても開発者ではあるので「コードを読んでください」と言えば読んでもらうことは可能なのですが、私たちのチームとリニューアルプロジェクト側のチームとでは技術スタックがやや異なっていることもあり、あまりここに頼りたくはありません。

チーム外の人にはドキュメントに書かれている情報の鮮度を判断しづらい

また、チーム内向けのドキュメントではフロー情報としてある時点での情報を書いたものをそのまま残してあるものも多いのですが、チーム外の人は私たちのチームやそのシステムの過去の経緯までは知らないことが多いので、あるドキュメントを見たときにそれがup-to-dateなものかの判断が付きづらく、誤った(out-of-dateな)認識を持たせてしまう危険性があります。

チーム外の人は必要なドキュメントに辿り着きづらい

更に、そもそも必要なドキュメントに辿り着けないという問題もあります。先述の通り、「書き手の書きやすさ重視」のアプローチでは、読み手の利便性のうち、「欲しい情報への辿り着きやすさ」は犠牲になっており、検索やリンクを駆使してもらう必要があります。

チーム内であれば自分たちがどういう言葉を使っているかが分かりますし、何かを調べようと思ったときにどのようなキーワードで検索したら見つかりそうかの候補もすぐに思いつきます。「あの記事からリンクされていた気がする」というのも覚えているかもしれません。しかし、これはチーム外の人には期待すべくもないことです。もちろん最小限の語彙はOpenAPI SpecificationベースのAPi仕様という形で見えるようになっており、そこで接した用語について関心を持って調べ始めるわけなので、全く白地からというわけではありませんが、やはり「欲しい情報へ辿り着く能力」には差が出てしまいます。

※ちなみに、将来的には現状の全文検索やリンクに加えてAIによる要約やチャット形式での検索が発展して、現在よりは必要な情報に辿り着きやすくなるのではないかと妄想しますが、その場合でもデータソースを書き捨ての文章のみで構成するのはなかなか厳しい気がします。

これからのドキュメンテーションの考え方

以上のような課題から、私たちのチームではドキュメンテーションの考え方を改めることにしました。具体的には以下のような方針を定めました。

チーム内向けとチーム外向けを分けない

これまで、ドキュメントはデフォルトがチーム内向けで、例外的にチーム外向けを書くという形になっていましたが、この分け方自体をやめることにしました。チーム外の人でも読めるものに最初からしましょう、ということです。実際には、チーム内のメンバーしか読まないドキュメント(たとえば、運用上の手順書など)も出てくると思いますが、その場合でも暗黙の前提知識を要求するような形では書かないということを原則としようとしています。

ドキュメントを小分けにせず、なるべく大きなまとまりにする

これまでは「場所に悩んだりして書かないよりは、とにかく書いておくことを優先する」という方針で、仕事をしている過程で小さなドキュメントをたくさん書いてきました。しかし、このアプローチでは、一度書かれたあとに更新されないドキュメントが増えがちです。更新されないドキュメントが存在することは、読み手、特に過去の経緯まで把握していないチーム外の読み手にとっては大きなノイズとなります。

新しい方針では、なるべく大きなまとまりの文書をメンテナンス対象とし、加筆・修正していくことにしています。あるテーマについてはこの文書だけが信頼できる唯一の情報源(Single Source of Truth)であるという状態を作ることです。

こうしておくことで、まず第一に、欲しい情報に辿り着きやすくなります。また、これはチーム内で話をしている中でメンバーから言われて「なるほど!」となった点なのですが、読まれる頻度の高いドキュメントは更新されるチャンスも多くなるということもあります。ドキュメントが更新されるタイミングとしては、何か変更が入った際に「あのドキュメントも更新しなきゃなー」と更新されるのがベストですが、更新を忘れてしまうことは実際には多いです。しかし、日頃から繰り返し開くことの多いドキュメントであれば、「あ、ここ情報が古いじゃん」と気づく機会が増えます。もちろん、ドキュメントが大きくなればその中の一部の記述だけを目当てにしてそれを開くことも増えると思いますが、それでもその部分以外の記述も併せて目に触れることはある程度あり、更新のきっかけになると思います。

フロー情報を書いたものはドキュメントとして扱わない

上の内容とも関連しますが、フロー情報として書いたものをドキュメントとして扱わないようにしようと考えています。

これまではフロー情報を書いたものもドキュメントの一部として扱い、「読まれる」ことを期待していました。しかし、この考え方はともすると「本来ストック情報として書かれるべきものがフロー情報として書かれっぱなしになってしまう」という事態を招きやすいと感じます。「フロー情報を残しただけでドキュメントを書いたつもりになる」のをやめなければなりません。そのためには 「フロー情報を書いたものはドキュメントではない」 というくらいの意識が必要だと思います。有益な情報として残すべきだと考えたなら、その情報が書かれるべきドキュメントを探して、メンテナンスするものとして記述します(もちろん、もはや必要でないと判断した場合には「メンテナンス」の一部として削除することもあるでしょう)。

インデックスとなる記事からリンクだけで必要な情報に辿り着けるようにする。

これはドキュメントへの辿り着きやすさの改善のための方針です。これまではドキュメントを新しく作成するとき、「どのようなタイトルにするか・どのような文言を入れておくか」という検索でのアクセスのしやすさの観点と、「どのディレクトリ*4に入れておこうか」という階層構造を使ったアクセスのしやすさの観点を意識することはありましたが、他の記事との関係でいうと、関連する記事同士をリンクで結びつけることによるネットワーク構造の作成くらいまでしか意識してきませんでした。

今回、新しく各グループ(ex. 仕様に関するドキュメント群)ごとにインデックス(ルート)となる記事を設定し、そこから明示的なリンクを辿ることで必要な情報を見つけられるようにしようということになりました。先述の通り、検索頼みにするのはチーム外の人にとっては利便性が特に低いですし、「検索や階層構造で見つけてくれる」というのに甘えると自分たちがその文書に辿り着くのも意識的にアクセスしたときに限られやすくなるため、書きっぱなしで更新されないドキュメントになりがちです。特定の記事からリンクだけで辿り着けるようにしておくことで、チーム外の人からアクセスしやすくなると同時に、更新されやすいようになることを狙っています。

終わりに

以上、私たちのチームにおけるドキュメンテーションの方針の転換について、その背景と併せてご紹介してきました。この方針で動き始めたのは最近なので、実際にどうなったか(うまくいっているのか・いないのか)はまだご紹介できる段階にありません。ドキュメントをメンテナンスしていくのはそもそも簡単ではなく、だからこそ従来の方針のような「書き手の書きやすさ」を重視するという方針にも意味がある(最初から読み手の利便性を100%満たすドキュメントを書けるのであれば苦労はしない)わけですから、今回立てた方針を適切に実行できるかどうかも不透明です。

しかし、社内向けとはいえチーム外にAPIを提供するチームとしては、ドキュメントをプロダクトの一部として捉え、コードと同じくらい大切にする必要があります。ソフトウェア自体に不具合がなくても、ドキュメントが不足していたり誤解を招くものであったりした場合、使い方を間違えることでシステム全体としては正しく動作しなくなってしまうこともあるわけです。「ドキュメントをプロダクトとして扱う」という考え方は『エンジニアのためのドキュメントライティング』でも語られています。

pub.jmam.co.jp

また、私個人としては、これまで他の開発者にクライアントとして使ってもらうソフトウェアをメンテナンスする経験がほとんどなかったので、これまでに形成してきた自分自身のドキュメンテーションに対する考え方をアンラーンする必要を感じています。今回のチームとしての方針の転換をいいきっかけとして、プロダクトの一部としてのドキュメントに真剣に向き合っていきたいと考えています。


「株式会社エス・エム・エス Advent Calendar 2023」、明日4日目は、@soranakkの記事を予定しています!

*1:なぜこのような構成になっているかは割愛します。

*2:厳密には、リニューアルプロジェクトではフロントエンドとバックエンドがGraphQLのAPIで通信するアーキテクチャとなっているため「ユーザーが触るWebアプリケーション」はフロントエンドだけなのですが、ここでは簡略化のためバックエンドの部分も含めて「ユーザーが触るWebアプリケーション」と記載しています。

*3:当初はSwagger UI、現在はRedocを利用しています。

*4:esaでは、ディレクトリ構造を作って記事を整理することができます。個々のディレクトリに相当する部分のことを「カテゴリ」と呼びます。