クラウドワークス エンジニアブログ

日本最大級のクラウドソーシング「クラウドワークス」の開発の裏側をお届けするエンジニアブログ

誰のためのコメント? 〜コメント・コミットメッセージの書き方を考える〜

クラウドワークスでエンジニアをしている八木 ( @negito6 )です。

私は最近、コメントをきちんと書くことに凝っています。コメントとは、ソースコード中に書いてコードの意図を説明したり、バージョン管理におけるコミットの説明を記述する、謂わば「注釈」のことを指します。

そこで本記事では、コメントを書くときの私なりのこだわりについて、紹介いたします。なんか長ったらしく書いています(自分でもそう思います)が、特に会社で強制しているわけではなく、今のところ私個人のポリシーです。(記事を書いた目的は、最後のほうをお読みください。)

なお、バージョン管理のツールは git および GitHub の例を用いてお話しします。ご自身の環境に合わせて適宜読み替えていただけると幸いです。

何を目指して書くか

想像してみましょう。時は金曜日の21:30。オフィスに居るエンジニアは自分一人。鳴り止まないアラート。他部署の人も何やら困っている。ユーザーからの問い合わせも増えているらしい。

最近開発内で勢力が拡大している酒クラスタ*1が飲み会中で、チャットに書き込む人もいない。目の前にあるソースを読むしかないが、見慣れないライブラリ、小耳に挟んだ社内用語、特別なデータがないと通過しない if 文、何を意味しているか分からないテスト。。。

f:id:negito6:20160502184349p:plain

そんな経験をしたこと、ないでしょうか。(※※※弊社での内情ではありません※※※)

少ない人数で、不慣れな領域の障害対応をしなければならないときは、ソースコード以外の情報が欲しくなります。

コメントを書くことのメリットはさまざまあると思いますが、私は「障害対応のため」に、もっと言うと「障害対応時の情報収集効率を上げるため」に絞って書くことにしています。それが、コメントの恩恵が一番大きいシチュエーションであると考えられるからです。

目的を絞る理由は、迷う要素を極力減らすためです。ただ漫然とコメントを書こうとしても、「前後のソースを読めば分かるんじゃないか」とか「ここに書かずに、別途仕様ドキュメントを作ったほういいのではないか」とか「とりあえず困ったら自分に聞いてもらえばいいかな」とか、色々と考え始めてしまうことがあります。しかし障害対応に目的を絞れば、万が一のときに欲しいと思われる情報を書くということに集中できます*2

障害は突然やってきます。自分のコミットの問題について、自分が常にアドバイスできるとは限りません。そんなときのためにコメントを書いておけば、過去と未来で情報交換をすることができます。仮に普段の開発には役に立たなくても、当たれば非常にリターンの大きい投資ですね。

この記事は、孤軍奮闘でコメント書いてる人、もしくは、書こうと思うものの迷ってしまいなかなか書けていない人にとって、役に立つかもしれない記事です。

- コメント書く派
|- 周りも巻き込んでる派
|- 孤軍奮闘派    <----    ここの人
`- 周りは気にしない派

- コメント書かない派
|- 書こうと思うけど書かない派    <----    ここの人
`- 書くべきではない派

ちなみに、「コメントには、変更の内容ではなく変更の理由を書こう」という話があると思いますが、その手の説明は色々なところで見かけるので、今回はあまり触れていません。

ツールごとに見えかたを考える

一口にコメントといっても、シチュエーションによって、見えるもの、見たいものが違います。

git log / git show でコミットメッセージを見る場合

コミットメッセージを見るときは、どんな情報がほしいでしょうか。私がコミットメッセージを見るのは、「ある変更が、なんのために入れた変更か」を知りたいときです。 Pull Request の diff が読みづらく変更点をコミットごとに知りたいときや、 git blame して特定の行の変更理由を知りたいときなどです。

コミット履歴は時間軸方向のデータを扱うので、 before / after の情報を含むことが望ましいでしょう。書くべきは、

  • コミット適用前の挙動
  • それでサービス上困っていること
  • コミット適用後の挙動

といったところでしょうか。

エラーが起きているのであれば、エラーの重要部分を貼って、「それが解消される」ということを記載しておけば充分だと思います。

f:id:negito6:20160428213220p:plain

GitHub で省略されたコミットメッセージを見る場合

GitHub で commits を見るときや、 Pull Request に含まれたコミット一覧を見るときはどうでしょうか。

私の場合コミット一覧を見るのは、「障害が起きたときに、直前のリリースに何か原因がないかを調べる」ということが多いです。

基本的には前述した git log のケースと同じですが、 GitHub でコミットのリストを見るときは、表示できる文字数に制限がありますね。そのため、限られた文字数の中で主題が伝わるよう、特にコミットメッセージの一行目、省略表示されたときに表示される文字数の範囲内に何を書くかを重視します。

メッセージが「リファクタリング」では障害への影響の有無が判断できないため、そのコミットの中身を見る必要が発生してしまいます。 たとえば、以下のようなコミットメッセージが並んでいたとき、問題となったコード・コミットを的確に探し当てることができるでしょうか。

f:id:negito6:20160428213636p:plain

このようなタイトルがたくさん並んでいるのを見て、怪しいコミットを全部開くのは大変ですね。せいぜい二つ三つに絞れるようにしたいところです。

コミットメッセージには、変更したモジュール名、関連する機能、またファイルやURLが限定されている場合はパスを表しておけば、かなりの判断材料になります。また、テストコードはユーザーに見える動作にも影響しないので、「テスト追加」なども重要な情報です。

git rebase コマンドの -i オプションでコミット一覧を開くときや、git log で --pretty="%s" のオプションをつけるときも、一行一コミットの表示になるため、限られた文字数内でコミットの主旨を表せるようにします。

ソースコード中コメントを見る場合

ソースコードにコメントを書くときは、フォーマットについて特に注意することはありません。こちらのケースの場合、考えるべきはコメントの内容です。

抽象度の高いコードを読むのは、障害対応時は特に負担になります。社内やチーム内で浸透しないライブラリを用いるときは、その動作を説明しておくと良いと思われます。また、関数・メソッドの戻り値の判りやすさにも気を配り、直感的でないものは動作や戻り値の例を書いておくと、デバッグの効率があがるでしょう。

コメントを書かなくて済むように読みやすいプログラムを書く、というのはもちろん理想的です。しかし実際は、過去のコードの再利用や公開ライブラリの利用、外部の API へのアクセスなど、全てを思い通りに書けるとは限りません。

# { "ok": true, "members": [{"id": 1234, "name": "negito6", ... }, ... ] }
api_call("users.list", params)

上記のコードがあったとします。「users.list という名前の API を実行したのに、欲しいリストのキーは members 」というのは想像しづらいのではないでしょうか。

ソースコード中に書かれるコメントの課題としては、コメントがどこのコードに対するものなのか解らないことがよくあります。コメントの対象がわかるよう今一度見直し、適切に空行を入れて範囲を明確にしましょう。また、前項で説明したコミットメッセージは長くても特別問題は起きませんが、ソースコードの場合はあまり長くならないように注意したほうががよいでしょう。

その他気にすること

参考にした記事へのリンク

コミットの際に、参考にした記事の URL を貼っておくことは非常に大切です。しかし、 URL があっても、中を見る手間をできるだけ省きたいものです。

ソースコードに URL が貼ってあっても、見る人のエディタやターミナルからリンクを直接開けるようになっていなければ、「URL をコピーし、ブラウザのロケーションバーに貼り付け、移動する」という操作が必要ですし、リンクしたサイトが落ちていたり引っ越してしまっていたりなど、そのページが見れなくなっていることもよくあります。

内容も重要です。リンクを開いてみるときというのは、当然リンク先にある情報に何か期待をしていたときです。欲しかった情報と実際の情報が関係なかった場合、開くための時間はそのままロスとなってしまいます。

リンク先の内容全てをコピーするというのは極端過ぎますが、どんな内容について書いてあるページか、開けばどんな情報が得られるのか、サマリーをコメントに載せておくだけで結果が変わってくるでしょう。

GitHub に依存しない

GitHub の Pull Request 上で、サービスの仕様やコードの書き方の議論をするケースがたくさんあると思います。ツールや外部サービスの依存について考え出すときりがありませんが、仮に GitHub の利用が変わらずとも、GitHub 上での議論が追えなくなってしまうことは考えられます。

私は

  • Git を使わなくなるケースは想定しない
  • GitHub から別サービスに乗り換えることはあるかもしれない
  • GitHub の利用が変わらずとも、そのリポジトリを使い続けるとは限らない

を前提にすると決めています。

「利用するホスティングサービスは同じままだけど、リポジトリは変わる」ということは想像しづらいかもしれませんが、たとえば大きくなったリポジトリを分割するときなどがあります。*3

上記を踏まえて、特に重要な意図、議論についてはなるべくコード転載するようにしています。コミットをわざわざし直すのが面倒なときは、マージボタンを押したときに、マージコミットのメッセージに記載する手もあります。

言語やフレームワークの機能

社内で採用して広く使われている言語・フレームワークの機能であれば、原則としては説明する必要はないはずです。ただし、極端にマイナーな機能や、間違いやすい機能を敢えて使うときは、書いてしまうほうが良さそうなこともあります。

Ruby on Rails の場合、たとえば present? / blank? / empty? の三つのメソッドの機能を比較している記事が山のようにあります。これは「ややこしいと思う人が多いから記事が作られる」と考えて差し支えないでしょう。当然調べれば分かるわけですが、説明して損はないと思います。

Revert の理由

障害の原因となったコミットが特定され次第、 Revert してデプロイする、ということがよくあると思います *4 。 しかし、私の知る範囲では、Revert の原因がきちんと書かれていることは残念ながら少ないです。

Revert 自体は、理由が単一パターンではないため*5、それだけでは障害だったのか否かは分かりません。なぜ Revert したのか、どんな障害だったか、記載しましょう。

開発中のバグ修正

私は今まで、開発中のバグ修正コミットは、squash merge することで、他のコミットに混ぜてしまっていました。 Bugfix という言葉からは障害を連想します。本当にユーザーへの不利益を起こしてしまったものと、開発中のトラブルとは区別したいからです。

最近では、「このエラーは開発しているときに見た気がするけど、対処のログが squash されてしまって残ってない。。。」という経験が何回かあり、「調査に手間を要したものであれば、開発中のコミットもそのままでいいかな」と考えています。

めんどくさくない?

以上に挙げたポリシーを全て導入すると、人によってはかなり面倒に感じると思います。コメント書かない派 / 書くべきではない派の人に勧めても、短期的な導入は難しいでしょう。

書こうという意欲があってたとしても、最初から全てをルール化するのは大変です。 まずは目標を絞り、迷ったらその都度考えて、少しずつパターンを作っていきましょう。 面倒なことでも、続けていくと習慣化されて作業一つ一つの負担は下がっていきます。 「どうせ書くなら、意味のあることを書いたほうがいいかな」くらいの気持ちで始めることが大切です。ルール導入時は、サボった人を糾弾したりしてはいけません。

周りを巻き込みたいとき、とにかくまずは、自分が率先して実績を積んでいくことが重要だと思います。書こうと思った時、近くに例があると、考える手間が減らせます。そして、「コメントがあって助かった」という成功体験を積み重ねることによって、書くことへの共感を持ってもらうこともできるでしょう。

終わりに

この記事を書いた目的について書きたいと思います。

コメントは、プログラムをリリースをするための必須な機能要件ではなく、且つ「解りやすいか解りづらいか」という内容の質を定量化できません。非常に抽象的な成果物です。

そういう曖昧なものについて、一度 Pull Request が上がってきたときにわざわざ「直してくれ」と言うのは結構心理的な抵抗があるものではないでしょうか(少なくとも私はあります。今のチームはコメントを書くことに積極的なので助かっていますが、それでも尚、わざわざ書き直してもらうのはあまり楽しいことではありません)。また、レビューの都度思いつきで指摘をしていると、主観的な意見ばかりになってしまい、指摘を受ける側は大変です。

チームとして取り組みを定式化をしていきたいとき、新人さんに覚えてもらいたいとき、 どうするべきかのポイントと、それをする理由、全体の目標がまとまっているべきだと思います。 この記事が、そのたたき台にになれば幸いです*6

クラウドソーシングのクラウドワークスでは、開発プロセスにこだわるエンジニアを募集中です! www.wantedly.com

*1:本ブログに登場するお酒エンジニアを指しているわけではありません。あくまで例です

*2:マーク・ザッカーバーグが同じTシャツを着ていたり、オバマ大統領がスーツの色を絞ったりしているのは、選ぶのに使うエネルギーを削るためだそうです。それと同じです

*3:共有のリポジトリを消してしまったというケースを見たこともあります(forkしたリポジトリと間違えたそうです)。そのときはデプロイサーバからブランチを復旧させたようでしたが、それまでGitHub上で蓄積した議論は消えてしまいました。復元する方法ってあるのでしょうか

*4:GitHub ユーザーにとっては、Pull Request 画面の Revert ボタン機能が追加されてから、 Revert のハードルがぐっと下がったように思います

*5:リリースのタイミングではないのにリリース用ブランチにマージしてしまったときなども Revert しています

*6:弊社内にも私の習慣が浸透していくことを期待しています

© 2016 CrowdWorks, Inc., All rights reserved.