Excluding Compiler Generated Code from the NDepend Dependency Matrix

May 25, 2013 — Leave a comment

Using the Dependency Matrix generated by NDepend I recently noticed that it included compiler generated code which isn’t of interest to me at this point in time. I was looking for a way to exclude it from the solutions’ Dependency Matrix. Fortunately, Patrick from NDepend team provided me with a great answer on Stackoverflow.

What is NDepend?

NDepend is a Visual Studio tool to manage complex .NET code and achieve high Code Quality. With NDepend, software quality can be measured using Code Metrics, visualized using Graphs and Treemaps, and enforced using standard and custom Rules.
Hence the software design becomes concrete, code reviews are effective, large refactoring are easy and evolution is mastered.

The following Dependency Matrix contains compiler generated code that is part of a dependency cycle. The compiler generated code is easily identified because the name contains +<> characters which are not permitted in user code. The dependency cycle can be identified by the black squares.

The Dependency Matrix

2013-05-25_18h41_43

Expanded Dependency Matrix…

2013-05-25_18h21_22

Code represented in this Dependency Matrix

The following code was written as an example for my original question on Stackoverflow. It is composed of a console application that uses a TestClass from a separate assembly to persist Json to a file.

class Program
{
    static void Main(string[] args)
    {
        var test = new TestClass(new Logger());
        test.WriteJsonFileToDiskAsync("path","[]");
    }
}

The logger is a dependency from my original code so I reproduced it with a dummy implementation

public interface ILogger
{
    void InfoIfDebuggerIsAttached(string message);
}

public class Logger : ILogger
{
    public void InfoIfDebuggerIsAttached(string format)
    {
        //TODO: Log somewhere
    }
}

The TestClass is quite similar to the code that got me curious about removing compiler generated code from the Dependency Matrix.

public class TestClass
{
    private readonly ILogger logger;

    public TestClass(ILogger logger)
    {
        this.logger = logger;
    }

    public void WriteJsonFileToDiskAsync(string filePath, string json)
    {
        Task.Factory.StartNew(() => WriteJsonFileToDisk(filePath, json))
            .ContinueWith(HandleWriteException);
    }

    private void WriteJsonFileToDisk(string filePath, string json)
    {
        Stream fileStream = null;
        try
        {
            fileStream = File.Create(filePath);
            using (var writer = new StreamWriter(fileStream))
            {
                fileStream = null;
                writer.Write(json);
            }

            var message = string.Format(CultureInfo.InvariantCulture, 
                                        "Persisted file: {0}", 
                                        filePath);

            logger.InfoIfDebuggerIsAttached(message);
        }
        finally
        {
            if (fileStream != null)
                fileStream.Dispose();
        }
    }

    private static void HandleWriteException(Task task)
    {
        if (task.IsFaulted)
        {
            //TODO: Handle Exception
        }
    }
}

In this case the compiler generates code because the Task Parallel Library is used to execute the WriteJsonFileToDisk method.

Generating a Dependency Matrix Without Compiler Generated Code

The ALT + Q keyboard shortcut brings up NDepend’s Queries and Rules Editor. With it’s intellisence, you can write a query and explore possible filtering criteria.

NDepend supports the Code Query LINQ (CQLinq) for maximum flexibility.

With CQLinq in Visual Studio, shed light instantly on any fact about your code.

For example the CQLinq query below ask for which method became even more complex?

 

from m in JustMyCode.Methods.Where(m1 => !m1.WasAdded())

let oldComplexity = m.OlderVersion().CyclomaticComplexity

let newComplexity = m.CyclomaticComplexity

where oldComplexity > 8 && oldComplexity < newComplexity

select new { m, oldComplexity, newComplexity }

To discard generated code you can use the following query

// <Name>Types Without Compiler Generated Code</Name>
from t in Application.Types
where !t.IsGeneratedByCompiler
select t

As you type the query, the editor will validate and execute the it. The results are instantly available, allowing you to further refine the query.

2013-05-25_19h40_31

Once the compiler generated code is filtered out, you can then export the results to the Dependency Matrix

2013-05-25_20h09_04

The Dependency Matrix

2013-05-25_20h13_12

Expanded Dependency Matrix…

2013-05-25_20h11_55

 

Conclusion

We can now focus our efforts on code that was written by developers. I wish filtering out compiler generated code could be done by using a toggle button on NDepend’s Dependency Matrix window.

Queries are a great way to build Dependency Matrices that answer our questions! Find out more on NDepend’s website.

No Comments

Be the first to start the conversation!

Leave a comment

This site uses Akismet to reduce spam. Learn how your comment data is processed.