Thursday, May 13, 2010

StyleCop

Having worked in both types of software companies (#1 - those that care about the quality of the code it produces, #2 - those that do not... and preferring the former by some way!), I was pleased to come across StyleCop - a tool that complements FxCop (which analyzes adherence to the Microsoft Design Guidelines for Developing Class Libraries in .NET assemblies) by checking source code for adherence to the coding standard.

Assuming company type #1, as the size of development teams increases with the scale of the project (and hence, the product under development), the importance of having source code developed in a consistent style increases. StyleCop is an invaluable tool in this regard; it checks source code from spacing between code elements to the correctness of documentation (albeit at a fairly rudimentary level). Even better, it allows integration with Visual Studio projects via MSBuild targets, which will force a build failure in the face of source code that falls short of the coding standard.

This does raise some issues for those that differ with Microsoft in the standards they apply; for these StyleCop provides 2 possible options:
  1. Customize the StyleCop settings (optionally, writing custom analysis rules)
  2. Change your coding standard
I took option #1, by disabling the settings that went against the coding standard - e.g. requiring that fields be defined at the end, methods be organized in order of visibility (as opposed to functionality/having overloads grouped together). StyleCop saves these settings in a Settings.StyleCop file; when analyzing source code, the merged StyleCop settings will be applied to all files in and below the closest folder containing the Settings.StyleCop file.

The merge mentioned above is implemented as follows: StyleCop applies settings from the global default included in the installation through the folder hierarchy, with the lowest level settings file having the highest priority. Hence, it is possible to define settings and override them at the required level of granularity. For example, I have a Settings.StyleCop file at the same level as the .sln file; however, I have another Settings.StyleCop file wherever an override is required (such as in IDE generated code), at a lower level in the source code structure. This also allows applying StyleCop within legacy codebases in areas where new features are being developed, for example.

Thus far, StyleCop is working just fine; a further minor adjustment to development protocol to require zero FxCop and StyleCop warnings when committing source code to version control will hopefully take the development team to the next level of code quality.

FxCop and Custom Dictionaries

I've moved back to using FxCop 1.36 (instead of the Visual Studio Code Analysis feature), for the following reasons:
  1. Managing exclusions/suppressions is easier than in code (especially in identifying the exclusions added without justification!)
  2. Identification of issues that no longer exist in the codebase (near impossible in large codebases, with the SuppressMessage attribute)
  3. Suppressions will not get built into the assembly as metadata
The main problem that I encountered in this move was with the use of custom dictionaries; while FxCopCmd.exe supports a /dictionary command-line switch, the FxCop GUI tool does not have a feature to add a custom dictionary.

There are some special paths which can be used to store the custom dictionary, such as the FxCop installation and User Profile paths - these have a major drawback in team development scenarios: they are not conducive for maintaining the dictionary in a common location in source control (in my case, in a path relative to the FxCop project file). Storing the custom dictionary in the same folder as the FxCop project file is supposed to work, but I could not get this to work as mentioned here, here and here.

The solution I came up with (quite by accident, while performing a diff on the FxCop project file after using FxCopCmd.exe with the /dictionary and /update switches!) was to add the relative path of the custom dictionary into a child element of the 'CustomDictionaries' element in the FxCop project file. I used the $(ProjectDir) variable within the FxCop project file to ensure the path of the custom dictionary would remain dynamic. As far as I can tell, this XML structure and the use thereof has not been documented by Microsoft.

A secondary benefit in using this approach is the facility to use the same custom dictionaries which were previously referenced from Visual Studio projects as Code Analysis Dictionaries, from source control.

A third tab in the FxCop GUI (in addition to the Targets and Rules tabs) to contain the dictionaries would be useful, to make using custom dictionaries easier. In essence, all it would have to do is handle adding/removing of CustomDictionary elements (i.e. a programmatic equivalent of my manual solution above).

Another great feature (on a slightly unrelated note) would be a set of MSBuild targets (in a .target file) that can be used to integrate with Visual Studio, a la the StyleCop VS integration.

EDIT: As per Steven's request, given below is the change I made to the .FxCop XML project file; under the 'ProjectOptions' element, I changed the 'CustomDictionaries' element to read as follows:

<CustomDictionaries SearchFxCopDir="True" SearchUserProfile="True" SearchProjectDir="True">
    <CustomDictionary Path="$(ProjectDir)/CodeAnalysisDictionary.xml" />
</CustomDictionaries>

Seems the word 'CodeDictionaries' had got stripped from the original post (as I'd used angle brackets); I've corrected the original article text.

Hope this explains my hack/fix sufficiently; I'd have liked to submit a .FxCop file, but it seems Blogger.com doesn't allow attachments.... :-(

Thursday, January 21, 2010

Presentation on Software Design Principles

This is a presentation on Software Design Principles, mainly based on the work of Bob Martin.

The slide deck is dedicated to Bob Martin and the other software engineering pioneers who set the foundation for the software we develop today. Thank you!