StyleCop による静的コード分析の実装
理解できないコードに直面することはよくありますか。多くの場合、書式に一貫性がないこと、無意味なコメントがあること、名前に規則性がないことがコードを読みにくくします。こうした一貫性の欠如はささいな問題として見過ごされがちですが、コードの全体的な保守性に大きな違いを生じさせることがあります。
StyleCop は、ソース コードのスタイルと書式の一貫性を維持する優れたツールです。Visual Studio コード分析と同様、StyleCop は静的コード分析を実行します。ただし、Visual Studio コード分析とは異なり、マネージ コードではなくソース コード ファイルをスキャンします。また、StyleCop はスタイルの一貫性欠如を検証するだけで、コードの最適化やパフォーマンスのチェックは行いません。
今回は、StyleCop を紹介し、そのしくみを示して、プロジェクトに導入する際に考慮すべき要素について説明します。最後に、Visual Studio Team Foundation Server (TFS) のビルドに StyleCop の実行を含める方法をデモします。
StyleCop ( stylecop.codeplex.com、英語) は、C# ソース ファイルで静的コード分析を実行するオープン ソースのツールです。このツールは Visual Studio に統合されて、コンテキスト メニューに表示され、現在のファイル、または選択したファイルやプロジェクトをスキャンするオプションを提供します。図 1 は、Visual Studio プロジェクトのコンテキスト メニューから使用できる StyleCop オプションを示しています。
図 1 StyleCop のコンテキスト メニュー オプション
[Run StyleCop] (StyleCop の実行) または [Run StyleCop (Rescan All)] (StyleCop の実行 (すべて再スキャン)) オプションをクリックすると、StyleCop はすべての C# ファイルを解析し、指定された StyleCop の規則に従っているかどうかを検証します。規則に違反していると、[エラー一覧] ウィンドウに警告が表示されます。
StyleCop 設定ファイル: StyleCop のすべての構成オプションを保持します。このファイルには、選択した規則などの情報、カスタムの単語や頭字語などのボキャブラリの情報、設定ファイルを親ディレクトリの設定ファイルとマージするかどうかなどの情報が格納されます (存在する場合)。
StyleCop がソース ファイルの親ディレクトリにある設定ファイルを再帰的に検索する場合は、単一バージョンの Settings.StyleCop ファイルを保持するのがベスト プラクティスです。1 つのファイルを保守し、チーム プロジェクトのルートに格納することで、チーム プロジェクト全体で同じ規則のセットを使用できるようになります。
カスタム辞書ファイル: Settings ファイルに単語と頭文字を追加できることに加えて、StyleCop は Visual Studio コード分析の辞書と同じ形式の CustomDictionary.xml ファイルも使って作業します。これにより、両方に同じ辞書ファイルを使用できるようになります。図 2 に、辞書ファイルの形式を示します。
図 2 カスタム辞書ファイル
<Dictionary>
<Words>
<Unrecognized>
<Word/>
</Unrecognized>
<Recognized>
<Word/>
</Recognized>
<Deprecated>
<Term PreferredAlternate=""/>
</Deprecated>
<Compound>
<Term CompoundAlternate=""/>
</Compound>
<DiscreteExceptions>
<Term />
</DiscreteExceptions>
</Words>
<Acronyms>
<CastingException>
<Acronym />
</CastingException>
</Acronyms>
</Dictionary>
StyleCop の目的と基礎を説明したので、次にこれを開発チームの作業に不可欠な要素として組み込むために必要なものを紹介します。
StyleCop の規則: StyleCop がコード ファイルで実行するチェックです。組み込みで使用可能な多くの規則があり、必要に応じて、独自のカスタム規則を作成することもできます。StyleCop の wiki ページに独自の StyleCop 規則の作成方法が詳しく説明されています ( bit.ly/12P665L、英語)。
StyleCop を使用する際は、まず使用する StyleCop 規則を決めます。すべての StyleCop の規則を使用することを強くお勧めします。ただし、多くの場合、開発チームには独自のコーディング標準があり、特定の StyleCop の規則を適用するのに大きな抵抗を感じる場合があります。スタイルに一貫性を持った管理可能なコードを使用する長期的な利点と、その導入に伴う小さな不便さとのバランスを取る必要があります。多くの優れたプラクティスと同様、いったん StyleCop の使用に慣れれば、最初から使っていたかのようになります。いずれにしても、チームが一律に使用する StyleCop の規則についてはチームの合意が必要です。
StyleCop の規則は、次の 7 つのカテゴリに分類されます。
- 文書の規則: ソース ファイルの文書要素の適合性を検証します。
- レイアウトの規則: ソース ファイルのレイアウトと行間を検証します。
- 保守性の規則: 必要のない括弧や単一のファイルに複数のクラスが存在するなど、ソース ファイルの保守性の側面を検証します。
- 名前付けの規則: メソッドと変数の名前の代替性を検証します。
- 順序付けの規則: コードのコンテンツの順序が正しいことを検証します。
- 判読性の規則: コードの書式が適切に設定されていて、判読可能なことを検証します。
- 間隔の規則: コード コンテンツの間隔が有効かつ適切であることを検証します。
StyleCop カテゴリとそれぞれの規則の詳細については、StyleCop の規則に関するドキュメント ( bit.ly/191GgiQ、英語) を参照してください。
StyleCop 規則を選択して、設定ファイルに保存するのはこれでよいとして、すべてのソース コードで StyleCop が一貫して実行されるようにするには、ビルド プロセスの一部として実行するしかありません。
これを行う方法は 2 つあります。
- StyleCop を C# プロジェクトの MSBuild ファイルに統合して、プロジェクトがコンパイルされるときに必ず実行されるようにします。この方法の詳細については、StyleCop のドキュメント ( bit.ly/13ZX2xL、英語) を参照してください。
- 継続的インテグレーションの Team Build に StyleCop を追加し、チェックインのたびに実行されるようにします。
ここでは継続的インテグレーションの Team Build で StyleCop を実行する方法を説明します。ゲート ビルドを使用している場合、StyleCop を実行することで違反のあるコード ファイルはチェックインされません。ゲート ビルドを使用していない場合でも、破損したビルドによってコードをチェックインする際に違反を修正するよう求められます。
Team Build で StyleCop を実行するプロセスは、ビルド ワークフローのアクティビティから呼び出される必要があります。今回は、Community TFS Build Extensions ( tfsbuildextensions.codeplex.com、英語) というオープン ソース プロジェクトから StyleCop アクティビティを使用します。Community TFS Build Extensions は、Team Build プロセス テンプレートに単純にドラッグ アンド ドロップできる多くの再利用可能なワークフロー アクティビティを含む一連のライブラリです。
ビルド コントローラーの変更: Team Build をカスタマイズする前に、まずビルド コントローラーのカスタム アセンブリのパスを設定する必要があります。ビルド エージェントは、ビルド ワークフローで見つけたカスタム アクティビティのアセンブリをこの場所から読み込みます。
カスタム アセンブリを追加するには、Team Project の適切な場所に新しいフォルダーを作成します。今回は新しいフォルダーに Custom Assemblies という名前を付け、Team Project ルート フォルダー直下の BuildProcessTemplate の下に作成しました。ここで、以下のアセンブリをチェックインします。
- StyleCop.dll
- StyleCop.CSharp.dll
- StyleCop.CSharp.Rules.dll
- TFSBuildExtensions.Activities.dll
- TFSBuildExtensions.Activities.StyleCop.dll
次に、これらのアセンブリを使用するようにビルド コントローラーを構成します。これは次の手順で実行します。
- Team Explorer のビルド リンクをクリックします。[アクション] をクリックして [ビルド コントローラーの管理] を選択します。
- 表示されるダイアログ ボックスから、ビルド コントローラーを選択し、[プロパティ] ボタンをクリックします。
- [ビルド コントローラーのプロパティ] ダイアログ ボックスで、Team Project で先ほど作成した Custom Assemblies フォルダーに [カスタム アセンブリへのバージョン コントロール パス] プロパティを設定します (図 3 参照)。
図 3 ビルド コントローラーのプロパティ
[OK] をクリックし、プロパティのダイアログ ボックスを閉じます。これで、ビルド コントローラーはカスタム アクティビティを読み込むように構成されました。次は、ビルド テンプレートをカスタマイズします。
以下に、気を付けておきたい考慮事項をいくつか示します。
- Visual Studio コード分析とは異なり、StyleCop は Visual Basic .NET をサポートしていないため、C# で作成されたソース ファイルにのみ使用できます。
- この記事の執筆時点では、StyleCop はまだ Visual Studio 2013 では使用できません。
- ホスト ビルド コントローラーとは、Visual Studio Team Foundation Service によってクラウドでホストされるビルド コントローラーです。このビルド コントローラーを構成する手順は、オンプレミスのビルド サーバーを使用する場合と同じです。
- 今回は Team Foundation Server (TFS) 2012 を使用しました。この手順は、TFS 2010 および TFS 2013 でも同じです。正しいバージョンの TFS Build Extensions を使用していることを確認してください。
すべての新しいチーム プロジェクト向けに、TFS は多くのビルド テンプレートを用意しています。これらのビルド テンプレートは、チーム プロジェクトのルートにある ProcessBuildTemplates というフォルダーに作成されます。まず、DefaultTemplate.11.1.xaml テンプレートをコピーして、StyleCop アクティビティに追加するためにカスタマイズします。DefaultTemplate.11.1.xaml ファイルのコピーを作成し、CustomTemplate.xaml という名前に変えます。
ビルド ワークフローをカスタマイズするには、開発環境にカスタム アクティビティを追加する必要があります。そのため、Visual Studio で新しいワークフロー アクティビティ ライブラリ プロジェクトを作成します。[新しいプロジェクトの追加] ダイアログ ボックスで、ターゲット プラットフォームとして Microsoft .NET Framework 4.5 を選択します。次に、新しく作成したプロジェクトで CustomTemplate.xaml ファイルへのリンクを追加します。そのためにはプロジェクトを右クリックし、[既存項目の追加] をクリックし、CustomTemplate.xml ファイルを参照し、[リンクとして追加] をクリックします。
開発環境を設定する最後の手順として、[ツールボックス] ウィンドウに StyleCop アクティビティを追加し、ドラッグ アンド ドロップできるようにします。そのため、[ツールボックス] ウィンドウの [アクティビティ] の下の領域を右クリックし、[タブの追加] オプションをクリックします。新しいタブに、「TFS Build Extensions」という名前を付けます。このタブの名前を右クリックし、[アイテムの選択] をクリックします。TfsBuildExtensions.Activities.Stylecop.dll アセンブリを参照して、[OK] をクリックします。これで、CustomTemplate.xaml ファイルを開いて、そこに StyleCop アクティビティをドラッグできるようになります。
ビルド テンプレートのカスタマイズ: StyleCop はビルド プロセスの早い段階で実行します。これにより、違反が見つかった場合にビルドがすぐに停止します。StyleCop はスキャンするソース ファイルが必要なため、StyleCop を最初に実行できるのは Run On Agent シーケンス内の Initialize Workspace シーケンスの後です (図 4 参照)。
図 4 StyleCop アクティビティのドロップ場所
ビルド ワークフローの中で StyleCop アクティビティを追加する適切な場所を決めたので、次にシーケンス アクティビティを追加します。シーケンス アクティビティの名前を「Run StyleCop」に変更します。Run StyleCop シーケンスの最終的な流れを図 5 に示します。
図 5 Run StyleCop シーケンス
コードのウォークスルー: 図 6 に示すのは、Run StyleCop シーケンスで定義された変数と型、およびそれぞれの目的です。
図 6 Run StyleCop シーケンスで定義された変数
変数名 | 型 | 説明 |
SourceCodeFiles | IEnumerable<String> | StyleCop でスキャンされるすべてのファイルの名前を格納します。 |
IsSuccess | Boolean | StyleCop アクティビティで違反が見つかったかどうかを格納します。 |
ViolationCount | Int32 | StyleCop の違反の数を格納します。 |
ワークフローには、StyleCop 設定ファイルのパスを格納する String 型の StyleCopSettingsFile というパラメーターもあります。
Run StyleCop シーケンスの最初は、FindMatchingFiles アクティビティです。このアクティビティは、Microsoft.TeamFoundation.Build.Workflow.dll アセンブリに含まれ、所定のファイル パターンに一致するすべてのファイルの一覧を返します。図 7 は、このアクティビティのプロパティの設定方法を示しています。
図 7 FindMatchingFiles アクティビティのプロパティ
プロパティ名 | 値 |
DisplayName | FindMatchingFiles |
IsSuccess | String.Format(“{0}\**\*.cs”, BuildDirectory) |
Result | SourceCodeFiles |
このアクティビティは、Build Directory のすべての C# (*.cs) ファイルを見つけるパターンを受け取り、結果を SourceCodeFiles 列挙型で返します。
シーケンスの次のアクティビティは、Microsoft.TeamFoundation.Build.Workflow.Activities.dll アセンブリに含まれる ConvertWorkspaceItem アクティビティです。このアクティビティは、パラメーターとして渡された所定の StyleCop Settings ファイルのサーバー パスをビルド サーバーのローカル パスに変換します。このアクティビティのプロパティを、図 8 に示します。
図 8 Get Local Settings File のプロパティ
プロパティ名 | 値 |
Direction | ServerToLocal |
DisplayName | Get Local Settings File |
Input | StyleCopSettingsFile |
Result | StyleCopSettingsFileLocalPath |
Workspace | Workspace |
これでソース ファイルの名前を取得し、StyleCop 設定の場所を確立しました。次は Execute StyleCop アクティビティです。図 9 に示すのは、Execute StyleCop アクティビティのプロパティの設定方法です。
図 9 Execute StyleCop のプロパティ
プロパティ名 | 値 |
DisplayName | Execute StyleCop |
LogExceptionStack | True |
SettingsFile | StyleCopSettingsFile |
ShowOutput | True |
SourceFiles | SourceCodeFiles.ToArray() |
Result | StyleCopSettingsFileLocalPath |
Succeeded | IsSuccess |
TreatWarningsAsErrors | True |
このアクティビティは配列に変換された SourceCodeFiles 列挙型を入力として受け取り、IsSuccess 変数と ViolationCount 変数に結果と違反の数をそれぞれ返します。Execute StyleCop という表示名を持ち、警告をエラーとして処理し、エラーを見つけた場合にビルドを停止するように設定しています。
Run StyleCop シーケンスの最後のアクティビティは、Write Build Message アクティビティです。このアクティビティは、結果と違反の数を表示するように設定します。図 10 は、このアクティビティのプロパティの設定方法を示しています。
図 10 Write Build Message Activity のプロパティ
プロパティ名 | 値 |
DisplayName | Completion Message |
Importance | Microsoft.TeamFoundation.Build.Client.BuildMessageImportance.Normal |
Message | String.Format(“StyleCop was completed with {0} violations”, StyleCopViolationsCount) |
これで、Custom ビルド テンプレートを使用できるようになりました。保存して CustomTemplate.xaml ファイルをチェックインします。新しいビルド テンプレートを使用するには、ビルド定義を開き、プロセスをクリックし、[ビルド プロセス テンプレート] を展開し、[新規] をクリックします。表示される [新しいビルド プロセス テンプレート] ダイアログ ボックスで、[既存の XAML ファイルを選択] オプションをクリックし、CustomTemplate.xaml ファイルを参照します。
StyleCopSettingsFile パラメーターの値を Settings.StyleCop ファイルの場所に設定します。[保存] をクリックして、ビルド定義を保存します。これで、StyleCop を使ったビルドの準備ができました。このビルド テンプレートはゲート ビルドに使用するのが最適です。これにより、チェックインしたすべてのソース ファイルで StyleCop 違反が見つからないことが保証されます。
今回は、Team Build で StyleCop を使用して静的コード分析を実行する方法を説明しました。静的コード分析により、より良いコーディング標準が推進され、Team Build で実行してすべてのチェックイン コードが標準に従っていることを保証できます。同様に、Team Build で他のベスト プラクティスも実行できます。Microsoft ALM Rangers は、多くの役立つビルド テンプレートを作成し、Team Foundation Build Customization Guide ( vsarbuildguide.codeplex.com、英語) プロジェクトから入手できるようにしています。さらに、独自のアクティビティを作成したり、Community TFS Build Extensions プロジェクトで使用可能なアクティビティを使用することもできます。
Hamid Shahid は、Microsoft ALM Ranger であり、エンタープライズ ソフトウェアの設計と開発の 12 年以上の経験を持つフリーランスのコンサルタントです。彼は、Microsoft ALM テクノロジのベスト プラクティスを推進することに大きな関心を持っています。彼のブログは hamidshahid.blogspot.com (英語) から、ツイッターは twitter.com/hamid_shahid (英語) から閲覧できます。
この記事のレビューに協力してくれた ALM Rangers および技術スタッフの Mike Fourie (フリーランスのコンサルタント)、Willy-Peter Schaub (Microsoft)、および Patricia Wagner (Microsoft) に心より感謝いたします。
Mike Fourie は、13 年以上のソフトウェア開発の経験を持つフリーランスのコンサルタントで、ビルドと導入の自動化を専門にしています。彼は、Microsoft ALM MVP と Distinguished ALM Ranger の資格を持っています。彼のブログは freetodev.com (英語) から参照できます。彼のツイッターは、 twitter.com/mikefourie (英語) からフォローできます。
Willy-Peter Schaub は、Microsoft Canada Development Center で、Visual Studio ALM Rangers のシニア プログラム マネージャーを務めています。80 年代中ごろから、ソフトウェア エンジニアリングにおける簡潔さと保守性を追求し続けています。ブログは blogs.msdn.com/b/willy-peter_schaub (英語) で公開されており、ツイッターは twitter.com/wpschaub (英語) からフォローできます。