Avoid excessive class coupling

Rule ND1410 Architecture

Assesses class coupling for types and methods by counting the unique application types consumed and their namespaces. High coupling suggests too many responsibilities, violating the Single Responsibility Principle: https://blog.ndepend.com/solid-design-the-single-responsibility-principle-srp/

How to fix

Break the type or method into smaller, more focused components each following a single responsibility.

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>Avoid excessive class coupling</Name>
// <Id>ND1410:AvoidExcessiveClassCoupling</Id>

warnif count > 0 
from x in JustMyCode.Types.Concat(JustMyCode.Methods.Cast<ICodeContainer>())

// Don't match too linear method or type, 
// hence require a minimum of cyclomatic complexity
let cyclomaticComplexity = x.IsMethod ? 
     x.AsMethod.CyclomaticComplexity : 
     x.AsType.CyclomaticComplexity
where cyclomaticComplexity >= (x.IsMethod ? 10 : 25)

// Optimization before really counting the number of types used
where x.IsType ? x.AsType.NbTypesUsed >= 90 :
                 x.AsMethod.NbMethodsCalled + x.AsMethod.FieldsUsed.Count() >= 40

let typesUsed = 
   (x.IsMethod ? 
     x.AsMethod.MembersUsed.Where(m1 => !m1.IsThirdParty).Select(m1 => m1.ParentType).Distinct() :
     x.AsType.TypesUsed.Where(t1 => !t1.IsThirdParty)).ToArray()

where typesUsed.Length >= (x.IsMethod ? 40 : 90)

// Require that not all types used are in the same namespace
// to enforce several responsibilities 
let namespacesUsed = typesUsed.ParentNamespaces().ToArray()
where namespacesUsed.Length >= (x.IsMethod ? 5 : 10)

orderby typesUsed.Length descending
select new { 
   x, 
   typesUsed,
   namespacesUsed,
   x.NbLinesOfCode,
   cyclomaticComplexity,
   x.MaintainabilityIndex,
   nbTypes = typesUsed.Length,
   nbNamespaces = namespacesUsed.Length,
   Debt = (x.IsMethod ? 
    typesUsed.Length.Linear(40, 8,  200, 60) :
    typesUsed.Length.Linear(90, 15,  500, 120)
       ).ToMinutes().ToDebt(),
   Severity = Severity.Medium
}

//<Expl>
// The *{0}* makes use of *{6}* application types spread across *{7}* namespaces.  
// This suggests that it may be handling too many responsibilities.   
//</Expl>

//<Desc>
// Assesses class coupling for types and methods by counting the unique
// application types consumed and their namespaces. High coupling suggests
// too many responsibilities, violating the Single Responsibility Principle:
// https://blog.ndepend.com/solid-design-the-single-responsibility-principle-srp/
//</Desc>

//<HowToFix>
// Break the type or method into smaller, more focused components each
// following a single responsibility.
//</HowToFix>

Architecture: all 13 items