if (review) { return learning; }
こんにちは。
株式会社ココナラ在籍のKです。
「コードレビューがつらい」
そのように感じている方は少なくないのではないでしょうか。
私も以前はそうでした。
本記事では、コードレビューのつらさの根本原因を明らかにした上で、私が実践している科学的根拠に基づいた向き合い方をご紹介します。
対象読者
本記事は、以下のような方に向けた記事です。
- コードレビューにつらさを感じている方
- コードレビューの質を改善したい方
- コードレビューを通して効率よく学びたい方
- コードレビューを通して開発効率を向上させたい方
記事の構成
本記事は、大きく以下の構成になっています。
- コードレビューのつらさの根本原因
- パラダイムシフト:「品質ゲート」から「学習機会」へ
- コードレビューの学習効率は優秀
- コードレビューの学びを最大化する実践的手法
コードレビューのつらさの根本原因
コードレビューは、レビュアーとレビュイーの双方にとってつらいものです。
まず、その根本原因について考えていきます。
レビュアーのつらさ
レビュアーにとっては、以下のようなつらさがあります。
-
レビュイーの問題
- レビュー対象コードの品質が低く、大量の指摘をするのがつらい
- レビュイーにコードを書く基礎スキルが不足しており、基本を一から説明するのがつらい
-
チームの問題
- 自身にレビューの負荷が集中していてつらい
-
自身の問題
- 自身に基礎スキルが不足しており、シンプルに他の人のコードを読むのがつらい
-
時間制約の問題
- 自身のタスクを抱える中、他者のコードのチェックに時間を割くのがつらい
レビュイーのつらさ
一方、レビュイーにも以下のようなつらさがあります。
-
レビュアーの問題
- 内容や根拠が曖昧な指摘に対応するのがつらい
- レビュアーからの誤った指摘に対して、誤っている理由を説明するのがつらい
- 好みの違いによる宗教論争に巻き込まれるのがつらい
-
チームの問題
- チームにドメイン知識が不足しており、背景を一から説明するのがつらい
-
自身の問題
- 自身に基礎スキルが不足しており、指摘への対応方法がわからないのがつらい
-
時間制約の問題
- 時間がない中、指摘事項の対応をするのがつらい
このように、レビュアーとレビュイーの双方にとって、コードレビューは様々なつらさを伴うものです。
根本原因としての品質ゲート
「これらのつらさをどうにかできないものか…」と考え、原因を掘り下げていきました。
すると、ある共通の根本原因があることに気付きました。
それは、レビューを「品質ゲート」として捉えているということです。
品質ゲートとは、レビューを品質保証のための関門と位置づけ、バグの発見と排除に重きを置く考え方です。
「品質ゲート」としてのコードレビュー
品質ゲートの典型例
品質のみを重視すると、レビューは単なる作業や義務になり、時間的負担や批判への恐れなどのネガティブな感情が生じやすくなります。
さらに、相手への配慮を欠いた指摘にもなりがちです。
例えば、以下のような状況は「品質ゲート」としてレビューが機能してしまっている典型例です。
- コードの意図や設計について、まったく議論されない
- 些細なコーディングスタイルの違いばかり指摘される
- 指摘された箇所を修正するだけで、なぜ指摘されたのか、根本原因を深く考えない
- 特定の人だけが積極的にレビューし、他の人はLGTMという定型文を書くマシーンになっている
- 開発者は疲弊し、個人とチームの成長は停滞し、最終的には品質も低下している
パラダイムシフト:「品質ゲート」から「学習機会」へ
では、どのようにすればこの状況を改善できるのでしょうか?
まず、一般的な改善策から見ていきます。
一般的な改善策の限界
コードレビューを改善しようとした場合、以下のような改善策がよく思い浮かびます。
- 機械的なチェックができるようにCIを整備する
- AIによるレビューを導入する
- ドメイン知識を共有する
- PRを小さくする
- …
これらの一般的な改善策は必要なものではあります。
しかしながら、一方で以下のような限界があることが多いです。
- 実行に時間がかかる
- 実行したとしても、効果が出るまでに時間がかかる
- 何かひとつの対応で、状況が劇的に改善するわけではない
パラダイムシフト
そこで、本質的な改善を行うには、コードレビューに対する考え方そのものを根本的に変える必要があると考えました。
つまり、
// 品質ゲート
if (review) {
return quality;
}
という視点から、
// 学習機会
if (review) {
return learning;
}
という視点へのパラダイムシフトです。
コードレビューを「品質ゲート」ではなく、「学習機会」と捉え直します。
パラダイムシフトによる変化
このパラダイムシフトにより、筆者の中で以下のような変化が起きました。
- レビュー時間が単なる作業や義務の時間から、自身が成長するための時間に変わった
- レビューが自身のスキルアップに繋がると認識することで、レビューへの意欲が高まった
- 指摘を批判として受け取るのではなく、自身の成長のための貴重なフィードバックとして捉えるようになった
- レビューを通じて学習することで、同じミスを繰り返すことが減り、結果としてコードの品質と開発速度が向上した
品質ゲート vs 学習機会
以下の表は、コードレビューを品質ゲートではなく、学習機会と捉えた場合に起こる変化をまとめたものです。
観点 | 品質ゲート | 学習機会 |
---|---|---|
目的 | バグの発見と修正、品質の保証 | 成長、学習、知識の共有、チームのスキルアップ |
焦点 | コードの正誤、コーディング規約への準拠、指摘事項の修正 | コードの理解、改善点・代替案の検討、根拠の説明、指摘事項の理解と原因分析 |
効果 | 短期的な品質維持 | 長期的な品質、効率向上 |
時間感覚 | 作業、義務、負担、限られた人生の時間の切り売り | 成長の機会、人生にとっての必要時間 |
レビューコメント | 批判的、評価的、形式的 | 建設的、協力的、対話的 |
感情 | レビュー中: プレッシャー、不安、批判への恐れ レビュー後: 解放感(修正が終わったことへの)、疲労感 |
レビュー中: 好奇心、探求心、学びへの意欲 レビュー後: 達成感、満足感、学びの喜び |
コードレビューそのものは何も改善していないにもかかわらず、大きく世界の見え方が変わっています。
まさしくパラダイムシフトです。
「品質ゲート」としてのコードレビュー
「学習機会」としてのコードレビュー
コードレビューは自己投資
それでも、レビューに時間をとられるつらさは変わらないのでは?と思われるかもしれません。
その疑問はもっともです。
短期的な視点で見れば、レビューは時間を消費する作業です。
しかしながら、レビューを学習機会と捉え、適切に実践することで、長期的な開発効率は向上します。
例えば、レビューを通じて新しい知識や技術を習得したり、コードの品質改善に貢献したりすることで、結果的に手戻りが減り長期的な開発効率の向上に繋がります。
また、「時間がない」という状況は、レビュー以外の要因(プロジェクトのスケジュール、タスク管理、個々のスキルなど)によって引き起こされていることも多いです。
重要なのは、レビューを単なる作業ではなく、将来への投資、特に自分自身とチームの成長に対する投資と捉えることです。
短期的な時間消費は、長期的な利益を生み出すために必要な投資です。
少なくとも筆者はそう考えました。
コードレビューは自己投資
コードレビューの学習効率は優秀
コードレビューを学習機会と捉えるにしても、そもそもコードレビューの学習効率が高くないのであれば、ただの精神論で終わってしまいます。
そこで、科学的根拠に基づいて考えます。
学習理論との適合性
コードレビューは、認知心理学で特に効果が高いと実証されている以下の学習理論と深く適合しています。
コードレビューに適切に向き合うことで、活用しないのがもったいないくらい効率的な学習機会になります。
記憶に定着させる
分散学習(間隔学習)
学習と学習の間に適切な間隔を空けることで、記憶の定着を促進する学習方法です。
-
効果
- 時間を空けることで、脳内で情報が整理され、長期記憶として定着しやすくなる
- 覚えたての情報を思い出すよりも、忘れかけた情報を思い出す方がより多くの認知的努力が必要であり、その努力が記憶の定着を促進する
- 分散学習が長期記憶の定着に効果的であることが多くの研究で実証されている
-
コードレビューとの適合性
- コードレビューは、不定期に発生するイベントであるため、半強制的に分散学習の機会を提供する
想起学習(検索学習)
過去に学んだ知識や経験を能動的に思い出そうとすることで記憶を強化する学習方法です。
-
効果
- 思い出そうとすることで脳の神経回路が強化され、長期記憶に定着しやすくなる
- ただ思い出すだけではなく、思い出した内容を第三者に具体的に説明することで、より記憶に定着しやすくなる
-
コードレビューとの適合性
- コードレビューでは、以下の行動が求められるため、想起学習の絶好の機会となる
- 学んだ知識や過去の指摘事項を能動的に思い出す
- 思い出した内容を相手に伝わるように具体的に説明する
- コードレビューでは、以下の行動が求められるため、想起学習の絶好の機会となる
深く理解する
精緻化
既存の知識に新しい情報を関連付け、その関係性を深く考察することで、本質的な理解を得るプロセスです。
-
効果
- 単に情報を暗記するのではなく、以下のように深く考察することで、理解度が格段に向上する
- 既存の知識と関連付け、自分なりの解釈を加える
- なぜ?どのように?という質問を繰り返し、深く掘り下げる
- 抽象的な概念を具体的な例に置き換える
- 学んだ情報を自身の言葉で説明することで、理解度を確認する
- 単に情報を暗記するのではなく、以下のように深く考察することで、理解度が格段に向上する
-
コードレビューとの適合性
- コードレビューでは、以下の行動が求められるため、精緻化の絶好の機会となる
- レビュー対象のコードに対して、その意図や設計、自身の知識(例:過去の経験、技術書籍から得た知識など)を関連付け、自分なりに解釈する
- 自己レビューやレビュー相手とのやり取りの中で、「なぜ?」「どのように?」と質問して掘り下げる
- アーキテクチャや設計原則などの抽象的な概念を具体的なコードに適用し、自身の言葉で説明する
- コードレビューでは、以下の行動が求められるため、精緻化の絶好の機会となる
応用、実践力を高める
インターリービング(交互配置学習)
異なる種類の課題に交互に取り組むことで、応用力、実践力を身につける学習方法です。
-
効果
- 解決手法が異なる類似した課題に取り組むことで、その手法を適用すべき状況を識別できるようになる
- 手法の理解が深まることで、複数の手法を組み合わせることでしか解決できない課題にも対処できるようになる
-
コードレビューとの適合性
- コードレビューの以下の特性から、インターリービングの絶好の機会となる
- 機能追加、バグフィックス、ライブラリ導入、パフォーマンス改善など様々な変更を取り扱う
- 仕様との適合性、可読性、パフォーマンス、セキュリティ、UXなど、様々な観点で評価する
- コードレビューの以下の特性から、インターリービングの絶好の機会となる
コードレビューを学習機会と考えることは妥当
以上のように、コードレビューは学習理論との相性が良く、単位時間あたりの学習効果が非常に高いです。
コードレビューを避けることは、効率的に学習する機会を自ら放棄するようなものと言えます。
学習理論について、さらに詳しく知りたい方には『認知心理学者が教える最適の学習法: ビジュアルガイドブック』が参考になると思います。
効果的な学習方法がわかりやすく整理されています。
コードレビューの学びを最大化する実践的手法
ここからは、筆者が実践している手法を具体的なステップと例を交えてご紹介します。
レビューを通じた学習サイクル
学習理論の恩恵を最大限享受するために、コードレビューを継続的な学習サイクルの一部と捉え、以下を実践しています。
レビュー前
レビュイー/レビュアー共通
コードレビューを効果的な学習機会とするには、習慣的な学びと時間の確保が必要不可欠です。
能動的に学んだことが学習のための素材になります。
学びなくコードレビューに臨むことは、素材なしで料理しようとするようなものです。
ステップ | やること | 解説 | 関連する学習理論 | 具体例 |
---|---|---|---|---|
事前学習 | 学びを習慣づける | 普段学んでいることが想起学習の思い出す対象、精緻化の関連付けの材料、インターリービングの観点になる | 想起学習、精緻化、インターリービング | ✅️ 書籍や記事などを読み、知識の幅を広げる ✅️ 普段使用している技術のドキュメントを読み、理解を深める |
時間の確保 | レビュー時間を確保する | 十分な時間を確保することで、深い考察や建設的な議論を行う余裕が生まれる | 精緻化 | ✅ レビュータスクの優先順位を上げる ✅ レビュー時間を定常的に確保する(毎日xx時〜xx時をレビューに当てるなど) ✅ 他のタスクとの時間配分を見直す |
レビュー時
レビュイー
レビュイーは、指摘された事項をただ修正するマシーンになるのではなく、レビュープロセス全体を自己成長の機会と捉えることが重要です。
レビューのあらゆるステップに学びの機会が存在しています。
ステップ | やること | 解説 | 関連する学習理論 | 具体例 |
---|---|---|---|---|
妥当性検証(自己レビュー) | 記憶を呼び覚ます | 普段能動的に学んでいることや過去の指摘を意識的に思いだすことで、想起学習を促進する | 想起学習 | ✅ 普段学んでいることや自身が過去に受けた指摘を思い出す |
思い出した事項が漏れなくコードに反映されているか確認することで、想起学習の効果を高める | 想起学習 | ✅ 普段学んでいることや過去の指摘が漏れなくコードに反映されていることを確認する | ||
間違いを探すのではなく、妥当性を証明する | 妥当である理由を自身の言葉で説明しようと意識的に努力することで、精緻化を促進し、根拠に基づいた深い理解と言語化能力を獲得する | 精緻化 | ✅ 「なぜこのテストケースで全ての動作が保証できるのか?」「なぜこのコードは可読性が高いのか?」「なぜこの実装でパフォーマンスが問題ないのか?」 など、根拠を明確に言語化できるまで自問自答を繰り返す | |
レビュアーの視点で確認する | 自身の視点とは異なる視点で確認することで、インターリービングの効果を間接的に得る | インターリービング | ✅ 自身がレビュアーのAさんであると想像し、Aさんが指摘しそうな点を予測する ✅ エディタ上でコード全体を確認するだけでなく、Files changedタブ(レビュアーと同じ視点)で差分を確認することで、レビュアーが抱くであろう疑問を先読みする ✅️ 先読みした指摘や質問に対して、事前にコードを修正、もしくは、PRコメントで説明を付け加える |
|
レビュー依頼 | 背景や目的を言語化する | 目的や背景を相手に伝わるように言語化することで、精緻化を促進する | 精緻化 | ✅ PRやIssueの説明欄に、変更の目的、背景、実装で工夫した点、レビューして欲しい観点などを具体的に記述する ✅ 口頭でのレビュー依頼の場合も、上記の点を意識してレビュアーに説明する |
コメント確認 | 指摘や質問の意図を理解する | 指摘や質問を自身の既存の知識と関連付け、意図を理解しようとすることで、精緻化を促進する | 精緻化 | ✅ レビューコメントに対して、なぜレビュアーはそのように指摘したのか、背景や意図を深掘りして理解する ✅️ 自身の知識や経験不足により理解できない点があった場合、能動的に調べ、自身の言葉で説明できるレベルまで理解しようと試みる |
コメント対応 | 質問や指摘コメントに対して回答する | 質問や指摘コメントに対して、自身の意図や疑問点などを言語化してレビュアーに伝えることで、精緻化を促進する | 精緻化 | ✅ 自身の意図をレビュアーに伝わるように説明する ✅ 必要に応じて、代替案を検討し、最適な案を示す ✅ レビュアーの意図が不明な場合は遠慮なく質問し、認識の齟齬をなくす |
コードを修正する | 理解した内容を具体的にコードとして反映することで、精緻化を促進する | 精緻化 | ✅ ただ言われた通りに修正するのではなく、よりよい修正方法がないか考える ✅ なぜこの修正が妥当なのか、自身の言葉で説明してみる |
レビュアー
レビュアーは、コードレビューを通じてレビュイーの成長を支援するだけでなく、自身も学び、成長する機会と捉えることが重要です。
レビュアーにとっても、レビューのあらゆるステップに学びの機会が存在しています。
ステップ | やること | 解説 | 関連する学習理論 | 具体例 |
---|---|---|---|---|
参加 | 能動的、積極的にレビューに参加する | 学習機会を最大限に増やす | 全て | ✅ 自身が担当可能なレビューに積極的に参加する ✅ 担当範囲外でも学びたい技術やドメイン、ロールモデルとなるエンジニアのレビューに積極的に参加する |
概要把握 | 変更の全体像を掴む | 精緻化の材料となる多様な情報を集めることで、精緻化の効果を高める | 精緻化 | ✅ PRやIssueの内容を確認し、背景、目的、設計思想、実装方針、テスト方針などを理解する ✅ 必要に応じて、関連ドキュメントを参照し、変更内容の周辺知識を補強する ✅ 必要に応じて、類似コードのレビュー履歴を確認し、過去の議論や指摘事項を参考にする |
不明点を解消する | 不明点を理解しようとすることで、精緻化を促進する | 精緻化 | ✅ 変更の意図や背景が不明な場合は、レビュイーに遠慮なく質問し、認識をあわせる ✅ 必要に応じて、周辺コードを含めて確認することで、差分だけでは見えにくいコード全体の文脈を把握する ✅ 不明点が技術的な内容である場合、能動的に調べ、自身の言葉で説明できるレベルまで理解しようと試みる ✅ 不明点がアーキテクチャや設計思想に関わる内容の場合、設計ドキュメントやアーキテクチャ図などを参照し、全体像のマクロ視点とPRのミクロ視点の双方から理解しようと試みる |
|
妥当性検証(レビュー) | 記憶を呼び覚ます | 普段能動的に学んでいることや過去の指摘を意識的に思いだすことで、想起学習を促進する | 想起学習 | ✅ 普段学んでいることや過去の指摘(特に自身が指摘できなかったが、他のレビュアーが指摘できた指摘)を思い出す |
思い出した事項が漏れなくコードに反映されているか確認することで、想起学習の効果を高める | 想起学習 | ✅ 普段学んでいることや過去の指摘が漏れなくコードに反映されていることを確認する | ||
多様な観点で確認する | 観点を意識的に切り替えながら検証することで、インターリービングを促進する | インターリービング | ✅ 仕様との適合性、可読性、パフォーマンス、セキュリティ、UXなど、様々な観点を切り替えながら検証する | |
間違いを探すのではなく、妥当性を証明する | 妥当である理由を自身の言葉で説明しようと意識的に努力することで、精緻化を促進し、根拠に基づいた深い理解と言語化能力を獲得する | 精緻化 | ✅ 「なぜこのテストケースで全ての動作が保証できるのか?」「なぜこのコードは可読性が高いのか?」「なぜこの実装でパフォーマンスが問題ないのか?」 など、根拠を明確に言語化できるまで自問自答を繰り返す | |
コメント | 具体的な根拠と共に改善案を提示する | 相手に伝わるように改善点を具体的に言語化することで、精緻化を促進する | 精緻化 | ✅ 改善が必要な理由、背景などを自身の言葉で明確、丁寧に伝える ✅ 当該コードに適用できる手法を複数提示する ✅ 複数の手法の中から最適と思われるものを選択し、その理由を論理的に説明する ✅ 可能な場合は、コードの修正イメージをサジェストする |
レビュー後
レビュイー/レビュアー共通
レビュー後も継続的に学びを深め、知識を定着させることが重要です。
ステップ | やること | 解説 | 関連する学習理論 | 具体例 |
---|---|---|---|---|
事後学習 | 徹底的に理解する | レビュー中に新しく学んだこと、完全に理解しきれなかった点を徹底的に掘り下げることで、精緻化を促進する | 精緻化 | ✅️ レビューコメントや議論の内容をノートやメモにまとめる ✅️ 不明点を解消するために、関連ドキュメントや書籍を読み返す、同僚に質問する ✅️ 学んだ内容を自分なりの言葉で説明できるように練習する ✅️ 実際にコードを書いて、学んだ知識を試してみる |
既存知識をアップデートする | 新しく得た情報を自身の既存知識に統合することで、精緻化を促進し、知識の精度を向上させる | 精緻化 | ✅️ 新しい情報を自身の既存知識に整合性がとれるように取り込むことで、各知識の理解を深める ✅️ 新しい情報と自身の既存知識との間に矛盾点がある場合、その矛盾を解消するように既存知識を補正する |
|
レビューを振り返る | レビューをやりっ放しにするのではなく、振り返ることで精緻化を促進する | 精緻化 | ✅ 自己レビューで気付けなかった点、自身はできなかったが他のレビュアーが指摘できた点を認識する ✅️ 気付けなかった原因を深堀りし、具体的なアクションに変換する |
|
定着 | 定期的に思い出す | 得た学びを忘却しないために、定期的に知識を呼び起こし、長期記憶として定着させる | 想起学習 | ✅️ 定期的にメモ、ドキュメント、書籍を見返す ✅️ 類似のコードを書くタスクが発生した際に、過去の学びを意識的に思い出し、適用する |
思い出す間隔を意図的に調整する | 能動的に思い出そうとする間隔を少しずつ延ばしていくことで、分散学習の効果を得る | 分散学習 | ✅️ 翌日、1週間後、3週間後のように少しずつ延ばす(忘れかけた頃に思い出すのが効果的) ✅️ エビングハウスの忘却曲線などを参考に、自身にとっての最適な間隔を見つける |
認知心理学の自動化による時間の節約効果
これらを実践すると、とてつもなく時間がかかるのでは?と思われるかもしれません。
当然、最初は時間がかかります。
しかしながら、人間には自動化という仕組みが備わっています。
認知心理学における自動化とは、経験を通じて、ある行動や思考が意識的な努力なしに、無意識に瞬時に行えるようになる現象のことです。
意識的に考えるのは時間がかかりますが、無意識に考えられるようになると、短い時間で大量の思考を処理できるようになります。
自動化の例
以下が自動化の例です。
前者については、実体験として経験された方も多いのではないでしょうか。
- 子供の頃、初めて自転車に乗った際はバランスを取ることに必死だったが、慣れるとそんなことはまったく意識せずに乗れるようになった
- 熟練したプログラマーは、長年の経験により、多くのコードパターンやアンチパターンを無意識のうちに認識し、瞬時に判断することができる
自動化の段階
自動化には、以下の3つの段階があります。
- 意識的に努力して考える段階
- 徐々に慣れてきて、意識的な努力が減る段階
- 無意識に考えられる段階
これをコードレビューに当てはめると、例えば以下のようになります。
- コードの隅々まで意識的にチェックする必要があり、どうしても時間がかかる
- 経験を積むにつれて、チェックすべき箇所や問題点のパターンが自然と頭に入ってくる
- 無意識のうちにコードの品質や問題点を一瞬で見抜けることが増える
- さらに、認知負荷が軽減されることで、より高度な設計や潜在的なリスクの評価といった思考に時間を割けるようになってくる
このように自動化が進むことで、徐々に時間の問題は解決していきます。
自動化が進んだ状態
ファーストペンギンからセカンドペンギンへ
コードレビューを学習機会と捉えるパラダイムシフトは、以下のようにチーム全体に広がることで、その効果を最大化することができます。
- ファーストペンギン(先駆者)が現れ、
- セカンドペンギン(支持者)がそれを支持し、
- チーム全体の成長が加速する
ファーストペンギンは、たとえ周囲が変化に消極的であったとしても、先駆者として勇気を振り絞り、自身のコードレビューに対する姿勢を積極的に変えていきます。
例えば、レビューで積極的に質問したり、学んだことを共有したりすることで、周りのメンバーに新しい視点を提供します。
セカンドペンギンの重要な役割は、ファーストペンギンの考え方に共感し、それを支持する行動を示すことです。
彼らが同様に学習を重視する姿勢を見せることで、その考えがチーム全体の共通認識となり、チーム全体に変化を広げていきます。
こうして、コードレビューを学習機会と捉える考え方がチーム全体に行き渡ると、コードレビューは単なる作業からチーム全体の成長を加速させる強力なツールに生まれ変わります。
まとめ
コードレビューのさまざまな問題の解決には時間がかかります。
一方で、自身の向き合い方を「品質ゲート」から「学習機会」に変えることは、今この瞬間からでもできます。
さらに、コードレビューに適切に向き合うことで、脆弱な精神論ではなく科学に基づき、自身やチームの成長を力強く前進させることができます。
実際、私はコードレビューへの向き合い方を変えてから確実にスキルが向上したと実感しています。
ぜひ、みなさんもあらためてコードレビューへの向き合い方を考えてみてください。
ココナラでは、積極的にエンジニアのみなさんを採用しています。
現在、フルサイクルエンジニアを絶賛募集中です。
カジュアル面談で、ココナラの魅力やキャリアパスについて詳しく聞いてみませんか?
採用情報はこちら。
その他のエンジニアも大募集中です。
カジュアル面談希望の方はこちら。
Discussion