エンジニアの太田です。

皆さん、デザインドックはご存知でしょうか?いわゆる設計書ですが、エンジニアによって書かれ、書いた本人またはチームによって実装される点と、技術的な詳細を明確にし技術的な議論をすることにフォーカスがある点が特徴です。他人に開発を依頼するための設計書や、既存のシステムを解説するための文章とは性質が異なります。

デザインドックを書くことの利点としては以下のような点があります。

  • 開発を始める前に全体のシステムを考察する機会を得る
  • 文章化することで、曖昧な部分が明確になる
  • 早い段階でチームメイトや専門家、関係者からフィードバックを得る機会を得る
  • システムの設計について明確な承認を得られる
  • 新しいメンバーがシステムの概略を理解する手助けになる

弊社でもすでに多くのデザインドックを利用しており、エンジニア間での議論の活発化を担っています。

具体的にどのような内容を書けばいいのでしょうか?今回は私の考えるデザインドックについて解説します。せっかくのアドベントカレンダーですから、デザインドックの形式で「デザインドック」を解説することに挑戦してみます!

Design Doc of Design Doc

Hiroyuki Ota
Last update: 2018/12/19
Status:Draft

Goal

デザインドックを導入することで、新しいシステム・機能の設計に関する技術的な議論を円滑にし、開発の早い段階でのフィードバックを容易にする。また複雑な機能を設計する際、ドキュメントの形で明確化することで曖昧な部分、考慮が十分でない部分をなくす。

Non Goals

  • 完璧な設計書の作成
    • デザインドックで書かれたシステムは、デザインドックを書いた本人またはチームによって実装されるため、概略に注力し、議論の必要のない詳細は省き、実装の詳細はコードレビューなどで議論する。
  • 要件定義
    • 簡単な要件ならばデザインドックでも定義できるが、要件が変更されるとそもそもシステム全体のデザインを変更する必要があるため、要件定義はデザインドックが書かれる前にある程度固まっている必要がある。

Background

ある機能やシステムをデザインする際、同じ機能を実現するのでも様々な方法があり、エンジニアは常に選択を行いながら開発を行っている。しかしたとえ短期的に同じ機能が実践できる設計でも、長期的に見た場合、拡張性(Extensibility)や安定性(Reliability)、スケーラビリティ(Scalability)、保守性(Maintenancebility)などが大きくことなり、いずれかの問題の結果システムを再構築することもある。

Google で使われていることで有名になったデザインドックは、エンジニアによって書かれる設計書であり、書いた本人またはチームによって実装されると、技術的な詳細を明確にし技術的な議論をすることにフォーカスがある点に特徴がある。

Overview

デザインドックは大まかに以下の章によって構成される

  • Goal:デザインされるシステムの目的
  • Background:前提になる知識や参考になるページ、専門用語の定義。
  • Overview:概要とシステムの構成など。
  • Detailed Design:設計詳細。
  • Caveats / Security Concerns / Privacy Concerns:プライバシーやセキュリティーなどの注意点

デザインドックを書くプロセスはチームによって様々だが、概ね次のようになっている:まず最初にドラフトとしてGoal や Overview などを埋めたあと、数人に共有し最初のフィードバックをもらう。さらに詳細を埋めたあと必要であれば関係者やチーム内レビューを行い、承認が得られれば開発に移る。開発によってデザインドックが書かれている内容と実装が次第に乖離してくるのを防ぐため、定期的にアップデートすることでメンテナンスする。

Detailed Design

構成

デザインドックの各章立てについて解説する。

  • Goal
    • Non Goals
  • Background
  • Overview
  • Detailed Design
    • Sub sections
    • Caveats / Security Concerns / Privacy Concerns
    • Alternatives Considered

Goal

1~3文程度の短い段落で、デザインされるシステムの目的を述べる。要件を定義するとき、後述するPRDが存在すればリンクを張り、存在しなければ専用の章を設ける。

Goal が間違って広く捉えられると、議論が範囲外を超えてしまい、毎回軌道修正する必要がある。そんなとき Non Goals として議論やシステムの目的範囲を狭め、明確にすることで、無駄な議論を省くことができる。

Background

前提になる知識や参考になるページをリストする。中で使う専門用語や略語も定義して、意味を明確にしておく。

デザインドックはシステム全体の議論を行うため、さまざまな人からフィードバックをもらう必要がある。たとえばフロントエンドとバックエンドの両方に改修が必要な機能の場合、両方のチームからレビューしてほしいが、それぞれのチームは自分のチーム外については詳しくない。そのような場合でも、関係者が全体を読んで理解できるように情報を補足するためにも、Backgroundは重要である。

Overview

概要や目的を3,4段落で説明する。システムが複数のコンポーネントからなる場合、概略図を書くと読者の理解が容易になる。

Detailed Design

詳細設計。必要に応じて数ページ程度に収めるのが理想である。章立てをきちんと行い、読者が必要な情報にたどり着けるようにすることが重要。あまりに長くなる場合は小さい機能を別のデザインドックとして独立させ、議論を分けることで読者の負担も減る。

Alternatives Considered

考慮されたが選ばれなかった設計をその利点・欠点も含めて書いておくことは、見逃されがちであるが重要である。

Caveats / Security Concerns / Privacy Concerns

Caveats にはシステムの注意点などを書く。セキュリティーやプライバシーの懸念に関しては、専用の章を設けることで、議論を明確化し、ローンチの前に必ず解決する。

その他

APIのデザインなどの、例があるとわかりやすいが Detailed Design に含めるには長すぎる場合は Example の章をAppendix としてつけると全体が読みやすくなる。

テストのプロセスが重要である場合は Test Plan の章を含めることで、どのようにテストされるか議論することが可能になる。

ツール

デザインドックを書くツールは、章立てされた文章が残せて、フィードバックが受け取れるツールならば何でも良い。

Google Docs

最もメジャーなツールは Google Docs であり、レビューの際はフィードバックをコメントの形でもらうことになる。利点としては以下の点が挙げられる。

  • コメントのハードルが低い
  • エンジニアに限らずだれでもコメントを受け付けられる
  • 共有範囲を自由に変更できる
  • 同時編集可能
  • 図の挿入が容易

欠点としては以下の点がある。

  • 変更履歴が見づらい
  • URLを知っていないと探しづらく、golink を使うなどの工夫が必要

GitHub + Markdown

Markdown 形式等のプレインテキストで書き GitHub 等のバージョン管理&レビューシステムを使ってフィードバックを貰う方法もある。利点としては以下の点が挙げられる。

  • 履歴が見やすい。それぞれの行をいつだれが変更したか追跡可能
  • シンタックスハイライト
  • コードと同時にレビューが可能
  • コードと同じレポジトリーで管理することで、見つけやすい

欠点としては以下の点がある。

  • エンジニア以外がコメントするハードルが高い
  • PRがないとコメントがつけられず、しかも変更した行に限られる。
  • 図を書くとき、コードで書くか画像をアップロードする必要がある

いつ書くべきか

デザインドックをいつ書くべきかについては明確な基準は無い。

  • 同僚・チームメイトのフィードバックが必要
  • チームメイトがそのシステムの開発に後から加わるとき、コードを読むだけでは十分な理解できない、もしくは時間がかかりすぎてしまう
  • デザインに複数の選択肢があり、後日自分が見返したときに現在のデザインを選んだ理由がわからなくなりそう

などの条件を1つでも満たした場合、デザインドックを書くことをおすすめする。

プロセス

デザインドックを書くプロセスはシステムやチームによって様々だが、概ね以下のようなステップを経る。

1. ドラフト

とりあえず最初のドラフトを書く。Goal と Overview、特に議論したい Detailed Design の章を書いてしまえば十分である。まだ書いてない章は TODO コメントを残しておくと、「まだ書いていない」のか「書くつもりがない」のかわかって読者に優しい。

2. 最初のフィードバック

チームメイトやメンターなどに共有し、フィードバックに基づいて更新していく。特に Google Docs や GitHub PR のコメントは本文には表示されないこともあるので、できるだけ同じフィードバック・質問が来ないように本文に反映させていく。たとえば読者が目的を外れた点について聞いてきたら、Non Goals をアップデートしたり、背景についての質問があれば Background に追記する。

3. 関係者レビュー・チームレビュー

開発がチーム内で完結するような簡潔なデザインドックであれば、このステップは飛ばす。

必要があれば関係者やより広いチームに共有する。デザインドック文化が根づいていれば、自分の範囲外でも有用なフィードバックを送ってくれるデザインドックのプロのような人がいるので、その人のことは覚えておいて、別のデザインドックを書いたときも直接その人に送ると、より自分のデザインドック力が高まる。

4. 開発

必要な人からのレビューを大方受けたあとは実装に移る。この際にデザインの時点では見逃していた点、想定外の課題に相対することはよくあることであり、その都度デザインドックをアップデートし、必要ならレビューを頼む。

5. メンテナンス

システムが改修され続けるたびに、デザインドックが更新されるのが理想だが、実際は放置されることも多い。デザインドックは実装されたあともシステムをざっくりと理解するために役立つため、チームに新しい人が来たタイミングでアップデートしたり、大きくシステムが変わる際には新しいデザインドックを書くのが望ましい。

Caveats

デザインドックのスタイルは一つではない

このデザインドックでは著者の経験に基づく、効率的なデザインドックの書き方について述べたが、エンジニアによってそれぞれデザインドックの書き方は異なっており、正解は一つではない。自分に合ったやり方を模索することが重要である。

すべての文章をデザインドックの形式で書く必要はない

例えばこの文章は「デザインドックを広めるための文章」であるが、議論よりも情報の伝達に重きが置かれるべきであり、デザインドックのフォーマットは必ずしも適さない。この文章をデザインドックとして書いている理由は単純に「デザインドックのデザインドック」というメタ的な面白さを追求した試みのためである。

最新の情報を反映していない

デザインドックはデザインを議論し、明確な間違いを避けたり、設計者自身が曖昧になっている点を明確にするためのもので、メンテナンスに重きを置かれていない。読者が疑問に思ったときにや間違いを見つけたときにアップデートする必要がある。

デザインドックに時間を書けすぎない

「完璧な」デザインドックを書こうと時間を使いすぎてしまうことは、「早い段階でフィードバックをもらい議論すること」を目的としたデザインドックの目的から逸脱している。できるだけ早い段階でレビューしてもらい、実装しなければわからない点があれば早めに実装に移るのも手である。

Alternatives

技術的な内容に関して文章を書くとき、デザインドックが適切なフォーマットであるとは限らない。

PRD

PRD(Product Requirements Document, 製品要求仕様書)は、製品が満たすべき仕様をまとめたものである。一般的にPRDはエンジニアがシステムをデザインドックで設計するに(少なくとも同時に)書かれるべきものである。デザインドックを書いたつもりが、製品についてばかり議論されるとき、必要なのはデザインドックではなく PRD である。

コードレビュー

APIの細かな定義や動作、使うアルゴリズムやその実装などは、実際に作り出すまでわからないことが多く、すべてを事前に決めることは不可能である。そのような技術的詳細は、実際に実装したあとコードレビューを行うほうが建設的で具体的な議論ができる。

Design Proposal

システムが「デザインドック」と呼ぶにはあまりにもシンプルだが、フィードバックを得たいとき、Detailed Design 以下の章を除いたデザインプロポーザルというフォーマットを準備しておくと、気軽にフィードバックを受けられる

Privacy Concerns

N/A

Security Concerns

N/A

Appendix: Example “Design Doc of Design Doc”

Design Doc of Design Doc

Hiroyuki Ota
Last update: 2018/12/19
Status:Draft

Goal

デザインドックを導入することで、新しいシステム・機能の設計に関する技術的な議論を円滑にし、開発の早い段階でのフィードバックを容易にする。……