コードコメントはこう書く!WHATではなく、WHYを説明する意義とは
こんにちは!
ラブグラフエンジニアのひろです。
今日はいまだに迷いながら書いているコードコメントについてです。
どんなコードコメントが良いコメントとされるのか、いくつかの例をもとに一緒に考えてみましょう。
コードコメントとは
そもそもコードコメントは何のために書くのでしょうか。
すべてのエンジニアが読んでいる本、と言っても過言ではない「リーダブルコード」の
コメントについての章ではこう書かれています。
「コメントの目的は書き手の意図を読み手に知らせること」
つまり、 そのコードが何をしているのか(What) ではなく、 なぜそのコードが必要なのか(Why) を書きましょう。ということですね。これを念頭に考えていきましょう。
事例1
なぜ includes と preload を分けて書いているのか
# ここに入るコメント
products =
Product
.includes(:categories, :reviews)
.preload(reviews: [:user, :rating])
products = products.where(categories: { name: params[:category] }) if params[:category].present?
products = products.where(reviews: { user_id: params[:user_id] }) if params[:user_id].present?
悪い例(WHATを書いている)
# includes と preload を利用して関連データをロード
良い例(WHYを説明している)
# categories, reviews は絞り込み条件によって、DBアクセスが発生する可能性があるので includes を利用
# reviews の先の user, rating は絞り込みでは使わず、 View で使っているだけなので preload を利用
この改善によって、わざわざ関連データの取得を分けて書いている理由が分かり、後からコードを読んだ人が「ここはまとめられそうだからまとめてしまおう」と変更してしまうことが無くなります。
また、 includes
と preload
がどう違うのか?という疑問の解消の助けにもなりますね。
事例2
なぜそこで処理を終わらせているのか
def process_payment(user, plan)
# ここに入るコメント
return if plan.is_enterprise?
if user.credit_card.present?
user.update(payment_status: 'paid')
else
user.update(payment_status: 'no_card')
end
end
悪い例(WHATを書いている)
# 企業向けプランの場合は、支払い処理をおこなわない
良い例(WHYを説明している)
# 企業向けプランの場合、支払いは請求書ベースで処理されるため、オンラインでの支払い処理をスキップ
後者のコメントがあることで、「支払い方法が異なるプランがある」というドメイン知識を得ることができ、さらに請求書で処理されているという運用フローも知ることができます。
他の開発時に運用フローを考慮に入れた提案ができるようになることが期待できますね。
事例3
class SendEmailForPhotographerJob < ApplicationJob
# ここに入るコメント
sidekiq_options retry: 0
悪い例(WHATを書いている)
# この Job はリトライしない
良い例(WHYを説明している)
# カメラマンに重複してメールが送信されるのを防ぐためリトライしない
このコメントがあると Job のリトライによって起きうることが把握でき、今後の Job 設計の参考になることが期待できます。
また、コメント自体があることで retry オプションについて調べるきっかけにもなるかもしれませんね。
終わりに
コードにどんなコメントを書くべきなのか、イメージが湧くようになったでしょうか?
コメントを書いた後に見返していて、「やっぱりここには必要ないかも?」と思ったり、「ただ何をしているか説明しているだけだから修正しなきゃ」と思うことがまだまだあり、コメントを書くにも鍛錬が必要だなと感じています。
はじめに紹介したリーダブルコードには、コメント以外にも大切なことがたくさん書かれているので、もしまだ読んだことがなければぜひ読んでみてください!
10年後の自分でも読みやすいと感じる ような、良いコードを書けるように精進していきましょう!
Discussion