Geeks With Blogs
Andrew Siemer's Blog Enterprise Web Applications, ASP.NET MVC, C#, SQL Server, Architecture, & Writing

The people behind the NDepend software recently provided me with their latest version of NDepend to see what I thought.  I initially ran the package over one of my recent projects and found that the reporting offered in the latest version of NDepend was infinitely better than the previous version (1.0) that I worked with.  I found the reports that NDepend was offering would be most valuable while building my latest project.  For this reason I started my latest project in a manner that would leave much room for improvement. 

My application in the beginning

The project that I am going to run NDepend over to help me catch mistakes as I develop is built in ASP.NET MVC, LINQ to SQL, and following Domain Driven Design.  I specifically didn’t follow most of the SOLID principles to see how well NDepend would allow me to catch and correct my deficiencies.  To start off I am using the standard Model View Controller concepts and have stuffed all of my business and data access layer into a separate assembly project.  I am building a services layer, have specific domain objects (generated by LINQ to SQL), and am using the Repository pattern.  Beyond that I am new’ing up class references, not creating interfaces for anything, and am lumping generic concepts into generic classes.

With that in mind I ran NDepend over my initial code base and was given the following reports (there is a lot more information offered…but we will start here):

image

image

VisualNDependView

AbstractnessVSInstability

ComponentDependenciesDiagram

image

What does all of this mean?  I took a look at this cheat sheet (http://www.hanselman.com/blog/content/binary/NDepend%20metrics%20placemats%201.1.pdf) to begin to decipher all of this information.  On our abstractness and instability chart my code is currently showing as being very concrete and very stable!  This is not a bad zone to be in (my code is neither painful or useless).  <GRIN>  Also, when looking at my dependency graph you will notice that for the most part (MOST PART) my presentation layer is only communicating with the sub system through my business layer.  Some of my code is generated (LINQ to SQL) or part of a framework (ASP.NET MVC) which means that there is not a whole lot I can do in some regards.  And we can clearly see in the metrics section (all the gradient squares) that some areas have a lot more code dedicated to them than others.  Finally we have a list of high level warnings (yellow sections of the CQL) that may benefit from closer inspection.

Since I have a nice baseline of my application built in a standard tiered manner but not following my normal development avenues (SOLID), I am going to first avoid the direct output of these reports and add in a couple of my normal design decisions to see how it affects these reports.  I am first most curious to see how implementing StructureMap will help me here as it will force me to generate interfaces for all of my classes as well as remove all the static dependencies in my code.  Also, once I have StructureMap implemented it will be easier to do things like Inversion of Control and Test Driven Development. Implementing StructureMap will help us get closer to the concept of the Interface Segregation Principle.  Once that is done I will rerun the reports to see where we are.  Then I will implement Inversion of Control (IoC) to see how that impacts things.  My next step would be to refactor my code so that it follows the Single Responsibility Principle (but in the effort to get this post done…I may push that to another article!).

Application after StructureMap

Once I added StructureMap into my source code for all the references that I could I started to find myself moving up the scale of “uselessness” but no closer to “abstractness” (which makes sense).  The change that was made was that rather than saying Object o = new Object() I am now generating an interface (with ReSharper) for the Object and then declaring an instance of the object using StructureMap using syntax like IObject o = ObjectFactory.GetInstance<IObject>().  This basically means that pretty much everything has an interface defining it’s usage.  Also, with StructureMap I can swap in mocks when testing.  This makes my code much more flexible down the road (more flexible apparently equals more useless).  An example of this flexibility is that if I want to use the standard .NET Cache initially I can.  Then later I can swap in a new MemCache object simply by injecting the new object everywhere that ICache is called for via StructureMap.  This is done with a couple of lines of configuration code in the StructureMap.config file…lots of power here!

Before (StructureMap and interfaces not used):

image

After (StructureMap implemented where possible, interfaces used where appropriate):

 image

Here are the other items to look at.

image

image

image

image

image

Having done my best to start following the Interface Segregation Principle I am now going to turn to my next favorite pattern/principal by implementing Inversion of Control (or the Dependency Inversion Principle) and see what improvements that gives us.

My application with Inversion of Control

In order to apply inversion of control to my application I will be taking all of the instantiations out of my methods and moving them out to parameters of a method or passed in via the constructor.  Now that I have StructureMap sewn into the application I can take advantage of some of its power in that if it sees an interface being specified in the constructor of an object that it is instantiating, it will go ahead and pass in the appropriate instance of that required object. 

For example, prior to doing IoC I had a repository class that would work with accounts (AccountRepository).  It would instantiate an instance of the Connection class internally and then do the work it needed to do to connect to the database and grab the appropriate account related data.  This means that the Connection class and the AccountRepository class were very strongly coupled to one another.  Some of this coupling in the same layer is not horrible…but in this case every single repository in my application would be coupled to my Connection object which over time would rapidly become a very large number.

We can easily fix this scenario using StructureMap in that we can require IConnection be passed in via the constructor of each repository class.  Then when we instantiate a repository object StructureMap will take care of passing the appropriate Connection to the Repository and we are off and running.  This removes the need for users of the Repository to be aware of which Connection object to use and reduces coupling considerably.

I will apply this concept to the entire application and see how that affects things in NDepend’s eyes.

Argh!  There was no physical change to my NDepend reports simply by implementing IoC!  NDepend looks at coupling across assemblies but not inside the assembly (at least I don’t see that anywhere).  No worries!  This addition will help down the road when it is time to start implementing our unit tests.  Not a total loss.

Addressing the canned CQL Queries and Constraints

Ok, let’s dig into some of the CQL Queries and Constraints to see if we can affect change that way.  The yellow sections of this report are the areas that need attention.

image

Lets start off with the Encapsulation warnings (section in red above).  In the Visual NDepend interface I can see the following warnings.

image

By double clicking on the first item “Methods” I see the following list.

image

Here you see specific suggestions to make my code more compliant with rules of encapsulation!  Double clicking the first problem area “Methods that could be declared as…” I am presented with this list.

image

Double clicking on any of these method names takes me directly to the code (in Visual Studio) that needs help.  From there I can dig around to see about making the suggested changes.  In some cases I see where I could indeed mark something as “internal”…however the suggestions that are being made are simply because nothing external to the assembly is calling the specific method.  Unfortunately for me I frequently import libraries and tools from past projects knowing that I will need to use them eventually.  In my case most of the suggested items that need to be fixed are items that are waiting to be used rather than items that need to be marked as internal! 

I continued to poke through their list of suggestions and found that while the suggestions are good, they are not always 100% appropriate.  This means that I will have to learn to live with some of these yellow cautionary sections as I can’t get them to go away (without mangling their CQL queries…which may apply at a later date)!

NDepend is super flexible!

Now that I have been using this product for a while, and have started to bump my head against it a bit, I am starting to find that this product is actually very flexible!  For example there is a query for for naming standards I have started to bump my head against.  I like to use an underscore to denote my private fields in a class.  NDepend would prefer that I use m_ instead.  To change this is quick and easy.  I simply locate the rule that bugs me, double click on it, make the change in the CQL query editor, and save the changes.

image 

image

I made the changes to the query above so that it now looks like this:

image

This goes for all of the rules that are in this product which means that I can add and remove rules as I see fit!

Posted on Thursday, May 28, 2009 4:07 PM | Back to top


Comments on this post: NDepend review – code evolution achieved by following NDepend metrics

No comments posted yet.
Your comment:
 (will show your gravatar)


Copyright © Andrew Siemer - www.andrewsiemer.com | Powered by: GeeksWithBlogs.net