Work in ProgressパターンによるPull Requestを利用した開発フロー

## はじめに

ソースコード管理ツールとしてGitlabやGithubを導入することで、ソースコードのバージョン管理に加えて、コードの変更前にコードレビューを実施するPull Requestを簡単に行うことができる。コードレビューの観点や手法は様々であるが、レビューを実施する前に幾つかのコンテキストをレビュー担当者とレビュー依頼者が共有しておくことでスムーズなコードレビューが期待される。

本文章ではWork in Progressパターンと呼ばれる手法を利用した、コードレビュー前のコンテキストの共有方法を紹介する。

## コンテキストの共有

コードレビューを実施する前に幾つかのコンテキストを共有することは、レビュー担当者の負担削減や、レビューの品質向上またレビュー依頼者のタスクの明確化に繋がる。共有するべきコンテキストの一例として以下の物が挙げられる。

 1. 実装する機能の詳細設計
 1. 実装する機能の仕様
 1. 実装する機能に期待する動作、単体試験の内容

上記のようなコンテキストに対して事前に共有、コンテキストに対するレビューを実施することで実装後の手戻りの防止が期待される。これらを口頭によるやりとりではなく、Github/Gitlabが提供するPull Requestを利用することで履歴として残すことが可能である。作業手順を列挙する。

 1. 作業ブランチを作る
 1. ファイル変更の無いコミットを作る
 1. リモートブランチへプッシュする
 1. Pull Requestを作る
 1. Pull Requestのレビュー後、実装作業を行う
 1. 変更をコミットする
 1. リモートブランチへプッシュする
 1. Pull Requestを更新する

### 作業ブランチを更新する

まずは統合ブランチ(主にmasterブランチ)や機能ブランチから派生をしたトピックブランチを作る。ブランチを作るためには事前にチケット管理システムを利用してタスクをチケット/ISSUE/かんばんで共有、まとめておくことが望ましい。ブランチの名称パターンはプロジェクトごとに様々だが、例えば`機能名/チケット番号`を採用することがある。

	git checkout -b tweet/#1001

### ファイルの変更がないコミットを作る

GithubでPull Requestを作るには、マージ先ブランチとは異なるコミットの存在するブランチが必要となる。そのため、最初にファイル変更がないコミットを作りPull Requestのみを作ることができる環境を用意する。また、このファイル変更のないコミットメッセージにはこれから実装される機能の仕様を記入することで実装作業によって満たされる仕様が明確化される。

	git commit --allow-empty -m '[WIP]テキストの最大文字数は140文字である'
	# コミットメッセージの先頭には作業中であることを表す[WIP]を付与する

### リモートブランチを作る

リモートリポジトリにプッシュすることで、リモートブランチを作る。

	git push origin tweet/#1991

### Pull Requestを作る

Githubの画面からPull Requestを作る。この時タイトルに`[WIP]`をつけて作業中であることを明記する。また、メッセージには共有するべきコンテキストを記入する。レビュー担当者は共有されたコンテキストをレビューする。問題がなければレビュー依頼者は実装作業を行う。また、コンテキストに対するレビューを実施したことが残るように[task list](https://github.com/blog/1375%0A-task-lists-in-gfm-issues-pulls-comments)を利用することもある。以下にサンプルのパターンを記載する。

#### タイトル:[WIP]テキスト入力文字数制限

#### 本文:

##### 設計

 - [ ] TextWatcherを利用してEditText入力後に入力されている文字数を確認する
 - [ ] TextWatcherを利用して,EditText入力後の文字数を画面に表示、更新する
 - [ ] EditTextのmaxLengthで、最大入力可能文字数を制限する

#### 動作確認方法

 - [ ] EditTextに文字を入力した際に、入力している文字数が更新される
 - [ ] 140文字入力すると、それ以上文字を入力できなくなる

### Pull Requestのレビュー後、実装を行う

作業者はPull Requestに記載した内容に則って作業を行う。実装中に設計の方針が変更になった場合には、Pull Requestの更新と共有を必ず行う。

### 変更をコミットする

作業者は作業が完了したら変更をコミットする。しかし、コミット時には最初につくったファイル変更の無いコミットが残っている。そのため、リビジョングラフの簡潔さを保つためこのファイル変更がないコミットを消しておく必要がある。

	git commit -m 'テキストの最大文字数を設定した'
	git commit -m '入力された文字数を画面に反映する'
	git rebase -i HEAD^^^ #ファイル変更の無いコミットを起点にrebaseを行う

`git rebase -i`はコミットの書き換えを実施できる。起動したエディタには現在のコミットの状態が記入されている。各行が1つのコミットに対応していて、先頭に書かれている命令を変更することでコミットに対して書き換えなどの作業を行うことが可能である。(ちなみにこのときソースコードを編集しているIDEやエディタを閉じておいたほうが良い)

ここで行う作業の内容は、「ファイル変更の無いコミットを次のコミットとまとめる」ことである。次の様にコミットの編集を行う。

```diff
#pick ${HASH} [WIP]テキストの最大文字数は140文字である
- pick ${HASH} テキストの最大文字数を設定した
pick ${HASH} 入力された文字数を画面に反映する
+ f ${HASH} テキストの最大文字数を設定した
pick ${HASH} 入力された文字数を画面に反映する
```

エディタを保存して終了するとrebaseが始まる。多分コンフリクトはしない。

`git rebase`の振る舞いについては各自で調べておくのが良い。

### リモートブランチへプッシュする

リモートブランチへのプッシュは、rebaseによってコミットを編集していることから、force pushが必要となる。

	git push -f origin tweet/#1001

### Pull Requestを更新する

Pull Requestのタイトルなどから`[WIP]`を取り去って、作業が完了したことをレビュー担当者に伝える。レビュー担当者はレビューを実施し、作業者は必要に応じて修正を行う。

## まとめ

Work in Progressパターンと呼ばれる手法を利用した、コードレビュー前のコンテキストの共有方法を紹介した。本方式では、コードレビューの前にコンテキストの共有を行うことでレビューによる手戻りの防止やレビュー担当者の負担の軽減を行いそれらを通じてソースコードの品質向上を実現できる。しかし、gitコマンドを適切に理解・運用する必要があることからマニュアルやドキュメントを事前に閲覧しておくことが必要不可欠である。