読者です 読者をやめる 読者になる 読者になる

開発速度を上げるための Pull-Request のつくり方

こんにちは、投稿開発部の森川 (@morishin127) です。クックパッド、お料理アルバムみんなのお弁当の iOS アプリの開発等に携わっています。

クックパッドでの開発は GitHub Enterprise 上で行われており、書いたコードをプロダクトに取り込む前には基本的に第三者のコードレビューが必須です。コードレビューはプロダクトの品質向上に貢献していますが、往々にして結構な時間と労力がかかるものです。Pull-Request を出してレビューをしてもらい指摘の修正を繰り返していると、場合によってはマージに数日〜1週間ほどかかってしまうこともあります。自分の開発速度を速めるため、また周りのエンジニアの開発速度を下げないためにレビューしやすい Pull-Request を出すことは重要です。この記事ではレビューしやすい Pull-Request のために心がけていることを紹介したいと思います。

説明文は構造化してひと目で分かるように

Pull-Request の説明文では Markdown が使えます。見出しや箇条書きのスタイルを利用することでかなり読み易くすることができます。例えば次のような形式で書くことが多いです。

# 目的
<実装の目的を一文ぐらいで>
# やったこと
- <実装の技術的な内容を>
- <箇条書きで>
- <書く>

UI の変更前後を視覚的に

Before / After のスクリーンショット

UI に変更のあった Pull-Request では説明にスクリーンショットを用いることが多いと思いますが、このとき変更後のものだけでなく変更前の画像も比較できるようにしておくと非常にレビューがし易いです。スクリーンショットを横に並べる場合は下記の Markdown のようにするとシュッとした感じになります。

before | after
---- | ----
<img src="" width="320"/> | <img src="" width="320"/>

f:id:morishin127:20160816192651p:plain

長い画面のスクリーンショット

余談ですが、モバイルアプリではスクロールビューのように画面に収まらない長いビューのスクリーンショットを撮りたい場合があります。iOS 実機を使っている場合は Tailor というアプリでスクロールしながら撮った複数のスクリーンショットを結合したりしています。ただ開発中はシミュレータを使用していることも多く、PC内に保存した画像を同様に結合できる手段が欲しかったためそのためのスクリプトを書いて使ったりもしています(雑ですが)。重なり部分を判定していい感じに結合してくれます。

morishin/image-stitcher
https://github.com/morishin/image-stitcher

アニメーション GIF で動作確認

実装した機能の動作の様子は静止画では伝わらないことも多いので動作の様子を撮影したアニメーション GIF を積極的に貼っています。撮影はかつてオープンソースだった Gifzo を社内用にアレンジしたものが使われています。実機の画面を撮影したい場合は QuickTime Player の機能で iPhone の画面を Mac に映しそれを先述のツールで撮影しています。

f:id:morishin127:20160816193322g:plain

変更は数百行までに

やはり大きな変更のレビューには時間がかかる上に問題点の発見も困難になります。プロダクトの内容や言語にも依りますが、 iOS アプリの開発においては 500 行を超えるとかなりレビューがしんどく感じます。大きな変更を加える場合は feature ブランチを切り、数百行以内に収まるように分割した Pull-Request を feature ブランチに向けて出すのが良いでしょう。複数の Pull-Request に分けるとレビューしてもらうものが増え時間がかかるように思えますが、変更が大きい Pull-Request は敬遠され中々レビューされなかったり(よくある)、問題点があっても発見されづらくなるリスクがあるため、適度に分割することが開発効率の向上に繋がります。

Dokumi による事前レビュー

クックパッド iOS の開発では CI 上で Dokumi というツールが動いていて、機械的な静的解析で分かるような問題点は Dokumi が Pull-Request へのコメントという形で指摘してくれます。こういったツールもコードレビューの負担を減らしています。Dokumi についての詳細は過去の紹介記事をご覧ください。 Dokumi (日本語) - クックパッド開発者ブログ

まとめ

サービス開発では品質の保持と同時に開発・検証のサイクルを速く回すことも求められます。前者を保証するためにコードレビューという作業は必要ですが、開発速度のボトルネックになることもあります。このコードレビューを速く回すためにもレビュワーに負担のかからないレビューし易い Pull-Request をつくるよう心がけましょう。

/* */ @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;*/ /*}*/