310 likes | 492 Views
NDepend & CQL. © April 2008 http://www.ndepend.com. Agenda:. Introduction CQL Queries & Constraints Quality & Metrics Dependencies Layering & Refactoring Code Snapshot Comparison Code Coverage State & Mutability Dead Code Optimal Encapsulation Naming Convention Object model
E N D
NDepend & CQL © April 2008 http://www.ndepend.com
Agenda: • Introduction • CQL Queries & Constraints • Quality & Metrics • Dependencies Layering & Refactoring • Code Snapshot Comparison • Code Coverage • State & Mutability • Dead Code • Optimal Encapsulation • Naming Convention • Object model • Build Process Health • Future
Introduction • The source code is the design: a need to reveal secrets kept in the structure of source code: • A need to understand the big picture with a top-down approach, no matter the size of the code base. • A need to rationalize the architecture of software by controlling the structural complexity (graph of dependencies). • A need to capture architectural constraints and to be advised ASAP of violation. • A need to measure the code quality and coverage. • A need to control the code evolution.
CQL Queries & Constraints • Queries: • SELECT TOP 10 METHODS ORDER BY NbLinesOfCode DESC • SELECT METHODS WHERE NbLinesOfCode > 10 • SELECT METHODS WHERE IsDirectlyUsing ″System.String″ • SELECT FIELDS WHERE HasAttribute "System.ThreadStaticAttribute" • Constraints: • WARN IF Count > 0 IN SELECT METHODS WHERE NbLinesOfCode > 20
Quality & MetricsLines Of Code (LOC) and NbILInstructions • SELECT METHODS ORDER BY NbLinesOfCode DESC • SELECT TYPES ORDER BY NbILInstructions DESC Logical LOC vs. Physical LOC class Program { static void Main() { string str = "hello"; str.IndexOf("hello", 10, 13); str.IndexOf( "hello", 10, 13); } }
Quality & Metrics Volume & Comment metrics Volume: • SELECT ASSEMBLIES ORDER BY NbNamespaces DESC • SELECT NAMESPACES ORDER BY NbTypes DESC • SELECT TYPES ORDER BY NbMethods DESC • SELECT TYPES ORDER BY NbFields DESC Comment: • SELECT NAMESPACES ORDER BY NbLinesOfComment DESC • SELECT METHODS WHERE NbLinesOfCode > 10 AND PercentageComments < 30
Quality & Metrics Coupling metrics Afferant Coupling (Ca) \ Efferent Coupling (Ce) • SELECT TYPES ORDER BY TypeCa DESC • SELECT METHODS ORDER BY MethodCe DESC • SELECT NAMESPACES ORDER BY NamespaceCa DESC Ranking • SELECT TYPES ORDER BY TypeRank DESC • SELECT METHODS ORDER BY MethodRank DESC
Quality & Metrics Cyclomatic Complexity • Cyclomatic complexity is a popular procedural software metric equal to the number of decisions that can be taken in a procedure. • Concretely, in C# the CC of a method is the number of following expressions found in the body of the method: if | while | for | foreach | case | default | continue | goto | && | || | catch | ternary operator ?: | ?? • Following expressions are not counted for CC computation: else | do | switch | try | using | throw | finally | return | object creation | method call | field access SELECT METHODS WHERE CyclomaticComplexity > 20 SELECT METHODS WHERE ILCyclomaticComplexity > 25 WARN If Count > 0 IN SELECT METHODS WHERE NbLinesOfCode > 20 AND CyclomaticComplexity > 8
Quality & Metrics Lack Of Cohesion Of Methods (LCOM) • Single responsibility principle: A class should not have more than one reason to change. In such class, almost every methods access every fields. • Lack Of Cohesion Of methods (LCOM) metric: SELECT TYPES ORDER BY LCOM DESC
Quality & Metrics Others metrics Method: • SELECT METHODS WHERE NbParameters > 5 • SELECT METHODS WHERE NbVariables > 10 Field Size of Instance: • SELECT FIELDS WHERE SizeOfInst > 16 Level & Layering: • SELECT NAMESPACES ORDER BY NamespaceLevel DESC
Dependency Layering & RefactoringDependency Structure Matrix (DSM) • Browsing • Dependencies weight • CQL Queries generation • ‘Box & Arrow’ graph production • Indirect dependencies mode
Dependency Layering & Refactoring Impact analysis to plan Refactoring • What if we need to replace Moco.Cecil by another framework: • SELECT TYPES WHERE IsDirectlyUsing "ASSEMBLY:Mono.Cecil" OR IsDirectlyUsing "ASSEMBLY:Mono.Cecil.Pdb" • ‘Box & Arrow’ graph production. • Code impacted
Dependency Layering & Refactoring.NET Components: Assemblies vs. Namespace • Assemblies: Physical • Cost at development time : poor compilation performance • Cost at deployment : more file to manage • Cost at runtime : CLR overhead per assembly basis • Namespaces: Logical • No cycles dependencies detection • Internal visibility level • Key to be able to use namespaces as components: Being able to control dependencies between namespaces
Dependency Layering & Refactoring Introduction to levelization • Central design principle: Getting rid of dependency cycles between components • A and B belongs to a dependency cycles: • They can’t be developed and tested independently • They are an indivisible unit • They constitute a super component • Diseconomy of scale phenomenon: one super component costs more than several smaller components. • Right size for a component : 500 to 2000 LOC
Dependency Layering & Refactoring Demo: Levelization / dependencies cycles
Code Snapshot ComparisonIntroduction to Build comparison • SELECT METHODS WHERE WasChanged OR WasAdded OR WasDeleted • SELECT METHODS WHERE CommentsWereChanged OR VisibilityWasChanged OR CodeWasChanged • SELECT METHODS WHERE IsUsedDifferently OR IsUsedRecently OR IsNotUsedAnymore • SELECT METHODS WHERE IsObsolete OR BecameObsolete • SELECT TYPES WHERE IsDirectlyUsing "ASSEMBLY:Mono.Cecil" OR IsDirectlyUsing "ASSEMBLY:Mono.Cecil.Pdb" • ‘Box & Arrow’ graph production. • Code impacted
Code Snapshot Comparison Build Comparison CQL Constraints • Force comment change: WARN IF Count > 0 IN SELECT METHODS WHERE CodeWasChanged AND !CommentsWereChanged • API ascendant compatibility: WARN IF Count > 0 IN SELECT METHODS WHERE IsInOlderBuild AND IsPublic AND (VisibilityWasChanged OR WasRemoved) • Interface immutability: WARN IF Count > 0 IN SELECT TYPES WHERE IsInterface AND IsPublic AND WasChanged • Force quality on change: WARN IF Count > 0 IN SELECT METHODS WHERE (CodeWasChanged OR WasAdded) AND (NbLinesOfCode > 20 OR CyclomaticComplexity > 10 OR …)
Code Snapshot Comparison Build Comparison facilities • Tier code change. SELECT METHODS WHERE IsUsedRecently SELECT METHODS WHERE IsNotUsedAnymore SELECT TYPES WHERE IsUsedDifferently SELECT NAMESPACES WHERE IsUsedDifferently SELECT ASSEMBLIES WHERE IsUsedDifferently • Dependency/Coupling changes.
Code CoverageCode Coverage Metrics • Coverage data gathered from • VSTS 2005 & 2008 • NCover 2.x • Metrics • PercentageCoverage • NbLinesOfCodeCovered • NbLInesOfCodeNotCovered • PercentageBranchCoverage (Ncover only)
Code Coverage Code Coverage Facilities • Uncoverable attributes • Coverage file merging options: • OR • XOR • AND • NONE
State and MutabilityState and mutability: Definition of immutable types • Immutable types: types where instances’ state cannot be modified once created. • A stateless type (i.e a type without any instance field) is considered as immutable. • A type with at least one non-private instance field is considered as mutable (because such a field can be eventually modified outside the type). • A class that derives directly or indirectly from a mutable type is considered as mutable. • Enumeration, static type, type defined in framework assemblies and delegate classes are never considered as immutable. • Particularly, classes that derive directly or indirectly from a class defined in a tier assembly that is not the System.Object class, is never considered as immutable.
State and Mutability CQL facilities for State and mutability • Ensuringthat the type Namespace.Foois immutable: WARN IF Count != 1 IN SELECT TYPES WHERE ! IsImmutable AND FulleNameIs "Namespace.Foo" • Matchingmethodsthat breaks immutability (i.ethat modifies instance fields): SELECT METHODS FROM TYPES "Namespace.Foo" WHERE ChangesObjectStateAND !IsConstructor • Matchingmethodsthat modifies staticfields: SELECT METHODS FROM TYPES "Namespace.Foo" WHERE ChangesTypeStateAND !IsClassConstructor • Matchingmethodsthat modifies a particularfield: SELECT METHODS FROM TYPES "Namespace.Foo" WHERE IsDirectlyWritingField "Namespace.Foo.m_Field"
Potentially dead code WARN IF Count > 0 IN SELECT METHODS WHERE MethodCa == 0 AND ! IsPublic AND ! IsEntryPoint AND ! IsExplicitInterfaceImpl AND ! IsClassConstructor AND ! IsFinalizer WARN IF Count > 0 IN SELECT FIELDS WHERE FieldCa == 0 AND ! IsPublic AND ! IsLiteral AND ! IsEnumValue AND ! NameIs "value__" WARN IF Count > 0 IN SELECT TYPES WHERE TypeCa == 0 AND ! IsPublic AND ! NameIs "Program"
Optimal Encapsulation • SELECT TYPES WHERE CoulBeInternal • SELECT METHODS WHERE CoulBePrivate • Danger: public constructor and serialization • SELECT NAMESPACES WHERE CoulBeInternal • Detecting usage of System.Compilers.Services.InternalsVisibleToAttribute SELECT METHODS WHERE ShouldBePublic
Naming Conventions • Instance fieldsshouldbeginwith m_ WARN If Count > 0 IN SELECT FIELDS WHERE ! NameLike "^m_" AND ! IsStatic • Interface nameshouldbeginwith I WARN If Count > 0 IN SELECT TYPES WHERE IsInterface AND !NameLike "^I" AND !IsNested • Types namesshouldbeginwith an upperletter: WARN If Count > 0 IN SELECT TYPES WHERE !NameLike "^[A-Z] " • Exception class shouldbesuffixedwith ‘Exception’ WARN If Count > 0 IN SELECT TYPES WHERE IsExceptionClass AND !NameLike"Exception$" or WHERE DeriveFrom "System.Exception" AND !NameLike "Exception$"
Object model • Types that should be sealed WARN IF Count > 0 IN SELECT TYPES WHERE IsClass AND NbChildren ==0 AND !IsSealed AND !IsStatic • Classes thatimplement ‘ICompare<T>’ shouldbenested WARN IF Count > 0 IN SELECT TYPES WHERE Implement "System.Collections.Generic.IComparer<T>" AND !IsNested AND !IsInFrameworkAssembly • OO Hierarcy: SELECT TYPES WHERE DepthOfInheritance > 6 SELECT TYPES ORDER BY NbChildrenDesc
Build Process Health • Assemblies versionning issues such as • AssemblyA references AssemblyB v2.1 but only AssemblyB v2.0 is available. • Assembly conflicts such as: • Several different assemblies with the same name can be found (different = different hash code and/or different version). • PDB files issues such as: • Missing PDB files. • PDB files and code source files not in-sync. • PDB files and assemblies are not in-sync. • Coverage files issues such as: • Corrupted or missing coverage files. • Coverage files and code source files not in-sync. • Coverage files and assemblies are not in-sync.
Future • Enhanced Visualization (2008 Q2) • XDepend = NDepend on Java (2008 Q3) • Code Query Framework CQF (NDepend 3, 2008 Q3) Writing code query and constraints with C# and LINQ