From now, all types added should respect basic quality principles

Rule ND1100 Code Smells Regression

Runs only in diff mode (baseline defined), on types added since baseline (easily modified to also match refactored types).

Matched types violate basic quality principles: too many methods, too many fields, or too many types used — often symptoms of too many responsibilities. Constructors, property/event accessors, constant and static-readonly fields, and enumerations are not counted.

How to fix

Split the type into smaller types implementing the same logic together.

Constant 10 minutes Debt: the fix effort is already estimated by the Code Smells rules. But severity is High, higher for new types: the time to improve them is now, before the next production release.

CQLinq source

This rule is written in CQLinq, C# LINQ over the NDepend code model. It ships with every new NDepend project: you can read it, adapt it, or use it as a starting point for your own custom rules.

// <Name>From now, all types added should respect basic quality principles</Name>
// <Id>ND1100:FromNowAllTypesAddedShouldRespectBasicQualityPrinciples</Id>
warnif count > 0

// Gather typesMoved, types whose parent namespaces changed since baseline:
// removed on one side and added on the other, such a type is not a new type.
let typesRemoved = context.CompareContext.OlderCodeBase.Application.Types
   .Where(t => t.WasRemoved()).Select(t => t.Name).ToHashSetEx()
let typesMoved = Application.Types
   .Where(t => t.WasAdded() && typesRemoved.Contains(t.Name)).ToHashSetEx()

from t in JustMyCode.Types where

// Only match types added since Baseline.
// Uncomment this line to match also refactored types since Baseline.
// (t.WasAdded() || t.CodeWasChanged()) &&
   t.WasAdded() &&

// Don't match types moved from one namespace to another
  !typesMoved.Contains(t) &&

// Eliminate interfaces, enumerations or types only with constant fields
// by making sure we are matching type with significant code.
   t.NbLinesOfCode >= 50 &&

// Optimization: Fast discard of non-relevant types 
   t.Fields.Count() >= 7 && 
   t.Methods.Count() >= 18
      
// Count instance fields and non-constant static fields
let fields = t.Fields.Where(f => 
      !f.IsLiteral &&
      !(f.IsStatic && f.IsInitOnly))

// Don't match these methods
let methods = t.Methods.Where(
   m => !(// m.IsConstructor || m.IsClassConstructor ||  // ctor/cctor not enumerated through IType.Methods
          m.IsGeneratedByCompiler ||
          m.IsPropertyGetter || m.IsPropertySetter ||
          m.IsEventAdder || m.IsEventRemover))
  
let typesUsed = t.TypesUsed.ExceptThirdParty().ToArray()

where 

// Low Quality types     Metrics' definitions are available here:
//     https://www.ndepend.com/docs/code-metrics#MetricsOnTypes
(  // Types with too many methods
   fields.Count() >= 7 &&
   methods.Count() >= 18 &&
               
   // Complex Types that use more than 40 application other types
   typesUsed.Length >= 40
)
select new { 
   t, 
   t.NbLinesOfCode, 

   t.MaintainabilityIndex,

   instanceMethods = methods.Where(m => !m.IsStatic), 
   staticMethods = methods.Where(m => m.IsStatic),
  
   instanceFields = fields.Where(f => !f.IsStatic),
   staticFields = fields.Where(f => f.IsStatic),
  
   typesUsed,

   // Constant Debt estimation, since for such type rules in category "Code Smells" 
   // accurately estimate the Debt.
   Debt     = 10.ToMinutes().ToDebt(),

   // The Severity is higher for new types than for refactored types 
   AnnualInterest= (t.WasAdded() ? 3 : 1) *
                    Severity.High.AnnualInterestThreshold()
}

//<Expl>
// The new *{0}* doesn't meet quality standard detailed in other issues.
//</Expl>

//<Desc>
// Runs only in *diff mode* (baseline defined), on types added since baseline
// (easily modified to also match refactored types).
//
// Matched types violate basic quality principles: too many methods, too many
// fields, or too many types used — often symptoms of too many
// responsibilities. Constructors, property/event accessors, constant and
// static-readonly fields, and enumerations are not counted.
//</Desc>

//<HowToFix>
// Split the type into smaller types implementing the same logic together.
//
// Constant 10 minutes Debt: the fix effort is already estimated by the
// **Code Smells** rules. But severity is **High**, higher for new types:
// the time to improve them is **now**, before the next production release.
//</HowToFix>

Code Smells Regression: all 9 items