非同期コミュニケーションにおけるドキュメント

VOYAGE MARKETINGの @katzchum です。

自分が携わったプロジェクトで、以下の2点を課題として、プロジェクトの進め方について検討しました。

  • プロジェクト立ち上げの流動的な場面でもリモートのメンバーに対しても如何に早く共通理解を促進させることが出来るか?
  • 開発のインプットとして、どうドキュメントを位置づけてチームへの情報の伝達手段として用いるか?

検討した結果、以下の取組を行ないました。

  • ドキュメントをDSLでコード化
  • DSLのレビューを通じて情報共有&ディスカッション
  • デッドコード化させない取組(短期・長期ドキュメント)

取組のプロセスとして軽量だったわりには良い体験や気付きが得られた様に思い、プロジェクトの背景・初期の悩みから、どうアプローチして取り組んで行ったのか、振り返りも交えてお話したいと思います。

ドキュメントの悩み

新規のプロジェクト立ち上げ時にドキュメントどうすんの?と聞かれると悩みますよね。

プロジェクトのスタートは大抵、以下のようになるかと思います。

  • プロダクトとして何をどうしたいのか?の青写真を作成
  • プロダクトオーナーと開発者との間で、青写真の図解を眺めてプロジェクトの進め方の検討やタスクのブレークをする
  • キックオフMTGを開催して青写真をベースにプロジェクトの概要を共有する

以降、青写真を起点に様々なコミュニケーションがされていきます。

ドメイン知識を持ち合わせた一箇所に固定化されたチームであれば、青写真をホワイトボードに書き殴ってディスカッションするなどできますが

  • プロジェクト自体がスモールスタート
  • 段階的にメンバーが増える(メンバーが固定化されない)
  • ドメイン知識が形成されていない(不確実性も高く・情報が全て出揃っていない)
  • リモート開発も組み入れる

上記の制約や要素が組み合わさると直接会話だけのコミュニケーションだけでは成り立ちません。
体制も含めてプロジェクトの成熟度が低い状況下ではそれなりの数のドキュメントの作成が必要となります。 ドキュメントがない若しくは適切に管理・共有されていないと、悩み事や困りごとが増えてきます。

  • 人が増えるたびに繰り返し説明するコストが嵩む
    毎回同じ図を書いて説明するのはめんどくさい
  • プロジェクトが進んでいく中で図も少しづつ変化していく
    何がどう変わったのか?どういう議論があってそうなっていったのか?
    ホワイトボードで書いた図に対してdiscussionが行われて出てきた指摘をどうやってリモートのメンバーに共有していくのか?
  • そもそもリモートのメンバーにホワイトボード使って説明ができない
    ホワイトボードの写真をとって共有したりもするけれども、結構情報が欠落するしミスリードもしやすい
    図の書き方は人それぞれだったりするし、複雑な構成だと言葉で補う必要がある
  • リモートメンバーにも図のレビューや疑問を挙げてもらいたいけど難しい
    書いた図に対して具体的にピンポイントでここ!というのを文章で指し示すのは大変です
    図に赤書きしたものをやりとりするのも、最新の図がどんどん変わっていくなかではもっと大変です
  • 共通の言葉が定まってないとやりづらい
    プロジェクトの初期では抽象的な概念がまだ言語化されていないので、非同期なコミュニケーションでは正確性を欠きます
    プロジェクトメンバーがそれぞれ同じ様な図だけど微妙にバラバラものを書いて、違うキーワードで説明されるケースが出てきそうです

またプロジェクトの立ち上げ当初では

  • 抽象的な概念が言語化されきたら、それを元の図解とのマッピングが出来るか?

というのも重要かと思います。
最初はふわふわっとした内容をイメージ化するのは雰囲気で出来ます。
そのアウトプットされたイメージを通してコミュニケーションすることでだんだん事柄や概念が言語化されていきます。
最初から全てを言語化するのは難しく、図を使って説明を補い共通理解を促進させるのが図解のメリットとなります。
図解は共通理解されている言語とセットで扱うことで価値が出てきます。
あくまでも図は補足説明の為のアウトプットであって、それ自体で全てを表現できるわけではありません。
エンジニアも非エンジニアも同じ言葉(ユビキタス言語)を使って今後やり取りしていくことになります。
逆にここら辺が出来ないとコミュニケーションが迷子になってしまいます。

以下の2点を課題として、プロジェクトの進め方について検討しました。

  • プロジェクト立ち上げの流動的な場面でもリモートのメンバーに対しても如何に早く共通理解を促進させることが出来るか?
  • 開発のインプットとして、どうドキュメントを位置づけてチームへの情報の伝達手段として用いるか?

検討した結果、冒頭で説明した以下の取組を行ないました。

  • ドキュメントをDSLでコード化
  • DSLのレビューを通じて情報共有&ディスカッション
  • デッドコード化させない取組(短期・長期ドキュメント)

非同期コミュニケーションにおけるドキュメントのやりとり

ドキュメントをDSLでコード化

なぜDSLなのか?どうしてコード化する必要があったのか?まず理由を説明したいと思います。

まずDSLですが、

  • 統一した表記内容にすることができる
  • コードとして取り扱うことができる

がメリットとしてあります。
フリーフォーマットでドキュメントを書くことは表現力に幅がありますが書き手のセンスが問われます。
表記内容に統一性がないので、読解力を求められたり違った解釈をされる可能性があります。
文字や表だけで表現するには冗長的になりすぎる場合は図解したい時も、フリーフォーマットでは書き方や扱うツールも千差万別です。

次にコード化する目的としての主眼は

  • Github上でレビューを可能にする

です。 通常のプログラムのコードと同様にドキュメントもGitHub上でのレビュー対象にします。
ここで言う所のドキュメントとは開発のインプットとなるもので

  • 各種UMLが扱うダイアグラム(図解)
  • データモデリングの叩き
  • 画面ラフ
  • 連携I/F(API、ファイル)の叩き etc..

などを組み合わせして他の文章(主にIssue)を補足する為のものになります。
図などはどんなツール(なんならホワイトボードでも)でも書けますが、その多くが独自フォーマットのバイナリでGithub上のレビューではうまく扱えません。これらの図や表をDSLを用いてコード(テキスト)化することでレビューを可能にします。
また対面レビューでなくてもリモートのメンバーも含めて大勢の人たちにレビューされてコメントがログとして残るようになります。

又、コード化の副次的なメリットとして以下があります。

  • 再利用が可能になる 説明をする度に毎回ホワイトボードに書く手間を省くことができる
    再現性もあり、編集・加工(コピペで一部分のみ変更とか)も楽
  • 複数ドキュメント間の関連が想像しやすい 記述するDSLが異なっても、同じ語句を用いることで複数のドキュメントに関連の意味づけをすることが出来ます
    コンテキストが異なる複数の独立した図で、イメージ上で例えば○と□とで違う表現方法がされたとしても同じ語句を使っていれば同じものとして認識できる
  • 変更の履歴をトレースできる バージョン管理の対象にすることで、履歴を追うことができる
    図解であったとしても、どの部分が修正されたか?又、コミットログなどでIssueと紐付けることでなぜ変更されたか?がわかる
  • ピンポイントでの引用・参照ができる 特にレビューの際に有効で、紙に印刷して赤書きを入れなくてもピンポイントで行又はブロック単位での指摘ができる
  • 情報の分断がなくなる コードと同様に扱うことによって情報が分散せずに済む
    一箇所に情報が集約されるので検索もしやすくなる(テキスト化されているので中身も検索対象となる)

どういうDSLを用いたか?

これから私が実際にプロジェクトで利用したいくつかDSLの紹介をしたいと思いますが、実際にどう書くのか?というのはここでは説明しません。
取り扱うDSLの記法が多数存在するので、ここで紹介するより、リンク先のドキュメントを見て頂いたほうが早いのでそちらを参考にしてみてください。

PlantUML

plantuml.com 各種UMLのダイアグラムを扱う際に利用しています
一通りのUMLをDSLで直感的に記載できます
UML以外の図も簡単な画面ラフ(ワイヤーフレーム)も扱うことができます

GraphQL

http://facebook.github.io/graphql/October2016/facebook.github.io データモデリングの叩きを作成する際に、ざっくりした型の定義(type)を行ない、データ取得のパターンの洗い出し(Query)とデータの操作のパターンの洗い出し(Mutation)を雰囲気で書きます
実装は行ないません。あくまでも雰囲気です
GraphQL自体はただのクエリ言語ですのでシステムを外部から見た際のデータにフォーカスしたインターフェース(振る舞い)をゆるく言語化する際に利用します
UMLのクラス図でも同じ目的で扱うことは出来ますが、内部実装までフォーカスしてしまうのでより抽象度の高いGrapQLを用います

OpenAPI(Swagger) Specification

swagger.io 最終的なAPI仕様書として記述させることもできます
連携I/Fの叩きとして先に作成します。レスポンス例も記載できるので、振る舞いのイメージを伝えるのにも便利です

CSV Schema

digital-preservation.github.io CSVやTSVのファイルフォーマットの仕様書を扱うことができます

DSLのレビューを通じて情報共有&ディスカッション

DSLで作成したドキュメントはGithub上でPRを作成してレビューを行ないます。
これらを作成・レビューする意図としては以下になります。

  • お互いの認識の共通理解の促進と確認
  • 開発のインプットとしての質を向上させる

文字だけで説明するのではなくDSLで書いた図等で補足するのですが、説明する側される側のどちらがDSLを書いても良いです。
作成されたDSLをレビューすることで、イメージどおりであればお互いの認識がとれて先に進められます。
逆に既に共通認識が取れていて文章のみ(多くはIssueのコメント)で伝わっている(疑問がない)のであれば、DSLを書いて補完させる必要はありません。
ただDSLでコード化するメリットで記載した同じ語句を用いる手法を取り入れて敢えてDSLで書き起こすというのもあります。
こうすることで例えばコード内で使うクラス名とDSLないの語句がマッチングでき、内部設計のレビューにもなります。

文章のみの説明だけでは伝わりづらいので、PlantUMLのDSLを使った例で説明したいと思います。
養殖な例題となってしまいますが、挨拶をするというユースケースがありそれを実装する場合で説明します。

”自分から相手に対して挨拶をする” という要件だった時にどの様に解釈しますでしょうか?
一番単純に書くとすると以下のようになります。

gist.github.com

f:id:katzumi:20180516194754p:plain

わたしとあなたがいて”こんにちは”というメッセージを渡しているだけですが、要件の文字を書き起こしただけでお絵かきしたに過ぎません。
これではメリットがありません。DSLなのでドメインを意識してコードをリファクタリングしてみます。

gist.github.com

f:id:katzumi:20180516194801p:plain

まず、わたしとあなたというのがアクターとして定義されました。
Author as “わたし” としているのが、利用する語句をあわせる意味があります。
他のドキュメント内でもAuthorという語句があったらこちらの図と同じ意味となります。
コンテキストが違って筆者と別名をつけていても同じものと理解できます。
単純に わたし としていたものが実装する際のAuthorというアクター。。Authorクラスが必要になるのかな?とか想像できる様になります。
アクターとしての概念が言語化されて明示されたことになります。このコードを見た人によっては”サンプルだからってブログを見ている人との関係性だったの?Personの方がもっと汎用的でいいんじゃない?”とツッコミを入れたくなると思います。
そういうフィードバックを貰うことで、お互いの共通認識の確認になり、ディスカッションもされることで開発のインプットとしての質も向上します。

デッドコード化させない取組(短期・長期ドキュメント)

ドキュメントはGithub上で管理されることになりコードと同じ様にチーム内で共同所有されます。
実際、ドキュメントはDSLで書かれたテキストなので、ソースコードを検索している際に関連するドキュメントも結果に含まれることになります*1のでよりソースコードと同列という意識で扱われます。
その共同所有しているという意識の中でチーム内で自然発生的に2つのルール的なものが出来てきました。

  • 短期なものは定期的にクリーニングする
  • 残す文章については参照がしやすいように改善する

作成したドキュメントを短期的なものと長期的になものに分けて、それぞれがデッドコード(DSLがプロジェクト的に参照されない状態)にならない様な取組となりました。

短期的なものでは、WIPのPR上でディスカッションのみに利用してmergeせずに捨てたりしました。
最初はプロジェクトの進行と共にコードと併せてドキュメントをブラッシュアップさせていた物が、開発が安定してきてコードも変更が少なく関連するドキュメントの参照・更新が少なくなったものは役割が終えたとして削除PRを作成して消しました。
ドキュメントの生成(merge)と破棄のプロセス自体がPRを通して行われます。

長期的なドキュメントについては、それぞれのドキュメントが独立して存在して初見者にはどうやって読み進めたら良いか分かりづらいので各DSLをAsciidoc内に埋め込んでインデックス化させました。
Asciidoc自体はマークダウンで書くことができPlantUML、Github形式のMarkdownやソースコード(コードハイライト対応)を埋め込むことができ、目次(Table of Contents)までつけれます。
AsciidocはGithub上でそのまま表示することが出来ますが基本的な表現のみしかサポートされていません。
UML等の図の埋め込みが展開されないのとAsciidoc独自の表現が反映されないのでPDF化して参照出来るようにしました。
PDF化すると大変綺麗に出力(仕様大全っぽく)できるのですが、出力するのが手間(環境構築も含め)なのでJenkinsで定期的に自動生成するようにしました。

取り組んだ結果どうだったのか?

まず個人的な感想となりますが、主にDSLを書く側だったのではあるのですがいくつかまとめると

  • オープンなフォーマット且つ軽量だったので書く安心感があった
    誰が書いてもほぼ均一な表現になるし読める(平準化される)
    言語の読み方についての説明は不要だった
    いつでも捨てられる安心感
  • ストックが溜まっていく感じが良かった(語彙力が増す)
    同じ様な図がコピペで使い回しができる
    変更点を説明するのに、前の図が使えて差分がわかる
    使い続けるとどんどんすらすら書けるようになる
  • イメージを文章化、更にコードとマッピングするフローがうまくつなげれた気がする
    表現が難しいのですが、頭の中を整理する道具として思考のフローとマッチした感がありました
    抽象的な概念(イメージ)の中から共通理解できる言語に落とし込むイメージです

    • 初期の思考フロー
      f:id:katzumi:20180516193624p:plain
    • 実装時の思考フロー
      f:id:katzumi:20180516193631p:plain

DSLが中間言語的な振る舞いをして開発からみるとより理解しやすい言語で語られる様になったかなと思います

  • 同じ表現(文章)が複数出現した時に正規化・共通化の気づきを得られた
  • 図だけで全て表現・説明しようとする悪いクセが直った
    作成した図を使って説明する時に、わかりやすいように吹き出しをいっぱい付ける癖がありました
    DSL自体はシンプルに書き、説明をPRのレビューコメントで残す様にしました
    そうすることで図がごちゃごちゃせずに、わかりやすくメンテナンスしやすいものに出来ました
    副次的な効果で、コメントに積極的にレビュー観点を残せるようになり、フィードバックを得やすくなりました
    設計上の不安も共有することで、図だけ見てもふ~んで済まされない感じにはもっていけました。
  • DSLとコードに乖離があると良い意味で気持ち悪さを感じるようになった
    作成したDSLをインプットにコーディングを進めて乖離がでてくるケースはまあ普通にあります
    その際にコードのレビューとセットでDSLの修正も併せて行うと、あーこうしたのね!とレビューする側の理解が早いです
    特にある程度のボリュームの新規機能で設計や実装に不安がある時にDSLがあると、初見のコードから実装時の思いを紐解くよりも共通理解されている言語で修正した内容と目的がわかる(コミットログなどから)とお互いに納得感が得られて進めます
    初期の理解で作成したDSLに対してコーディングを進めてより理解が進んだ状態で見直すと、もっとこうしたら良かったのでは?という気付きが得られるケースもありました

他のメンバーからのフィードバックとその考察をまとめると

  • 図は簡単に書けたが、UML自体の書き方が難しかった
    雰囲気でUMLは書けますが、ちゃんと理解して伝わるように書くのには苦労していました
    ただ初期だけで一度出来上がったものに対して変更を行うのは問題なく出来ていました
  • 画面ラフの共有はさくさくできてよかった
    モデルと画面項目のマッピングや項目位置など、基本的な要件を伝えるのはそれほど手間にもならず手戻りも少なくできた
    ラフから実際の画面(bootstrap)を作成するのは別途UIのガイドラインがないと辛い
  • ドキュメントの更新を忘れる
    プロジェクトの初期でドキュメントの扱いPRのフローが定まっていなかった為、どうしても更新が漏れるケースがありました
    メンバーには完全に同期しなくても良い旨を共有していましたが、次の改修もありそうなものはなるべくDSLの修正を行うように依頼をしました
    ここら辺はドキュメントを作りすぎない、短期的なものと長期的なものを分けてうまく扱う様に布教していくしかない様に思います
  • ユースケース・ステートマシンを書く時にレイアウトが大変
    自動で良しなに配置してくれるけど、迷子にならないように配置しようとするとコツがいる
  • 情報が一箇所に集約されGithubだけに集中できる
    リモートからだと他のツールやリポジトリを参照する際にVPNが必要なケースが多かったのですが、それが不要になったのが大きいです
    ローカルにcheckoutして参照できるので、ネットワークがつながらない時に作業中断しなくてすみました

総評すると取組のプロセスとして軽量だったわりには良い体験や気付きが得られた様に思います。
最初はドキュメントをツールやフォーマットの側面からの困りごとを改善したいとの思いからスタートでしたが、振り返ってみると非同期なコミュニケーションで情報のロスを少なく・逆に密にする為に手法とそれにマッチするフォーマットとをそれぞれ変える必要があったのだと思いました。

*1:前述のソースコードとDSLとで同じ語句を用いて意図的にそうなることを目指しています