たのしくなるコードレビュー

こんにちは!サービス開発部でAndroidアプリの開発をしているこまたつ(@k0matatsu)です。

みなさんコードレビューしていますか?
最近ではとりいれているチームも多いと思いますが、良い効果をもたらしてくれる一方で、負荷の高い作業でもあります。
また、コードレビュー自体に馴染みの薄かった人はなにをどうしたらいいのか難しいですよね。
同僚から得たアドバイスと自分なりのノウハウをあわせて、コードレビューの指針を考えていたので公開してみようと思います。

前提として、クックパッドではGitHub Enterpriseとプルリクエストを使った開発プロセスを採用しています。
また、コードレビューの前には自動テストと静的解析ツールによる単純なフォーマット、コードスタイル、頻出バグのチェックは行われているものとします。
静的解析による機械的なチェックはコードレビューよりも低コストで有効な方法ですので是非取り入れてみてください。

コードレビューの目的

なにをやるかの前に、なぜやるかをハッキリさせておくことはとても大事です。
目的を明確にしておくことで、判断が必要になった際に指標になります。

コードレビューの目的は会社やチーム、レビュアーとレビュイーの関係性などによって様々ですが、私は次の二軸に比重を置いています。

  • 品質向上
  • スキルアップ

品質向上

プログラムを書いているのは人間なので、ミスが発生します。
コンパイラや静的解析をすり抜けて来るものもありますし、全体の設計に沿っているかなど、人間でなくては確認が難しい要素もあります。
コードレビューを行うことで、複数人の違う視点が入るため、ミスを検出し「読みにくい」などの感覚的な部分のフィードバックも得ることができます。
ここで言う品質とは、バグの量ではなく、可読性やメンテナンスのしやすさも含めたソースコード全体の品質をさします。

スキルアップ

コードレビューの中で疑問を解決したりアドバイスを得ることで自分自身が知り得なかった情報を得ることができます。
自分のスキルに不安があっても、疑問を感じた部分を積極的に質問していくことで多くの学びが得られます。
一方的な査読ではなく、双方向コミュニケーションの場と捉えることでレビュアーとレビュイー双方のスキルアップが期待できます。

何に注意するべきか

チェックすべき項目は多岐に渡りますが、次のような部分を重点的に確認します。
ここであげる項目の他に、ドメイン知識など他の開発者よりも詳しい分野があれば、その知見を使ってフィードバックを行います。

  • アーキテクチャ・設計
  • 挙動
  • 改善

それぞれどのようなチェックを行うか、掘りさげて見ていきましょう。

アーキテクチャ・設計

目的に沿った設計がされているか、全体のアーキテクチャに沿った設計になっているかを確認します。
具体的には次のようなところを重点的に確認しています。

  • 単一責任原則: ひとつのメソッドに違う目的の処理を入れない
  • 命名: 一連の処理の中で統一されているか
  • 粒度: プルリクエストを分割した方がいい部分はあるか

また仕様に疑問を感じた場合も、コードレビューと一緒にその仕様で問題ないか確認してもらいます。

挙動

主に準正常系を見ていきます。
Androidの場合はとくに次の場合に予期せぬ挙動をすることが多いので注意しています。

  • バックキーが押されたとき
  • バックグラウンドから戻ったとき
  • 画面回転をしたとき

改善

より良い書き方があれば指摘します。
AndroidではSDKにTextUtilsやDateUtils、Uri.Builderなどの便利クラスが存在します。
この手のクラスは存在自体が知られてない場合もあるため、積極的にオススメしていきましょう。
標準ライブラリ以外にも、チーム内で運用している便利クラスやメソッドは新しいメンバーは知らないことが多いです。

手順

ここまで、コードレビューの内容部分をみてきました。
次はどのような手順でレビューを行っているかを記します。
人によってやりやすい方法は様々ですが、参考になれば幸いです。

  1. 内容を把握する

    • どのような目的で書かれたコードなのか、主な変更点などをdescriptionを読んで確認します
    • 必要な情報が足りなければ追加をお願いすることもあります
  2. 軽いチェックを行う

    • typoや粒度、明らかな間違いなど、ブラウザから差分を見ただけですぐに判断できる問題が無いか確認します
    • この時点でたくさん問題が見つかった場合は一旦修正を待ってから次のステップへ進みます
  3. 挙動を確認する

    • 実際の挙動を確認します
    • 前に上げたとおり、準正常系をメインに正常系と、切断などの簡単な異常系も確認します
    • 挙動が確認できないものや、確認する必要がないもの、微細な修正の場合はスキップする場合もあります
  4. 細かいチェックを行う

    • 挙動が問題なければソースを読んで細かいチェックを行います
    • 必要があればコードを手元に持ってきて、呼び出し箇所を調べることもあります
  5. 修正後の確認

    • 修正差分の確認を行います
    • 修正量によりますが、コミット内容だけをチェックする場合と、ステップ2からチェックしなおす場合があります

このように、コードレビューを軽いチェックと細かいチェックの2層に分けています。
作業の合間などに軽いチェックを行い、まとまった時間が取れるときに細かいチェックをすることで、レビュイーに素早くフィードバックが返せるように心がけています。
他にも、なるべくポジティブなコメントもつけるようにすることで心理的負担を減らす工夫をしています。
冒頭で軽く触れた、静的解析による機械的なチェックもレビュアーの負担を軽減するための取り組みのひとつです。

おわりに

コードレビューは業務の中でも集中力を要する大変な作業のひとつではないでしょうか?
技術によって人間が負担する部分を減らしていくのが理想ではありますが、コードレビューは多くの学びを得られるチャンスでもあります。
自分なりの手順を決めてこなせるようになってくると、今まで気が重かったタスクも楽しく進められると思います。
やっていきましょう。

/* */ @import "/css/theme/report/report.css"; /* */ /* */ body{ background-image: url('http://cdn-ak.f.st-hatena.com/images/fotolife/c/cookpadtech/20140527/20140527163350.png'); background-repeat: repeat-x; background-color:transparent; background-attachment: scroll; background-position: left top;} /* */ body{ border-top: 3px solid orange; color: #3c3c3c; font-family: 'Helvetica Neue', Helvetica, 'ヒラギノ角ゴ Pro W3', 'Hiragino Kaku Gothic Pro', Meiryo, Osaka, 'MS Pゴシック', sans-serif; line-height: 1.8; font-size: 16px; } a { text-decoration: underline; color: #693e1c; } a:hover { color: #80400e; text-decoration: underline; } .entry-title a{ color: rgb(176, 108, 28); cursor: auto; display: inline; font-family: 'Helvetica Neue', Helvetica, 'ヒラギノ角ゴ Pro W3', 'Hiragino Kaku Gothic Pro', Meiryo, Osaka, 'MS Pゴシック', sans-serif; font-size: 30px; font-weight: bold; height: auto; line-height: 40.5px; text-decoration: underline solid rgb(176, 108, 28); width: auto; line-height: 1.35; } .date a { color: #9b8b6c; font-size: 14px; text-decoration: none; font-weight: normal; } .urllist-title-link { font-size: 14px; } /* Recent Entries */ .recent-entries a{ color: #693e1c; } .recent-entries a:visited { color: #4d2200; text-decoration: none; } .hatena-module-recent-entries li { padding-bottom: 8px; border-bottom-width: 0px; } /*Widget*/ .hatena-module-body li { list-style-type: circle; } .hatena-module-body a{ text-decoration: none; } .hatena-module-body a:hover{ text-decoration: underline; } /* Widget name */ .hatena-module-title, .hatena-module-title a{ color: #b06c1c; margin-top: 20px; margin-bottom: 7px; } /* work frame*/ #container { width: 970px; text-align: center; margin: 0 auto; background: transparent; padding: 0 30px; } #wrapper { float: left; overflow: hidden; width: 660px; } #box2 { width: 240px; float: right; font-size: 14px; word-wrap: break-word; } /*#blog-title-inner{*/ /*margin-top: 3px;*/ /*height: 125px;*/ /*background-position: left 0px;*/ /*}*/ /*.header-image-only #blog-title-inner {*/ /*background-repeat: no-repeat;*/ /*position: relative;*/ /*height: 200px;*/ /*display: none;*/ /*}*/ /*#blog-title {*/ /*margin-top: 3px;*/ /*height: 125px;*/ /*background-image: url('http://cdn-ak.f.st-hatena.com/images/fotolife/c/cookpadtech/20140527/20140527172848.png');*/ /*background-repeat: no-repeat;*/ /*background-position: left 0px;*/ /*}*/