Presentation is loading. Please wait.

Presentation is loading. Please wait.

How to make the most of Code Analysis Patrick Smacchia NDepend Creator and Lead Developer Build Stuff Lithuania - 11th Dec 2013.

Similar presentations


Presentation on theme: "How to make the most of Code Analysis Patrick Smacchia NDepend Creator and Lead Developer Build Stuff Lithuania - 11th Dec 2013."— Presentation transcript:

1 How to make the most of Code Analysis Patrick Smacchia NDepend Creator and Lead Developer Build Stuff Lithuania - 11th Dec 2013

2  Introduction to NDepend  Contract, Unit Test and Code Coverage  Designing to make the UI testable  Detect regressions early with Code Rule  On Clean Code Structure

3 Introduction to NDepend

4  Tool for.NET Developers I’ve created in April 2004  Became commercial in February 2007  Tool specialized in static analysis of.NET code  Integrate in Visual Studio (2013, 2012, 2010, 2008)  Integrate in Build Process to produce reports  Soon 4.000 companies client worldwide  JArchitect (for Java) CppDepend (for C++) NDepend Facts

5  Code Rules written with C# LINQ syntax  Dependency Graph and Matrix  Code Diff  Code Metrics, Treemap  Trending  Code Coverage  … NDepend Features

6 How do we use NDepend to build NDepend?

7 Contract, Unit Test, Code Coverage

8  Microsoft Code Contract library  Suitable for the public surface of your product API  Standardized (documentation, compiler check…)  Not adapted for an intensive usage (slow compilation)  System.Diagnostics.Debug.Assert()  Adapted for an intensive usage, everywhere in your code  Only work in DEBUG mode  At least it doesn’t slow down production execution Code Contracts in.NET

9  Pretty much the same thing. Really!!  In both cases we want to check for assertions.  In both cases we want a failure if a condition is not fulfilled, because it means correctness violation  Code Contracts MUST fail if not fulfilled at unit test running time  Advantage: You can run an automatic test with few assertions, but still get the contracts assertions verified. Code Contracts vs. Unit Tests

10  100% ! … less is not enough!  Often we hear: the last 10% are too costly to be covered  Why is it too costly?  Because this last 10% code is not well testable  Hence it is not well designed  Hence it is error-prone  Nobody wants to let the most error-prone code uncovered by test, do you? How much Code Coverage is needed?

11  100% … at least needed for core business logic classes that contain the application complex logic  NDepend entire code base: 79% covered  100% coverage also means all contracts get checked  Isolate in some special classes uncoverable code  Blocking methods: MessageBox.Show() OpenFileDialog()  Hard to repro error cases: IO.UnauthorizedException catch  … How much Code Coverage is needed?

12  3 major.NET tools to obtain Code Coverage from automatic tests run:  VS Code Coverage  JetBrains dotCover  NCover  Ndepend can import Code Coverage from any of these tools Code Coverage

13 NDepend rules and Code Coverage // Types tagged with FullCoveredAttribute should be 100% covered warnif count > 0 from t in Application.Types where t.HasAttribute ("NDepend.Attributes.FullCoveredAttribute".AllowNoMatch()) && t.PercentageCoverage < 100 let notFullCoveredMethods = t.Methods.Where( m => m.NbLinesOfCode> 0 && m.PercentageCoverage < 100 && !m.HasAttribute("NDepend.Attributes.UncoverableByTestAttribute".AllowNoMatch())) select new { t, t.PercentageCoverage, t.NbLinesOfCodeNotCovered, notFullCoveredMethods, t.NbLinesOfCode, t.NbLinesOfCodeCovered }

14 NDepend rules and Code Coverage // Types 100% covered should be tagged with FullCoveredAttribute warnif count > 0 from t in JustMyCode.Types where !t.HasAttribute ("NDepend.Attributes.FullCoveredAttribute".AllowNoMatch()) && t.PercentageCoverage == 100 && !t.IsGeneratedByCompiler select new { t, t.NbLinesOfCode }

15 NDepend rules and Code Coverage // From now, all types added or refactored should be 100% covered by tests warnif count > 0 from t in JustMyCode.Types where // Match methods new or modified since Baseline for Comparison... (t.WasAdded() || t.CodeWasChanged()) && //...that are not 100% covered by tests t.PercentageCoverage < 100 let methodsCulprit = t.Methods.Where(m => m.PercentageCoverage < 100) select new { t, t.PercentageCoverage, methodsCulprit }

16 NDepend rules and Code Coverage // Types that used to be 100% covered but not anymore warnif count > 0 from t in JustMyCode.Types where t.IsPresentInBothBuilds() && t.OlderVersion().PercentageCoverage == 100 && t.PercentageCoverage < 100 let culpritMethods = t.Methods.Where(m => m.PercentageCoverage < 100) select new {t, t.PercentageCoverage, culpritMethods }

17 Designing to make the UI testable

18  A kernel object, referencing a grape of objects, that is shared amongst all UI panels  The kernel hold access to  Application states (currently running an analysis?, session opened? …)  Application context (user preferences, licensing options, theme…)  Application actions (open/close session, show/hide panel…)  Session states (analysis result loaded, diffed?…)  Session actions (build a graph, edit a code query…)  … NDepend UI Design

19

20  Suitable to write UI integration tests, that pilot the UI.  Not much assertions are done in unit-tests bodies …  …but thousands of code contracts nested in UI code are covered by test run. Hence they are checked! NDepend UI Design and Tests foreach (var panelKind in new[] { PanelKind.StartPage, PanelKind.ProjectProperties, PanelKind.Matrix, PanelKind.Graph…}) { InvokeOnUIThread( () => m_Kernel.App.Actions.SetActivePanel(EventSender.Main, panelKind)); InvokeOnUIThread( () => m_Kernel.App.Actions.ShowPanel(EventSender.Main, panelKind)); }

21 NDepend UI Design Ruled  Generic rules can be written to enforce design decisions like: Panels shouldn’t use each other  Demo // Panels shouldn't use each others warnif count > 0 let panelsNamespaces = Application.Namespaces.WithNameWildcardMatch("NDepend.UI.Panels.*") from nUser in panelsNamespaces.UsingAny(panelsNamespaces) from nUsed in panelsNamespaces.UsedByAny(panelsNamespaces) where nUser.IsUsing(nUsed) select new { nUser, nUsed }

22 Detect Regressions early with Code Rules

23  Code Rules like  Types that used to be 100% covered but not anymore  Methods that could have a lower visibility  Avoid transforming an immutable type into a mutable one  Potentially dead Types  Class with no descendant should be sealed if possible  Constructor should not call a virtual methods  …  Not so much about keeping the code clean for the sake of it. Code Rules

24  More often than not, a green rule that suddenly gets violated, sheds light on a non-trivial bug.  It is all about regression.  It is not intrinsically about the rule violated…  …but about what happened recently, that provoked a green code rule to be now violated.  Demo! The importance of Green Zone

25 On Clean Code Structure

26  What’s common about most of projects packaged into one large assembly?  Nancy.dll  NHibernate.dll  Mscorlib.dll  System.dll  The code is completely entangled into namespaces dependencies cycle! Common structure problem

27  The problem comes from the lack of definition of the notion of components in.NET.  A component is a group of cohesive classes (cohesive in the sense, one get used => all get used).  There is no clear definitions about how to package these classes other than the notion of.NET assembly (or VS project).  Consequences: Real-world applications are made of hundreds of.NET assemblies Only one structure rule: Avoid cycles

28  But.NET assembly is a physical artefact:  One assembly  one physical file  Not fun to deploy hundreds of assemblies  Not fun to reference dozens of assemblies of a library (and maintain these referenced)  A component is a logical artefact  Finer-grained than assembly => an assembly should contain many components  This is why I advocate namespace to be the right granularity to define component Only one structure rule: Avoid cycles

29  250 namespaces spawned over 10 assemblies Design of NDepend

30  For a public API, its practicaly impossible!  For an application the code rule Avoid namespace mutually dependent usually gives good hints about what to do, How?  Because developers usually know about high level and low level code.  For example, the rule say that mscorlib System namespace shouldn’t use any other namespace  Typically, resolving all namespaces mutually dependent will result into a well layered code structure. How to get rid of cycles?

31  Two ways to get rid of an unwanted namespace dependency:  Move type(s) from one namespace to another  Create an Inversion of Control by defining abstractions (interfaces), in a new lower namespace  Try it! This is much cheaper to achieve than expected, and getting rid of spaghettis is priceless!  Because only code structure is touched (class def, interfaces def, namespace def)  Code flow (method bodies) is left untouched. How to get rid of cycles?

32  Introduction to NDepend  Contract, Unit Test and Code Coverage  Designing to make the UI testable  Detect regressions early with Code Rule  On Code Structure Questions?


Download ppt "How to make the most of Code Analysis Patrick Smacchia NDepend Creator and Lead Developer Build Stuff Lithuania - 11th Dec 2013."

Similar presentations


Ads by Google