最初に
本記事の内容は、コードレビューの基本を押さえつつ、Riderを使用してコードレビューを少しでも楽にするためのTipsを記載したものとなります。この記事が、コードレビューをより効率的に行い、コード品質を向上させるための一助となれば幸いです。
本記事の対象者は以下の通りです。
- コードレビュー入門初心者
- Riderを使ったコードレビューを試してみたい人
コードレビューの考え方
コードレビューはなぜ必要なのでしょうか?
他の人に自分のコードを見てもらうことで得られるメリットを考えてみましょう。
1. バグの早期発見と、コード品質の向上
コードレビューをすることで、自分では気付けなかった潜在的なバグや、ケアレスミスなどの早期発見に繋がります。これにより、後々のトラブルや修正コストを大幅に削減できますし、コード品質を早い段階で向上できるため、リファクタリングのコストを下げることができます。
2. コードの一貫性と標準化
プロジェクト内のコードには一貫性を持たせましょう。無秩序なコードは複雑になり、可読性が失われてしまいます。それを避けるために、コーディングルールを設けているプロジェクトも多いと思います。
コードレビューを行うことで、チーム全体が共通ルールやベストプラクティスを守るように促すことが可能です。
可能な限り、命名規則にも一貫性を持たせましょう。プロジェクト内での共通用語や、コード上での名前の組み方を予め決めておくと、共同開発がスムーズになります。以下は一例です。
- 非同期メソッドはAsyncをつける(例:ChangeSceneAsync)
- イベントハンドラではOnプレフィックスを用いる(例:OnSucceeded)
3. チームのスキル向上
コードレビューは、チーム内のエンジニア同士がお互いに学び合う良い機会にもなります。異なる視点やアプローチで実装されたコードをレビューすることで、良い刺激を受けることができます。レビューされる側も、人に見られることを前提としてコードを書く意識をもつため、より良い実装がないかを考えるトレーニングとなります。
4. 実装箇所の手法共有と、コミュニケーションの促進
自分の書いたコードが誰にもチェックされずそのまま使用となる場合、コードの実装を的確に追える人が、コードの実装者しかいない状態になります。緊急度の高いバグ修正が必要になった時、担当者が不在の際は、他のエンジニアが実装箇所を確認するケースがほとんどです。その場合、PR履歴やコード変更履歴を0から追ってコードの確認をする必要になり、通常よりも修正に対して時間がかかってしまいます。
しかし、もしコードレビューをチームで実施している場合は、実装者以外でコードを認識している人は、少なくとも他に一人以上いることとなります。これはつまり、実装担当者が不在の場合でも、他のメンバーがフォローできる体制になるということです。属人化を避けるためにもコードレビューの文化を取り入れることはおすすめです。
上記のような状況に備えて、PRに関しても実装詳細をできるだけ記述しておくことをおすすめします。少なくともタイトルと変更点、影響範囲の3つが記述されていれば、かなり状況が把握しやすくなるでしょう。
コードレビュー時のレビューポイント
では、実際にコードレビューのポイントを押さえていきましょう。IDEの機能を駆使したりプラグインを使用すれば、コードレビューにかかるコストを半分以下におさえることができます。今回はタイトル通り、Riderを使用した場合でのコードレビュー手法について解説するため、前半ではRiderの便利な機能とプラグインを紹介し、後半では、人間がレビューする箇所のポイントを紹介していきます。
Riderでのコードレビュー
今では、RiderはUnity開発にかかせないIDEとなっています。便利な機能も山ほどあり、それをひとつひとつ理解し、把握しようとするとキリがありません。
今回は機能の中でも、特にコードレビューに役立つものをピックアップして紹介させて頂きます。
Rider上でのコーディングルール設定
実際にプロジェクト立ち上げ~序盤においては、コーディングを行う前に、そのプロジェクトでのコーディングルールを設定することになるでしょう。その際に、コーディングルールをIDEに反映させることで、コーディング時のコストを大幅に減らすことが可能です。
Windows及びLinuxからは**File > Settings > Editor > Code Style > C#
**
MacOSからは**JetBrains Rider > Settings or Preferences > Editor > Code Style > C#
**
でコーディングスタイルの設定を行うことができます。
preview画面がついているため、それぞれの設定の影響を確認しながら調整していくことができます。
チームでのコーディング規約を設定し、共有するのであれば以下の記事が参考になります。
コーディング規約の設定を行うのであれば、1つずつ設定を見ていくのが良いでしょう。
「名称が英語だから設定しにくい…」と感じる場合は、RiderのUIや設定を日本語化するプラグインの追加をおすすめします。
コードの自動解析
Riderでは、コード解析機能を通じて、コード上のパフォーマンス的に問題のあるコードの検出や、名前・コメントなどのスペルチェックを自動的に検出してくれます。
例えば、以下のような場合、Riderから該当箇所への下線と共に提案が行われます。
-
コード内でのパフォーマンスが懸念される箇所
- Updateメソッド内で
GetComponent
を使用 - ボクシング(値型を参照型に変換)が発生
- 短時間での大量オブジェクト生成(例:毎秒1000個、
new GameObject()
を行う)
- Updateメソッド内で
-
誤字、脱字が見受けられる箇所
-
SendMessage
をSenMessage
と書いた場合 - Riderの辞書に登録されていない単語を使用した場合(プロジェクト固有の名詞を使用する時に発生することが多いので、その際にはRiderの辞書に登録を行う)
-
-
コード内のクラス名や変数名などが、コーディングルールに従っていない時
- Classなどのアッパーキャメルケースの際に、小文字から開始していた場合
-
static
を使用する変数にs_という接頭辞をつけるルールがあるのに、それを守っていない変数名を使用していた場合
-
より良いコードに置き換えられる時
-
if
文を多用している箇所をswitchステートメントで置き換えられる場合 -
if
文ネストが深い箇所をinvert if
を行い、早期リターン文へ変換できる場合 - 冗長な処理をLINQ文でシンプルにできる場合
-
- 使用されていないusing、変数、関数などがある場合
コードレビューをしていく中で、実際に下線されている箇所と出くわしたら一度手を止めて、実際に自分の手元でどのように修正できるのかクイックFixという機能を活用してみましょう。
クイックFixを適用する
この機能はエラーや警告が出た箇所を、Rider側から提案されている内容に合わせて即時に修正できる機能となります。
下線、または波線が引かれたコードの左側に、以下のようなアイコンが表示されます。
エラー:必要なファイルがimport
されていなかったり、宣言がされていない変数を使用した場合などに表示されます。
警告、提案:GetComponent()
を行っている箇所をStart
又はAwake
へ移行できそうなときや、スペルミスと思わしき名前を発見してリネームの提案ができそうな場合に表示されます。
提案:ネーム、アクセス修飾子の変更を行いたいときに使用します。
アイコンをクリックすると、コード解析によって検出されたコードへの提案を適用するか選択できるコンテキストメニューが開かれます。
例えば上記の画像では、
- アクセス修飾子の付け忘れをしているため、privateを付け足すか
- このメソッドはどこからも使用されていないため、削除する
を提案されています。
Context Actionsという機能にショートカットキーを割り当てると、クイックFixも素早く実行できるようになるため、おすすめです。(またはキーマップの種類によっては既に設定されています)
Reformat and Cleanupの活用
コードレビュー相手がもし、まだ入ったばかりの新人さんであれば、コードレビュー時に変更箇所をReformatやCleanupを使用して、コーディング規約に沿っているか確認するのも良いでしょう。
それぞれ、以下のような機能を持ちます。
Reformat の機能
- インデントの整備
- 空白の統一(例えば、スペースとタブの統一)
- コードブロックの整形
- 波括弧の位置
- 改行の統一
- 空行の追加や削除
Clean up の機能
- ‘Reformat’の全ての機能
- 使用されていないusingディレクティブの削除
- コード解析に基づく提案の適用
- 未使用の変数の削除
- 簡略化できるコードの修正
- 変数やメソッドの名前変更(命名規則に基づく)
- コードスタイルの強制適用
- プロパティのアクセサーの位置や順序の統一
- アクセス修飾子の付け足し
今回の記事の趣旨とはずれてしまいますが、コードを書く側としてはSave時のAuto ”Reformat and Cleanup”を設定することをお勧めします。
CognitiveComplexityの導入
Cognitive Complexityは、コードの理解難易度を測定するためのメトリクスであり、G. Ann Campbellによって提案されました。Rider上でこのプラグインを導入することで、このメトリクスをリアルタイムで計算し、コードの複雑度を可視化することができます。
CognitiveComplexity - IntelliJ IDEs Plugin | Marketplace
上記のプラグイン紹介ページにもあるように、コードの複雑度は数値化され、4段階に分けられて警告が表示されます。
以下のような場合に、コードの複雑さが計算され、複雑度が増加します。
- ループや条件分岐の増加
- ネストの追加
- ラムダの多用や複雑なLINQ文の追加
複雑さを表す数値が100%前後の状態になっている場合は、リファクタリングの提案をおすすめします。
例えば、以下のようなリファクタリングが効果的です。
- 別メソッドへ分割
- 早期リターン
- 長い式を説明する変数を用意し、そちらに式の結果を格納
人が読む際に注力すべきポイント
コードレビューをする際には、Riderの便利な機能を活用して、機械的なチェックで済むような箇所はRiderに任せてしまいましょう。次は、レビュアーとして注力すべきポイントを考えていきます。
以下に、具体的なレビュー時の観点を紹介します。
コードがシンプルか、大きさが適切か
コードレビューを行う際、まずコードがシンプル且つ、クラスやメソッドが適切な大きさであるかを確認します。シンプルなコードは、他の開発者にとっても理解しやすく、保守も容易です。先述したCognitive Complexityを利用して、複雑さを可視化し、コードをシンプルにできる余地があるか確認してみましょう。複雑なロジックが避けられない場合でも、Riderのリファクタリングツールを活用して、コードをよりシンプルにできないか検討しましょう。特に、冗長な条件分岐やネストされたロジックを見つけた際には、Riderが提案する改善案を参考に、コードの透明性と明瞭性を高めることができます。
簡単には解決できない複雑性を伴ってしまう場合は、処理の妥当性とタスクの期日を鑑みて、そのコードで行くかどうか、決めるのが良いと思います。
出力(戻り値)のチェック
コードレビュー時には、メソッドやプロパティが返す出力のチェックも重要となります。Riderの静的解析機能を活用して、出力の妥当性や信頼性を確認しましょう。例えば、メソッドが必要な情報だけを返しているかどうかはRider側でも確認ができますし、クイックFixによる修正も可能です(例:リスト列挙用の読み取り専用List<int>
→ IList<int>
, or IEnumerable<int>
)。
また、不必要なデータを出力の中に含んでいないかのチェックも行いましょう。余分な出力は使用する側の考えるコストを増加させてしまいます。
秘匿性を持っているか
コードレビューでは、クラスやプロパティ、メンバ変数の公開範囲についても確認しましょう。コードが適切にモジュール化され、必要な情報だけが外部に公開されている状態が望ましいです。Riderのアクセス修飾子に関する警告機能も利用しつつ、もし外部に公開する必要がないものまでpublicになっていそうであれば、コードレビュー上でコメントして、公開している意図を確認することをおすすめします。
割れ窓理論の適用
小さな問題を見つけたらそのまま放置せず、実装者に確認を取りましょう。たとえば、インデントのズレや無駄な空行など、「これくらいならいいや」という気持ちで見逃してしまうと、そのコードはそのまま負債となります。塵も積もれば山となるように、小さな問題もあちらこちらに増えていけば、コード全体の品質に悪影響を及ぼしてしまいます。
割れ窓理論の観点からも、レビューの段階でどんな些細な問題でも積極的に修正を提案し、コード全体の品質維持に努めましょう。こまめな修繕は、長期的な目で見ると、プロジェクトを長続きさせる重要な要素となります。
リファクタリングの重要性
コードは建物のように日々古くなっていくものです。長期運用を考えているプロジェクトであれば、定期的なリファクタリングは不可欠です。たとえば、複雑化してしまったメソッドを簡潔にすることで、後々のバグ発見や修正が容易になります。コードレビュー時に、実装箇所と絡む古いコードがある場合は、古いコードも合わせてリファクタのお願いをしても良いと思います。
リファクタリングをしていくことで、コードの質を維持し、将来的な保守コストも低減できます。
また、リファクタリング作業を行うことで、修正した場合の該当箇所の影響範囲を確認する必要もあるため、周辺実装に対する理解を深めることもできます。時間に余裕があるときは、少しずつでもリファクタリングの提案をしてみると良いかもしれません。
RiderでのGitHub連携とPRレビュー機能
RiderはGitHubとの連携を、スムーズに行えるような機能を兼ね備えています。これにより、開発者はIDEから離れることなく、GitHub上でのクローン、コミット、PRレビューなどの作業を効率的に行うことができます。ここでは、RiderでのGitHub連携と、それを活用したコードレビューやPR(プルリクエスト)管理の機能について紹介します。
GitHubとの連携
Riderを使用すると、GitHubリポジトリを簡単にクローンしたり、プッシュ、プルなどの基本的な操作を行うことができます。GitHubアカウントをRiderに接続することで、以下のような機能が利用可能になります:
- PRの作成と確認: Rider上で直接プルリクエストを作成し、変更内容を確認できます。これにより、レビューやマージのプロセスをIDEから行うことができます。
- ブランチの管理: GitHub上のブランチをRider内で簡単に切り替えたり、作成・削除したりできます。これにより、開発フローをスムーズに進めることが可能です。
また、もしGitHub Copilotを契約しているのであれば、プラグインからGitHub Copilotをインストールし、そこからGitHubアカウントを紐づけてRider上で使用することも可能です。
PRレビュー機能
RiderのPRレビュー機能を活用すると、GitHub上のPRをIDE内で直接確認し、コメントを追加したり、レビュー済みのファイルにチェックマークを付けることができます。
- コードコメント: PR内の変更されたコード行にRider上から直接コメントを追加できます。これにより、コードの修正点や改善案、質問などをRider上から即座に伝えることができます。
- レビュー済みマークの設定: PR内の変更ファイルを確認後、レビュー済みとしてチェックマークを付けることができ、現時点で、どのファイルがレビュー済みかを一目で把握できます。
- ディスカッションの管理: 追加したコメントに対するディスカッションもRider上で行うことができ、PRのレビューがより効率的に進められます。
まとめ
コードレビューは、ソフトウェア開発において品質を保ち、チーム全体のスキルを向上させるための重要なプロセスです。本記事では、Riderを活用してコードレビューを効率化するための方法を紹介しました。Riderのコーディングルール設定や自動解析機能、クイックFix機能を駆使することで、レビュアーとしての負担を軽減し、フォーカスしたいポイントを絞ることが可能です。
特に、RiderのCognitive Complexityのようなプラグインを利用することで、コードの複雑度を数値で把握することもできますので、それを元にリファクタリングの提案などもしてみてください。これらのツールをうまく活用することで、プロジェクト全体のコード品質が向上し、より保守性を高くすることができます。
最後に、コードレビューは単なるバグの発見だけでなく、チーム内のコミュニケーションを促進し、知識を共有する重要な機会です。Riderの強力な機能をフル活用し、効率的で質の高いコードレビューを実現していきましょう。