In my continuing use of NDepend on both my work and home projects, I have been investigating CQL more and more, especially from the perspective of use in continuous integration. NDepend provides some incredibly powerful analysis features and I find the idea that constraints can be applied and warnings reported as part of day 1 builds to be extremely appealing. I’m all about keeping code clean, constrained, and consistent. NDepend provides another great tool in my kit to ensure that my own code is marshalled to my standards from the very first line that is written. As David Muhondro put so eloquently in his blog post, NDepend is static analysis on steroids. When most users encounter CQL for the first time, the response is “wow, this looks really powerful, now what does it mean?”. I’ve started by taking the stock queries that are included in a basic NDepend project and understanding what they mean and the warnings that they are expected to generate. By understanding the warnings and their purpose in the project, I began to understand how I could tweak those queries and even write my own to enforce the rules I’d like my code to live by.
Let’s start by looking at an example. After creating a new NDepend project and pointing it at a list of assemblies to analyze, the default CQL queries that are included are grouped into the following categories:
- Code Quality
- Unused Code / Dead Code
- Diff / Changes / Evolution
- Test Coverage
- Purity / Immutability / Side-Effects
- Naming Conventions
- .NET Framework Usage
- Samples of Custom Constraints
- Constraints extracted from Source Code
I started by looking at the Unused Code / Dead Code queries, specifically at the Potentially unused methods query. By double-clicking on the query it is opened in the CQL query editor and displays the following:
Breaking it Down
Let’s break this down a little. First of all it is important to realize that this is not SQL, despite any similarities in the syntax. The first line selects the top 10 methods that satisfy the query and then raises a warning if the total number of methods is greater than 0. The reason for the seemingly superfluous top 10 selection is that if the count is greater than zero then those top 10 will be displayed as the results of the query. To avoid swamping with noise the query is restricting to only the first ten offenders. The next line is the first part of the WHERE clause and looks for methods with an CruiseControl to bring these warning and reports into the daily life of your projects. While static analysis en masse isn’t for everyone (not even for me), a small list of CQL queries can help you perform necessary housekeeping without having to do the hard hunting work yourself. The inevitable question is whether or not this overlaps with FxCop. There is some overlap, but they are both just tools from which you should pluck the best of the functionality you like and strike down the cruft that gets in the way. There are some cases where writing an FxCop rule specific to your application is a good thing, however I’m finding that writing CQL queries for warnings lends itself a little better to how I think about static analysis in the first place. The key is finding that sweet spot in the middle.