Avoid excessive class coupling
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>
Open in the interactive Rules Explorer · All default rules
Architecture: all 13 items
- Avoid namespaces mutually dependent ND1400
- Avoid namespaces dependency cycles ND1401
- Avoid partitioning the code base through many small library Assemblies ND1402
- Enforcing Clean Architecture ND1412
- UI layer shouldn't use directly DB types ND1403
- UI layer shouldn't use directly DAL layer ND1404
- Assemblies with poor cohesion (RelationalCohesion) ND1405
- Namespaces with poor cohesion (RelationalCohesion) ND1406
- Assemblies that don't satisfy the Abstractness/Instability principle ND1407
- Avoid excessive class coupling ND1410
- Higher cohesion - lower coupling ND1408
- Avoid mutually-dependent types ND1409
- Example of custom rule to check for dependency ND9900