Googleに学ぶドキュメントの作法

# はじめに

これはGoogle流のドキュメント、特にソースコード内に記載されるコメントの書き方、また、考え方についての記事です。
それが最適であるかは抜きにして、純粋な意味でGoogleの取り組みを知ってみたいと思います。


この記事は[Googleのソフトウェアエンジニアリング](https://www.oreilly.co.jp/books/9784873119656/) および [Documentation Best Practices](https://github.com/google/styleguide/blob/gh-pages/docguide/best_practices.md) を参考にしています。



# Googleにおけるドキュメント

## エンジニアにとってのドキュメント

多くの場合、エンジニアにとってドキュメント作成は<strong>つまらないもの</strong>と見なされているが、それには以下のような理由がある。

- 恩恵を受けるのは読み手であり、書き手ではない
- 文章を書くことをプログラミングとは別のスキルと見なしている
- ドキュメントそのものは、ソースコードとは別の新たな保守すべき重荷であり、ソースコードそのものに対して何らプラスの影響を与えない


しかし、よくできたドキュメントは書き手であるエンジニアに対して以下のような恩恵を与える

- 設計および実装の再検討の機会を与える。簡潔に説明できない場合は設計不足を指摘されているのかもしれない
- いかなる場合もコード内で凝ったことをするべきではないが、もし書いてしまった場合にはデバッグの助けになる
- コード自体の質を良く見せる

## ドキュメントをどのように扱うべきか

ドキュメントはコードと密結合しているケースがしばしばある。
そのため、ドキュメント、それ自体も<strong>コードのように</strong>扱われるべきである。
端的に、ドキュメントとは以下のようであるべきだ。

- 従うべきポリシー、ルールがある
- ソースコントロール支配下に置かれている
- 保守責任のあるオーナーがいる
- 変更についてレビューを経る
- アプリケーションのバグのように、問題が追跡される
- 定期的に評価、テストされる
- 正確さ、鮮度の両面から計測される

逆に、wikiスタイルのドキュメントは以下のような理由からアンチパターンである

- 明確なオーナがいないため、管理されなくなる
- 修正を行う者と利用する者の完全な二極化が進んでしまう
- モノリシックで階層化が難しい
- 内容の重複、コンフリクトが容易に発生する


## ドキュメントのレビューフロー

コードのようにドキュメントを扱うとは、コードと同じようにレビューフローを経るべきである、ということである。
これはレビュアーがレビュイーのコードの変更意図をくみ取りやすくするという効果もある。
ただし、コードレビューとドキュメントレビューには違いもある。

それは<strong>最適を求めない</strong>、ということである。

それがドキュメントであっても、レビュアーはレビュイーに対して改善を求めることができるし、そうあるべきだが、
一般に、ドキュメントの場合は<strong>"完璧であること"</strong>よりも<strong>"十分よいこと"</strong>であることのほうが優先される。
ドキュメントにおいては完璧に書くことより、小さな改善を素早く反映できることのほうがずっと価値がある。


## 良きドキュメントであるために

### 対象の読者を認識すること

<strong>読み手は書き手ではない。</strong>
そのため、対象の読者を想定し、もしくは限定することが良きドキュメントを書くためには必要だ。
読者は、その言語、ドメインに精通した熟練プログラマかもしれないし、新米のジュニアエンジニアかもしれない。
目的も様々で、インターフェイスを知りたい利用者もいればバグ修正をしなければならない開発者もいるだろう。

<strong>そういった全ての読者に最適な共通のドキュメントは存在しない</strong>

しかし、よりよくあることはできる。
それは短く書くことだ。

短く書くためには、長いドキュメントを作成し、それを編集する工程が入る。
この工程がドキュメントをより良いものにしてくれる。


### 書かれるべき目的を理解すること

ドキュメントは常に、<strong>読まれるために</strong>書かれる。
そのため、読み手がどんな情報を欲しているのか、が何をどのように書くべきなのか、の端的な答えになる。

ドキュメントには以下のような類型がある。
- リファレンスドキュメンテーション(コードのコメントもここに含まれる)
- デザインドキュメント
- チュートリアル
- 概念的ドキュメンテーション
- ランディングページ


本記事では、基本的にリファレンスドキュメンテーションを扱うが、それ以外のドキュメントについても簡単に触れておく。

#### リファレンスドキュメンテーション

ここでは、コードベース内でコードについて記したコメントを意味する。
一般に、コードの使い方を説明するAPIコメントと、実装の子細を解説する実装コメントの二つに分かれる。

#### デザインドキュメント

簡単に言えば、提案段階の設計書である。
設計上のトレードオフと決定、考慮事項等が含まれる。

#### チュートリアル

チームに新規参加したエンジニアが最初に行うべきことを記載したテキスト。


#### 概念的ドキュメンテーション

アプリケーション、もしくは、プロジェクト全体を俯瞰して見るためのドキュメント。
あるデータのライフサイクル等はここに記載される。

#### ランディングページ

チームの個々の情報へのリンク集

### リファレンスドキュメンテーションの作法

前述の通り、リファレンスドキュメンテーションは以下の二つに分類でき、それぞれの想定される読者と提供するべき情報がある
- APIコメント
 何ができるのか、引数の要件は何か、戻り値は何か、どんなエラーが起こり得るのか、など、あくまで実用的な内容のみが必要で、実装や設計上のトレードオフ、内部処理の子細については必要ないし、書くべきではない

- 実装コメント
 読者はある程度のドメイン知識を有しているということを想定したうえで、コード理解の助けになる内容

また、以下に記述するコメントには共通するルールがある。
それは、ごく一部の例外を除いて、<strong>コメントを書くことがデフォルトである</strong>、ということである。

#### ファイルコメント

Googleではごく一部の例外を除いてコードファイルの先頭にコメントを記載しなければいけない。
コメントは、そのファイルの概要とどのような方針で実装されたのかの内容を含んでいる必要がある。
特に、概要は1~2行程度で簡潔に書かれるべきで、もし、長くなるようなら設計不足である。

```typescript
/**
 * このファイルには体長の測定や鳴き声の採集など、Animal型およびそれを継承する型に対する
 * ユーティリティメソッドが含まれる。
 * Animal型を継承する個別の型特有のメソッドを含まないことで、Animal型に対する一般性を担保できるように設計した
 **/ 
```

#### クラスコメント

Googleでは全ての公開クラスは、そのクラス自体、そのクラスの重要なメソッド、そのクラスの目的を含んだクラスコメントを記載しなければならない。

```typescript
/**
 * MarsupialクラスはKangarooクラスやKoalaクラスの基底クラスであり、
 * 主要なメソッドであるgetHabitat()はデフォルトで"Oceania"を返す。
 **/
```

#### 関数コメント

Googleでは例外なく、クラスの公開メソッド、もしくは自由関数が<strong>何を行うのか</strong>を簡潔に説明するコメントを記載しなければならない。
このコメントは、関数が行うことと戻り値を端的に表した動詞で始まることが望ましい。(英語表記では)
これは、<strong>今読んでいる関数が読者の探しているものではない</strong>、という情報を真っ先に提供するためでもある。
一貫性のあるテキストは素早く走り読みして、必要としている情報へアクセスすることを可能にしてくれる。

```typescript
/**
 * 与えられた動物の生息地域を返す。
 **/
function getHabitat(animal: Animal) {
```

### 良きドキュメントであり続けるために

古いコードが問題を引き起こすように、古いドキュメントも問題を起こす可能性がある。
また、そもそも、全ての読者に誂えのドキュメントが無いように、改善のできないドキュメントもない。
ドキュメントは盆栽に似ている。こまめに枝をうつことで、鮮度は保たれ、長期的により良いものとなってゆく。
このために、Googleではそのドキュメントの最終レビュー日を記録することがしばしばある。


# 実際にGoogleのコードコメントを読んでみよう

[Code Search](https://cs.opensource.google/)では、Googleのオープンソースプロジェクトを横断して、コードの検索および閲覧ができ
気になった方はリンクへ