テストとコードレビューの目的


自チームのテストとコードレビューのルールを決めるにあたって、その目的をまず明確にして共有すべきだと判断し、ドキュメントを書いてみました。

# 概要
本ドキュメントはテスト＆コードレビューの目的を共有するためのドキュメントである。

- 何故テストとコードレビューが必要なのか？
- どんなテストとコードレビューを目指せばいいのか？

といった、テストとコードレビューの全体方針を記す。

# 目次
- [前提](http://qiita.com/necojackarc/items/0efa125ce1ea90e739f0#%E5%89%8D%E6%8F%90)
- [テストの目的](http://qiita.com/necojackarc/items/0efa125ce1ea90e739f0#%E3%83%86%E3%82%B9%E3%83%88%E3%81%AE%E7%9B%AE%E7%9A%84)
- [コードレビューの目的](http://qiita.com/necojackarc/items/0efa125ce1ea90e739f0#%E3%82%B3%E3%83%BC%E3%83%89%E3%83%AC%E3%83%93%E3%83%A5%E3%83%BC%E3%81%AE%E7%9B%AE%E7%9A%84)
- [まとめ](http://qiita.com/necojackarc/items/0efa125ce1ea90e739f0#%E3%81%BE%E3%81%A8%E3%82%81)
- [FAQ](http://qiita.com/necojackarc/items/0efa125ce1ea90e739f0#faq)

# 前提
プログラムの作成や改良時にはおおまかに以下の情報が必要となる。

- 要件・ユーザーストーリー
- システムの振る舞い・外部インターフェース設計設計
- 各コンポーネントの振る舞い・内部アーキテクチャ設計
- プログラム・ソースコード

## ドキュメント化すべきこと
何を実現したいのか？それがどこに書いてあるのか？といった情報はメタ情報であるため、ソースコードに落とし込むことは難しい。

そのため、以下に関してはドキュメント化すべきである。

- 実現したいことは何か（要件・ユーザーストーリー）
- どのシステムがどう関連しているか（システム全体図）

## ソースから読み取れること
各コンポーネントの振る舞いや、それぞれの設計などについては、テストコードおよびソースコードから読み解くことができる。

- システムの振る舞い・外部インターフェース設計設計（テストコード）
- 各コンポーネントの振る舞い・内部アーキテクチャ設計（ソースコード・テストコード）
- プログラム・実装（ソースコード）

すなわち、要件・ユーザーストーリーをどのように実現しているのかといった情報は、ソースコードおよびテストコードから読み取れるようにしておくことが望ましい。

# テストの目的
- 長期視点から見たソフトウェア品質の向上
    - テスト自体は品質向上のためでなく品質測定のために行う
    - ソフトウェアの継続的改善にはテストは必須
    - ソフトウェアはリファクタリングによって品質が向上する
- 要件・ユーザーストーリーを満たしていることの確認
    - テストでストーリーを再現することで要件漏れが見つかりやすくなる
    - その振る舞いを満たすための外部設計や詳細設計を理解しやすくなる

## テストがないと起きること
- ソフトウェア品質の低下
    - 継続的改善（リファクタリング）が困難になる
    - プログラミング言語やフレームワークのバージョンアップが困難になる
        - プログラムの要件に変更が生じなくても、外部要因（バージョンアップ） により、プログラムの変更は将来的には必ず訪れる
        - そのアプリケーションは変わらないかも知れないが、外部ライブラリやOSなどの刷新により、インターフェースが古くなると、使っているプログラミング言語やフレームワークのバージョンをあげざるを得なくなる
        - 結果、ソースコードの改修が必要になる
        - 改修後の動作確認時、テストがなければ手作業で全て確認することになり非常に苦しい
- 要件・ユーザーストーリーを満たしているかの確認がマニュアルになってしまい、確認に対するコストが増加することになる
    - マニュアルでの動作確認は、人間の不安定な精確さの上に成り立つことになる
        - 要件漏れが発生する確率があがる
- そのプログラムに求められる仕様や振る舞いを読み取ることが困難になる

### 格言
- ***唯一生き残るのは、変化できる者である - ダーウィン -***
- ***変化こそ唯一の永遠 - 岡倉天心 -***

一言で言うと、テストがあることで変化可能なシステムに近づくことが可能になる。

## テストがなくて起きたこと
- エンバグの発生
    - バグフィックスが新たなバグを生む完全なる悪循環
- エンジニアの退職などにより、作成者がいなくなってしまうと仕様を知ることが困難になる（コードレビューでも同様の問題が起こる）
    - 誰も触れないソースができあがり、サービスの改良どころではなくなる
    - 不具合が不具合を産む状況になり、事業としての成長もとまる可能性が高い

*この項目では実際に過去に起きたことや具体例を書いて、テストが必要だという実感を持ってもらおうと思っています。*

# コードレビューの目的
「何を実現したいか（仕様）」に対し「どう実現しているか（コード）」をレビューするのを基本の考え方とする。

- ソフトウェア品質の向上および属人性の排除
    - 技術的負債となり得るコードがないかを確認する
- スキルの向上及びナレッジの共有
    - 担当者の実装レベルの把握と向上（教育的観点）
    - 他人のコードを読むことによって学びや発見を得る
    - 開発者同士のコミュニケーションの活発化

## ソフトウェア品質の向上と属人性の排除
ソースコードある意味ドキュメントでもあるため、「他人が理解できる」必要がある。
それを実現するためには、他人の目線を取り入れることが最もシンプルかつ効果的である。
他人が読めないソースコードとは、ただの負債である。

また、ソースコードは基本的に「変更に耐え得る設計」である必要があるため、適切な設計になっているかどうかの確認も同時に行うべきである。

### レビューの観点
技術的負債となり得るコードがないかをレビューでは確認する必要がある。

- 属人性が高すぎるコード（何をやってるか他人がわからない）がないか
- 設計（クラス設計、モジュール分割、メソッド抽出 etc ... ）は適切かどうか
- クラス名、メソッド名、変数名  etc ... がわかりやすいかどうか

## スキルの向上及びナレッジの共有
言うまでもなく、良いレビューはスキルの向上に効果的である。かつ、他人のコード（特に自分よりもスキルが高い人のコード）を読むことはそれ自体が勉強になる。
また、実装について議論をすることで、ナレッジの共有や互いの成長を促すことができる。
チーム内で互いから学び合うことにより、チーム全体のレベルの向上が促進される。

## コードレビューをしないと起きること
- 書いた本人すら理解するのが困難なソースコードが生み出される
- チーム全体のレベルの向上速度が遅くなる

### 具体例
- エンジニアの退職などにより、作成者がいなくなってしまうと仕様を知ることが困難になる（テストでも同様の問題がおきる）
    - 誰も触れないソースができあがり、サービスの改良どころではなくなる
    - 不具合が不具合を産む状況になり、事業としての成長もとまる可能性が高い

# まとめ
テストとコードレビューを簡潔にまとめると以下の通りである。

- ソフトウェア品質の向上（変化に対応できるシステムを作る）
- 属人性の排除（誰もがソースコードから情報読み取れるようにする）

これらを満足させれるように、テストとコードレビューを実施していくことが重要である。

# FAQ
- 仕様がわからないためコードレビューができないときはどうするの？ 
- 誰もが理解できるってことは一番レベルが低い人に合わせるの？

## 仕様がわからないためコードレビューができないときはどうするの？ 
- ここで指している仕様とはなんのことでしょう？
    - ビジネス要件・ユーザーストーリー
        - ドキュメント・プルリクエストの説明を見ましょう
    - プログラムの振る舞いや設計
       - テストやソースコードで表現されているはずなので、それを見ましょう
    - どちらを見てもわからない、つまり他人が理解困難（属人性が高いのか情報が足りていない）ということなので、コードレビューの依頼者にその旨を伝えましょう
    - しかし、残念ながら現状、とんでもないコードは存在するので、その時は頑張るか有識者に質問しまくりましょう

## 誰もが理解できるってことは一番レベルが低い人に合わせるの？
- 良い設計を目指しましょうという意味です
- 良い設計、良いイディオムなどは積極的に共有し、そちらを使いましょう
- 判断に困る技法や設計の場合、周りの人に聞いて、できるだけ多くの人の視点を入れましょう
- あまりに黒魔術的だと判断されたら、それは直したほうが良いと思います

# おすすめの読み物
- [コードレビューのベストプラクティス](http://postd.cc/code-review-best-practices/)
- [Code Review Best Practices](http://kevinlondon.com/2015/05/05/code-review-best-practices.html)

---

以上です！

目的はもっともっと沢山あると思いますが、重要だと感じているところについて、自分はこう理解している、こう考えている、というのを文字に起こしてみました。

ここはこうしたほうが良い、これはおかしい、ここは何言ってるかわからないなど、気になる点がありましたらコメントいただけると嬉しいです。

最後までお読み下さりありがとうございました。