NDepend, a second look

After my previous post regarding NDepend I have decided to give it another go, this time on a new project.

I am using Visual Studio 2015 for the first time so need to install NDepend for VS2015; this is now very easy after setting things up last time. Navigate to the NDepend folder, run NDepend.VisualStudioExtension.Installer.exe and click install for VS 2015.

Installer

I’ve just started a new project, Qujck.MarkdownEditor. At the current point of time the code reads some markdown and renders it for display in a WebBrowser control, using google prettify to add syntax highlighting to code snippets.

Analysing the project this early on was a pleasant experience with only 93 violations.

Dashboard

  1. Avoid namespaces mutually dependent
    This took me a moment to figure out. What I have is classes in the namespaces Qujck.MarkdownEditor.Queries and Qujck.MarkdownEditor.Aspects that both make use of a couple of extension methods in Qujck.MarkdownEditor. This is the sort of thing that leads to a namespace such as Common, Core, Infrastructure etc and on this occasion I will go with Infrastructure.

Dashboard

Great, 91 violations to go …

Rules Explorer

  1. Avoid empty interfaces * 2
    These 2 warnings are not errors for me, the 2 interfaces are IQuery<TResult> and ICommand that I have highlighted in numerous other posts. The recommendation for ignoring these is to create a dedicated attribute and modify the rules with something along the lines of && !m.HasAttributes("Namespace.IsNotDeadAttribute"). This is a solution but it’s not for me, my code does not need to know (and arguably should not know) about the analysis tool. My preference is to hard code these 2 interfaces into the rules and can be achieved by tweaking the query:
warnif count > 0 from t in JustMyCode.Types where 
  t.IsInterface && 
  t.NbMethods == 0 &&
  !new string[]
  { 
      "IQuery<TResult>",
      "ICommand"
  }.Contains(t.Name)
select new { t, t.TypesThatImplementMe }
  1. Class with no descendant should be sealed if possible * 2
    One is the MainForm generated by Visual Studio and the other is the CompositionRoot class that I have recently added for doing Pure DI. Both of these can be sealed
  2. Instance size shouldn’t be too big
    This the MainForm so I can ignore this. In fact I will ignore all Forms:
warnif count > 0 from t in JustMyCode.Types where 
  t.SizeOfInst > 64 &&
  t.BaseClass.Name != "Form"
  orderby t.SizeOfInst descending
select new { t, t.SizeOfInst, t.InstanceFields } 
  1. Nested types should not be visible
    Referring to this post, I like to organise my Command and Query handlers by housing them within a static parent class, another query tweak will fix this:
warnif count > 0 from t in JustMyCode.Types where 
  t.IsNested && 
 !t.IsGeneratedByCompiler &&
 !t.IsPrivate &&
 !new string[]
  {
    "Query",
    "Query+Handlers",
    "Command",
    "Command+Handlers"
  }.Contains(t.ParentType.Name)
select new { 
   t, 
   t.Visibility 
} 
  1. Avoid namespaces with few types
    Qujck.MarkdownEditor.Properties is VS generated
    Qujck.MarkdownEditor.Infrastructure was created to fix avoid namespaces mutually dependent above
    Qujck.MarkdownEditor is the root namespace
    I’m going to ignore this one for now and see how the solution evolves.
  2. Types with disposable instance fields must be disposable
    This is MainForm again. Bizarrely the generated code MainForm.Designer.cs does have a Dispose method, the fix is to simple add IDisposable as in public sealed partial class MainForm : Form, IDisposable
  3. Avoid public methods not publicly visible
    Referring to this post I would normally have Command and Query handlers nested within an internal static partial class Handlers but have made Handlers public for now to remedy this error
  4. Types that could have a lower visibility
    Now this is the case while I am doing Pure DI, but if I shift over to using SimpleInjector then the classes would all need to have publicly accessibly constructors. I am going to disable this rule.
  5. Methods that could have a lower visibility
    As above, I will disable this rule.
  6. Fields should be marked as ReadOnly when possible
    2 out of 3 fixed, the other is the components field of the generated code MainForm.Designer.cs. I’m going to ignore this one.
  7. Methods names should begin with an Upper character
    Fixed.
  8. Static fields should be prefixed with a ‘s_’
    Deleted!
  9. Instance fields should be prefixed with an ‘m_’
    This rule is not for me: I am going to disable this rule.
  10. Avoid defining multiple types in a source file
    Fixed.
  11. Mark assemblies with CLSCompliant
    Fixed.

2 rules violated, 4 Violations – I can live with that! :-)

Dashboard

Rules Explorer

Leave a Reply