NDepend customizing rule: Avoid namespaces with few types

NDepend is a tool that offers a wide range of features to let developers analyze a .NET code base. It comes with about 200 built in rules. But there are a few default rules that do not fit “my rules”. This blog post shows how to customize one and even more important why. Avoid namespaces with few types I observed that the original rule outputs an unnecessary line for namespace {} because of the compiler generated classes (caused by linq queries). Here is my *fixed* rule to skip “0 types“ in the result: warnif count > 0 from n in JustMyCode.Namespaces let types = n.ChildTypes.Where(t => !t.IsGeneratedByCompiler) where types.Count() < 5 && types.Count() > 0 orderby types.Count() ascending select new { n, types }

NDepend customize rule: Avoid defining multiple types in a source file

NDepend is a tool that offers a wide range of features to let developers analyze a .NET code base. It comes with about 200 built in rules. But there are a few default rules that do not fit “my rules”. This blog post shows how to customize one and even more important why. Avoid defining multiple types in a source file I completely agree, with one exception: When having a generic and a non-generic type e.g. MyClass and MyClass<T> warnif count > 0 let lookup = Application.Types.Where( t => t.SourceFileDeclAvailable && !t.IsGeneratedByCompiler && !t.IsNested ).ToMultiKeyLookup( t => t.SourceDecls.Select(d => d.SourceFile) ) from @group in lookup.Where( g => g.Select( x => x.Name.IndexOf("<") > -1 ? x.Name.Substring(0, x.Name.IndexOf("<")) : x.Name ).Distinct().Count() > 1 ) let sourceFile = @group.Key let typeWithSourceFileName = @group.FirstOrDefault( t => t.SimpleName == sourceFile.FileNameWithoutExtension ) let typeIndex = typeWithSourceFileName ?? @group.First() select new { typeIndex, types = @group as IEnumerable<IType>, typeNames = String.Join( ", ", ((IEnumerable<IType>)@group). Select(t1=>t1.Name). ToArray() ), sourceFile.FilePathString }

NDepend customize rule: Types too big

NDepend is a tool that offers a wide range of features to let developers analyze a .NET code base. It comes with about 200 built in rules. But there are a few default rules that do not fit “my rules”. This blog post shows how to customize one and even more important why. Types too big I use extension methods to collect several functionality for e.g. framework types as string. Each Extension-Class is typically  spread across several files and partial to keep overview and maintainability. NDepend analyses on assembly basis and therefor cannot know about my tricks. But I can put some knowledge into the query: warnif count > 0 from t in JustMyCode.Types where t.NbLinesOfCode > 500 && !t.Name.EndsWith("Extensions") orderby t.NbLinesOfCode descending select new { t, t.NbLinesOfCode, t.NbILInstructions, t.Methods, t.Fields }

NDepend customize rule: Quick summary of methods to refactor

NDepend is a tool that offers a wide range of features to let developers analyze a .NET code base. It comes with about 200 built in rules. But there are a few default rules that do not fit “my rules”. This blog post shows how to customize one and even more important why. Quick summary of methods to refactor This rule gives you a quick overview of what needs to be refactored. I adjusted the rule so that compiler generated delegates that have a high “IL Nesting Depth” do not appear.Sample code for this case: var tablesNames = from tableRow in conn.GetSchema("Tables").Rows.Cast<DataRow>() let tableName = tableRow["TABLE_NAME"].ToString() where !tableName.Contains("$") ... select tableName; warnif count > 0 from m in JustMyCode.Methods where m.NbLinesOfCode > 50 || (m.NbILInstructions > 200 && m.ILCyclomaticComplexity > 50 ) || m.CyclomaticComplexity > 20 || m.ILCyclomaticComplexity > 50 || (m.ILNestingDepth > 5 && m.ILCyclomaticComplexity > 10) || m.NbParameters > 5 || m.NbVariables > 20 || m.NbOverloads > 25 select new { m, m.NbLinesOfCode, m.NbILInstructions, m.CyclomaticComplexity, m.ILCyclomaticComplexity, m.ILNestingDepth, m.NbParameters, m.NbVariables, m.NbOverloads }

NDepend customizing rule: Static fields should be prefixed with a 's_'

NDepend is a tool that offers a wide range of features to let developers analyze a .NET code base. It comes with about 200 built in rules. But there are a few default rules that do not fit “my rules”. This blog post shows how to customize one and even more important why. Static fields should be prefixed with a 's_' I use underdashes for instance fields and therefor I have a custom rule for static fields. They tend to look even more scary (and that’s what they should) if prefixed with ‘_s_’. So here is my rule: warnif count > 0 from f in Application.Fields where !f.NameLike (@"^_") && f.IsStatic && !f.IsLiteral && !f.IsGeneratedByCompiler && !f.IsSpecialName && !f.IsEventDelegateObject select new { f, f.SizeOfInst }

NDepend customize rule: Instance fields should be prefixed with a 'm_'

NDepend is a tool that offers a wide range of features to let developers analyze a .NET code base. It comes with about 200 built in rules. But there are a few default rules that do not fit “my rules”. This blog post shows how to customize one and even more important why. Instance fields should be prefixed with a 'm_' I prefix instance fields with a ‘_’ not with ‘m_’ so I need to customize the default rule: warnif count > 0 from f in Application.Fields where !f.NameLike (@"^_") && !f.IsStatic && !f.IsLiteral && !f.IsGeneratedByCompiler && !f.IsSpecialName && !f.IsEventDelegateObject select new { f, f.SizeOfInst }

Validating Code Quality with NDepend

Patrick Smacchia’s NDepend is a great tool to improve code quality and should be run quite regularly. It can be run as a strand alone GUI tool, from inside Visual Studio and as part of your build process. I’ll use the tool over the next few weeks to analyze and improve the quality of one of my personal code bases. I’ll try to share my experiences beside tips and tricks as well as giving feedback to Patrick. Code Rules an Queries At first I’d like to highlight one of the most powerful features: Code Rules an Queries. This lets query your code base over LINQ queries thanks to CQLinq. There are about 200 default rules. The power really evolves as you start customizing these and further on start writing your own rules. Here is an example: from m in Application.Methods where m.NbLinesOfCode > 30 && m.IsPublic select m And a screenshot of the Editor: Wishlist As X-Mas is soon I’ll write down a few things I would have expected or that would improve the tooling experience. Tab a selection in “Query and Rules Edit” Currently a tab on a selected range removes the range. Tabbing helps me to keep code readable.

Re: How to change the default browser in Visual Studio programmatically

I’d really like to thank Scott Hanselman for digging into the nitty gritty details of how to change the Visual Studio Default Browser. But… let me cite one of the comments: “Should adding browser options to Visual Studio be <sarcasm>this easy</sarcasm>?” I hope we all agree on: Go fix this! As I have not found my way to powershell (yet) and I want to have VS Integration (as Scott finalizes his post) too: Here comes the macro version…Sub SetInternetExplorerAsDefaultBrowser() Dim FilePath As String = _ Path.Combine( _ Environment.GetFolderPath( _ Environment.SpecialFolder.UserProfile), _ "AppData\Local\Microsoft\VisualStudio\10.0\browsers.xml") Dim xml As String = "<?xml version=""1.0""?>" & vbCrLf & _ "<BrowserInfo>" & _ "<Browser>" & _ "<Name>Internet Explorer</Name>" & _ "<Path>""C:\Program Files (x86)\Internet Explorer\IEXPLORE.EXE""</Path>" & _ "<Resolution>3</Resolution>" & _ "<IsDefault>True</IsDefault>" & _ "<DDE><Service>IExplore</Service>" & _ "<TopicOpenURL>WWW_OpenURL</TopicOpenURL>" & _ "<ItemOpenURL>""%s"",,0xffffffff,3,,,,</ItemOpenURL>" & _ "<TopicActivate>WWW_Activate</TopicActivate>" & _ "<ItemActivate>0xffffffff,0</ItemActivate>" & _ "</DDE>" & _ "</Browser>" & _ "</BrowserInfo>" If (File.Exists(FilePath)) Then File.Delete(FilePath) End If Using sw As New StreamWriter(FilePath) sw.Write(xml) End Using Dim ConfigFile As New FileInfo(FilePath) Using key As RegistryKey = _ Registry.CurrentUser.OpenSubKey( _ "Software\" & _ "Microsoft\" & _ "VisualStudio\" & _ "10.0\" & _ "WebBrowser\" & _ "ConfigTimestamp", _ True) key.SetValue( _ "LastConfigurationTimestamp", _ DateTime.Now.ToUniversalTime().ToFileTime(), _ RegistryValueKind.QWord) key.SetValue( _ "CacheFileDateLastMod", _ ConfigFile.LastWriteTimeUtc.ToFileTime(), _ RegistryValueKind.QWord) key.SetValue( _ "CacheFileSizeBytes", _ ConfigFile.Length, _ RegistryValueKind.DWord) End Using End Sub