みなさんはコードを書くとき、何を大事にしていますか?私はずばり、 シングルタスク にすることを重視しています。
ここでのシングルタスクは「コードを書いている間はコードを書くことに集中する」ということではなく、
- 条件分岐を書いている間は条件分岐を書くことに集中する
- テストを書いている間はテストを書くことに集中する
のようなことを指します。
実際、アメリカ心理学会による マルチタスクに関する調査の記事 でも「一度に複数のタスクを行うと生産性が低下する」と言われています。コードを書くという作業においても、とある箇所を実装しながら「テストはどう書くんだろう」「今後拡張することになったらどうしよう」などと考えてしまい、手があまり動かないという経験をした方もいるかもしれません。
とはいえ、git を使った開発をしていれば、開発をしている間はブランチが枝分かれしないので、見かけ上シングルタスクをやっているように見えます。
(Git ツリーの例)
そこで、
先にコミットする内容を決めてからコードを書けばシングルタスクになって生産性が上がるんじゃないか…?
という発想に至りました。これが今回ご紹介する コミットメッセージ駆動開発 (Commit Message Driven Development, CMDD) です。この先は CMDD の具体的な手法とメリット・デメリットについて触れていきます。
(私以外にも Commit Message Driven Development について言及している方がいらっしゃいますので、その方々の記事もぜひお読みください。)
コミットメッセージ駆動開発 (Commit Message Driven Development, CMDD) とは
CMDD とは、コミットメッセージに合わせてコードを書く開発手法であり、コーディングのシングルタスク化を促すことで生産性の向上を助けるプラクティスです。
具体的には
- やることリストを作成する
- コミットメッセージを書く
- コードを書く
- コミットする
- プッシュする
というサイクルで進みます。コミットメッセージを書いてからコミットするまでの流れは何度か繰り返すこともあります。
(CMDD のイメージ図)
CMDD の実践方法
ここでは git コマンドを利用して CMDD を行う方法を紹介します。
あくまで私ならこうするという話なので、ぜひアレンジして自分なりの方法を作ってみてください。
やることリストを作成する
やることリストはどこに作成しても構いません。テキストファイルでも良いですし、ノートに手書きで書いても大丈夫です。また、初めからリストを完璧に書けなくても構いません。休憩中やコードを書いている間など、思いついたらその都度書き足せばいいのです。
コミットメッセージを書く
まず、コミットメッセージを決めて空コミットします。
--allow-empty
オプションを付けることで、コードの変更を含まない、メッセージだけのコミットができます。
git commit --allow-empty -m "[wip]fix: リクエストの xx パラメータが検証されていないので検証する"
コミットメッセージは具体的に書くようにしてください。例えば、「リクエストのバリデーションを修正する」よりも「リクエストの xx パラメータが検証されていないので検証する」の方がより良いです。
以下の要素を含めるように意識してみてください:
- 何を実装するのか
- どうしてその実装が必要なのか
(コミットが完了したときの出力例)
$ git commit --allow-empty -m "[wip]fix: リクエストの xx パラメータが検証されていないので検証する"
[main yyyyyyy] [wip]fix: リクエストの xx パラメータが検証されていないので検証する
コードを書く
次にコードを書きます。
…何か他のことを思いつきましたか?大事なことであれば、やることリストに書いておきましょう。今はコミットメッセージに書いたことをやる時間なのです。
コードを書き終わったら、ファイルをステージします。
git add <files> ...
コミットする
直前のコミットを上書きしつつメッセージの先頭にある [wip]
を削除します。必要に応じて具体的な実装内容を追記しても構いません。
--amend
オプションで直前のコミットを上書き、--date
オプションでコミット時刻を変更できます。
git commit --amend --date "$(date)"
# エディタが開いたらメッセージを編集して閉じる
(コミットが完了したときの出力例)
$ git commit --amend --date "$(date)"
[main zzzzzzz] fix: リクエストの xx パラメータが検証されていないので検証する
Date: Mon Jan 01 08:00:00 2024 +0900
1 file changed, 1 insertion(+)
何を実装しているか忘れたときは
もし、途中で迷った場合は、git log
コマンドで直前のコミットメッセージ(何をやろうとしていたか)を確認します。
(ああそうだ、今はリクエストのバリデーションを修正しようとしていたんだった、と)
$ git log
commit zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz (HEAD -> main)
Author: Jane Doe <jane_doe@example.com>
Date: Mon Jan 01 07:00:00 2001 +0900
[wip]fix: リクエストの xx パラメータが検証されていないので検証する
commit xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
Author: Jane Doe <jane_doe@example.com>
Date: Mon Jan 01 06:00:00 2001 +0900
initial commit
CMDD のメリット
コードを書いていて迷うことが少なくなる
先にコミットメッセージ(実装内容)を決めることで、今取り組むことが明確になるだけでなく、思考も整理されるため、コードを書いていて迷うことが少なくなると思われます。
コードレビューがしやすくなる
コーディング後にコミットメッセージを考える場合、実装後に内容が決まるため、チェックポイントを設けてコミットする習慣が無ければ単に「xxx を修正した」や「m 月 d 日作業分」など煩雑になりやすいです。コミットが煩雑であればあるほど、レビュワーはコードの完成形だけをもとにレビューをさせられますが、コミットメッセージが明確であれば実装過程がより鮮明になり、レビュワーがコードを読みやすくなります。
また、バグが見つかった際はどのコミットでバグが埋め込まれたかを特定しやすくなり、バグが埋め込まれる前のチェックポイントに戻って実装をやり直すことも容易になります。エクストリームプログラミングのベイビーステップやテスト駆動開発などと併用することでバグを埋め込む可能性はさらに低くなると思われます。
プログラミング学習がはかどる
プログラミング学習において一つのプログラムを作成する際、いくつものステップを経由します。各ステップにおける思考の過程をコミットメッセージとして残すことで、迷っても後から振り返ることができます。
CMDD のデメリット
Git pre-commit hook が多いリポジトリでは開発スピードが落ちる
コミットが細かくなる反面、コミット量は多くなるため、pre-commit hook でユニットテストや変更ファイルのフォーマットなどをたくさん行っている場合、それだけで時間がかかってしまい、開発スピードが落ちるどころか、開発者にとってもイライラのもとになります。開発環境を軽量にしたり IDE の使い方を工夫するなどしてコミット時の時間を軽減することが必要になります。
ブランチをそのままマージすると後々見にくくなることがある
CMDD では思考が整理される反面、細かな過程も生々しくコミットされるため、ブランチをそのままマージコミットとして積むと、かえってノイズとなることもあります。その場合、コードレビューが済んだらリベースやスカッシュマージなどを利用し、美しい形に整えた方が良いかもしれません。
ペアプロの場合、今何をやっているかの管理はナビゲーターがやればよい
と個人的には思います。なので私は CMDD のことを「セルフペアプロ」と呼んでいます。ちなみに「セルフペアプロ」という単語は今考えたやつですね。すでに思いついている方がいたらすみません。
所感
以上のように実装もはかどる、レビューもしやすくなる、そんな CMDD ですが、ググってもあまり記事が出てこないことから、それほど流行っていないのでしょう…
その理由として、
- 熟練したエンジニアの方にとっては今回紹介した手法が頭の中でごく自然にできている
- プロダクトの品質を高めるためならテスト駆動開発などで十分である
などが考えられます。
個人の開発スキルを高めるという目的では効果が得られると思いますので、ついついコミット単位が大きくなってしまうことを課題と感じていらっしゃる方はぜひお試しください。
References
Commit Message Driven Development | Sven Hofmann