コード分析とは
継続してアプリケーションを開発していく中では、コードの保守性も重要になってきます。特にチームの開発では、メンバーのスキルにバラつきがあるため、中にはあまり良いとは言えない品質のコードが書かれてしまうこともあります。
こういった問題に対処するための方法にはいくつかあります。有識者、他のメンバーによるレビューを通じて直していくという方法もその一つです。しかし、せっかくの貴重なレビューの場を、ある意味些末な「コーディングルール」というようなものの指摘に費やすのは、非常にもったいないことです。レビューでは機能要件に沿った内容やコードの設計、構造といった、「人でしかできない」ことに注力したいものです。
そこで、「コーディングルール」のような決まりきったものについては、ツールを使って検出し、直していきましょう。そのためのツールの一つが、今回紹介するVisual Studioに搭載された「コード分析」機能です。
コード分析はコードをビルドしてできたアセンブリの中間コード(IL)を解析することで、コードがある一定の「ガイドライン」に沿っているかチェックします(図1)。また、指摘箇所とともにその問題の修正方法のヒントも得ることができます。
必要環境の準備
コード分析の実行にはVisual Studioが必要です。「Visual Studio Community」などの製品を、はじめにインストールしておいてください。
Visual Studio Communityは個人開発者であるか、企業内であればOSS開発を行うなど一定の条件を満たしていれば、無償で使用できます。企業内で使用する際の条件については、上記ページに簡単にまとめられていますので、ライセンス違反しないように内容を確認してからインストールしてください。
本記事ではこのVisual Studio Communityを、以降の説明に使っていきます。
サンプルコード
本記事のサンプルコードは、ページ上部のリンクからダウンロードする他に、GitHubでも公開しています。
このリポジトリをGitでクローンしてコミットをさかのぼることで、本記事の各フェーズのコード分析実行結果を手元で再現できます。記事と併せて、コード分析機能の理解に役立ててください。
コード分析の実行方法
それでは、実際にコード分析を行う方法について見ていきましょう。
コード分析対象プロジェクト作成
コード分析を行う対象となるプロジェクトを作成します。サンプルでは「Visual C#」→「クラス ライブラリ」プロジェクトを作成しています。
次に作成したプロジェクト内に含まれるClass1.csファイルを、次のように編集します(リスト1)。
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace codeAnalysis { public class someClass { public void doSomething(int count, int i) { var newCount = countUp(count); } private int countUp(int count) { return count + 1; } private static void UnUseMethod() { } } }
コード分析の設定
次にコード分析の設定を行います。
まずプロジェクトのプロパティ ページを開き、「コード分析」タブを選択します。そして、「ルールセット」→「この規則セットを実行」を、既定の"Microsoft マネージ推奨規則"から"Microsoft のすべての規則"に変更して保存します(図2)。
この「ルール セット(規則セット)」とは、どのようなチェックを行うかを指定する「ルール」を管理するものです。"Microsoft のすべての規則"は最も厳しいルールセットで、その名のとおりMicrosoftによって提供されるすべてのチェックが行われます。
実際に開発で利用する際は、そのシステムに合わせてルールをカスタマイズするのが一般的です。その方法については、後ほど紹介します。
コード分析の実行
準備ができたところで、実際にコード分析を行ってみましょう。
コード分析を行うには、Visual Studioの「分析」メニュー→「ソリューションでコード分析を実行」を選択します(図3)。また、メニュー項目に表示されているように、Alt+F11というショートカットキーでも実行できます。
コード分析の実行が終わると、「コード分析」ウィンドウが表示され、コード分析によって見つかった警告事項の一覧が表示されます(図4)。
これらの警告事項をクリックするとことで、コード内の該当箇所にジャンプすることができ、さらにその修正のヒントが表示されます(図5)。
コード分析結果への対処
コード分析を行い、コードの問題点が明らかになったところで、今度はその修正を行っていきましょう。
指摘事項の修正
コード分析結果では簡単なヒントは表示されますが、その指摘の詳細は分かりません。詳細を知るには、分析結果内の"CA9999"といったリンクをクリックしましょう。MSDNライブラリ内の該当ページがWebブラウザで表示されます(図6)。
ヒントとこの詳細内容を元に、コードを実際に修正していきます。例えば、「CA1709: 識別子では、大文字と小文字が正しく区別されなければなりません」というルールで、名前空間名、クラス名、そしてメソッド名の3か所が指摘されていますので、詳細ページに表示された通り、「大文字始まりの単語区切り大文字」という、いわゆる「PascalCase」な名前に修正します(リスト2)。
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace CodeAnalysis // 名前空間名の修正 { public class SomeClass // クラス名の修正 { public void DoSomething(int count, int i) // メソッド名の修正 { var newCount = countUp(count); } private int countUp(int count) { return count + 1; } private static void UnUseMethod() { } } }
修正したら再びコード分析を実行し、CA1709の指摘がなくなったことを確認しましょう。
コード分析結果の抑制
コード分析によって指摘された内容の中には、そのシステムの状況によっては対処する必要がないものも含まれます。こういった警告については、「抑制」することで次回以降のコード分析実行時に、その箇所が無視されるようになります。
抑制にはソース内で直接指定する方法と、「抑制ファイル」というファイルにまとめて記述する方法の2種類があります。どちらも、ツールで自動的に行ってくれますので心配はいりません。順番にやり方を見ていきましょう。
ソース内で指定する方法
まずはソース内での抑制です。例えばCA1704として指摘されている警告は「メソッドのパラメータ名をiではなくもっと意味のある名前に変更しろ」というものですが、場合によってはiという名前がふさわしいケースもあります。今回はそのケースに該当したとみなして抑制してみましょう。
「コード分析」ウィンドウでCA1704を選択すると、項目の右下に「操作」というリンクが表示されるので、「メッセージの非表示」→「ソース内」を選択します(図7)。すると、該当箇所にSystem.Diagnostics.SuppressMessage属性が付けられ、抑制するルールとその対象となるモノの名前等(今回はパラメータ名i)が設定されます。
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "i") public void DoSomething(int count, int i) { var newCount = countUp(count); }
抑制ファイルで指定する方法
次に抑制ファイル内での抑制です。例えばCA2210として指摘されている警告は「アセンブリに厳密名をつけるために署名しろ」という内容ですが、小さな範囲で閉じたシステムでは、そこまでしなくてもよいケースもあります。今回はそのケースに該当したとみなして抑制してみましょう。
方法はソース内と同様で、「操作」→「抑制ファイル内」と選択するだけです(図8)。すると、プロジェクトにGlobalSuppressions.csという名前の「抑制ファイル」が作成され、ソース内と同じようにSuppressMessage属性が追加されます。
// このファイルは、このプロジェクトに適用される SuppressMessage //属性を保持するために、コード分析によって使用されます。 // プロジェクト レベルの抑制には、ターゲットがないものと、特定のターゲット //が指定され、名前空間、型、メンバーなどをスコープとするものがあります。 // // このファイルに抑制を追加するには、[コード分析] の結果でメッセージを // 右クリックし、[メッセージの非表示] をポイントして、 // [抑制ファイル内] をクリックします。 // このファイルに手動で抑制を追加する必要はありません。 [assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA2210:AssembliesShouldHaveValidStrongNames")]
抑制した状態でコード分析を行い、指摘されなくなっていることを確認しましょう。なお、抑制を解除するには、該当するSuppressMessage属性を削除してください。
ルールセットのカスタマイズ
先述のとおり、実際の開発ではVisual Studioに標準で搭載された分析ルールは厳しい、もしくはやさし過ぎてあまり有用でないことがあります。そこで、分析ルールをカスタマイズし、開発の状況にふさわしい状態でコード分析を行うのがよいでしょう。
分析ルールをカスタマイズするには、先述のとおり「ルールセット」を変更します。まず、プロジェクトのプロパティページを開き、コード分析を選択します。次に「ルール セット」→「この規則セットを実行」の隣の「開く」ボタンをクリックし、ルールセットの編集画面を表示します(図9)。このとき、最も厳しいルールセットである「Microsoft のすべての規則」を元にして、不要なルールを除外していくようにするのがよいでしょう。
ルールセットを開いたら、不要なルールのチェックを外していきましょう。今回は「CA1014 アセンブリに CLSCompliantAttribute を設定します」を除外してみます(図10)。
ルールセットのカスタマイズが終わったら、ファイルを保存します。ただ、元となる「Microsoft のすべての規則(AllRules.ruleset)」ファイルは読み取り専用のため、新たに別名で保存することになります。今回はプロジェクトフォルダー内に「MyRules.ruleset」ファイルとして保存しましょう。
その後、プロジェクトのプロパティページから、今ほど保存したルールセットファイルを「参照」で開きます。そして、再びコード分析を実行すると、先ほど除外したCA1014について指摘されなくなることが確認できます(図11)。
なお、カスタマイズしたルールセットには、プロパティウィンドウで「名前」を編集し、分かりやすい名前を付けるとよいでしょう。
チームでコード分析活用
最後に、チームでコード分析を活用する際のテクニックを2つ紹介しておきます。
ビルド時に実行する
せっかくのコード分析ですが、手動で実行するだけだとメンバーによってはコード分析を行ってくれないこともあるでしょうし、何かの手違いで実行されないこともあるでしょう。そんなときは、ビルド時に一緒にコード分析を行わせるようにもできます。
プロジェクトのプロパティページを開き、「ビルドに対するコード分析の有効化」にチェックを入れて保存します(図12)。こうするだけで、ビルド時に自動的にコード分析も行われるようになります。
ただし、コード分析はそれなりに時間もかかるため、ビルドをするごとに毎回実行すると、快適な開発のリズムを崩す恐れもあり、その使用には注意が必要です。
それでもビルド時の自動実行には魅力があります。開発環境ではなくCIツールによる継続ビルドなどのタイミングでコード分析を行うだけでも効果はあるでしょう。そのためには、MSBuildでビルドする際、RunCodeAnalysisプロパティにtrueを設定して実行すればよいです(図13)。
msbuild /t:Rebuild /p:RunCodeAnalysis=true CodeAnalysisDemo.sln
NuGetを使ったルールセットの共有
チーム用にカスタマイズしたルールセットファイルを用意しても、そのルールセットを使ってもらうためには、それぞれのプロジェクトのプロパティで設定する必要があります。また、ルールセットを改版したら、そのたびに新しいルールセットファイルを配布する必要もあり、手間がかかります。
そんなときは、NuGetを使ってカスタマイズしたルールセットファイルの配布とプロジェクトへの設定を行うのがおすすめです。開発しているシステム用のプロジェクト テンプレートも用意して、そのテンプレートでルールセットのNuGetパッケージを使うようにしておけば、設定の漏れもありません。
そして、ルールを改版したときは、新たなバージョンのNuGetパッケージを配置すれば、あとは各メンバーにNuGetパッケージをアップデートしてもらうだけで配布が完了します。また、NuGetのコマンドラインツールを使えば、一括でアップデートすることもできるでしょう。
紙面の都合上、詳しくはその方法を紹介できませんが、次のGitHubリポジトリで公開しているので、興味があれば参照して試してみてください。
まとめ
コード分析機能を使うことで、ある程度のコードの不備は機械的に検出することができることが分かったと思います。今回はガイドラインに沿っているかどうかをチェックする機能のみ紹介しましたが、Visual Studioに用意された分析機能は他にも「パフォーマンス計測」「プロファイラー(メモリ使用率などの計測)」「コードメトリクス計算(コードの「分かりやすさ」などの計算)」、といったものがあります。
どれもうまく使えばコードの品質を向上するのに役立つ機能です。また、上位エディションのVisual Studioは自動化テストのタイミングでコードのカバレッジを測定することもできます。
人間がより生産的な作業に注力するためにも、こういった機械的なチェックを行うツールをぜひ活用してみてください。