Avoid types too big
Matches types with more than 200 lines of code (JustMyCode methods only): extremely complex to develop and maintain. Maybe a God Class: a class controlling too many others, grown into The Class That Does Everything. NbLinesOfCode metric: https://www.ndepend.com/docs/code-metrics#NbLinesOfCode
How to fix
Split into smaller types. Refactoring a God Class takes patience:
- Split the logic into smaller classes (possibly private nested ones the God Class becomes composed of).
- Partition by responsibilities: look for subsets of methods strongly coupled with subsets of fields.
- If mostly logic (few states), consider static classes with only pure static methods (no field read/assigned), which are easily testable.
- Keep the God Class interface at first, delegating to the extracted classes, until it is a pure facade; then keep or discard it.
- Write tests for each method before extracting it.
Estimated Debt: linear from 1 hour (200 loc) to 10 hours (2.000+ loc). Static types with no mutable fields cost less: their static methods are easily moved between types.
- Split the logic into smaller classes (possibly private nested ones the God Class becomes composed of).
- Partition by responsibilities: look for subsets of methods strongly coupled with subsets of fields.
- If mostly logic (few states), consider static classes with only pure static methods (no field read/assigned), which are easily testable.
- Keep the God Class interface at first, delegating to the extracted classes, until it is a pure facade; then keep or discard it.
- Write tests for each method before extracting it.
Estimated Debt: linear from 1 hour (200 loc) to 10 hours (2.000+ loc). Static types with no mutable fields cost less: their static methods are easily moved between types.
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 types too big</Name>
// <Id>ND1000:AvoidTypesTooBig</Id>
warnif count > 0 from t in JustMyCode.Types where
// First filter on type to optimize
t.NbLinesOfCode > 200
// # IL Instructions is commented, because with LINQ syntax, a few statements can compile to hundreds of IL instructions.
// || t.NbILInstructions > 3000
// What matters is the # lines of code in JustMyCode
let locJustMyCode = t.MethodsAndConstructors.Where(m => JustMyCode.Contains(m)).Sum(m => m.NbLinesOfCode)
where locJustMyCode > 200
let isStaticWithNoMutableState = (t.IsStatic && t.Fields.Any(f => !f.IsImmutable))
let staticFactor = (isStaticWithNoMutableState ? 0.2 : 1)
orderby locJustMyCode descending
select new {
t,
locJustMyCode,
t.NbILInstructions,
t.Methods,
t.Fields,
Debt = (staticFactor*locJustMyCode.Linear(200, 1, 2000, 10)).ToHours().ToDebt(),
// The annual interest varies linearly from interest for severity major for 300 loc
// to interest for severity critical for 2000 loc
AnnualInterest = staticFactor*(locJustMyCode.Linear(
200, Severity.Medium.AnnualInterestThreshold().Value.TotalMinutes,
2000, Severity.Critical.AnnualInterestThreshold().Value.TotalMinutes)).ToMinutes().ToAnnualInterest()
}
//<Expl>
// The *{0}* has {1} statements considered as handcrafted code.
// This is too large suggesting the need to split it into multiple
// smaller implementations, each dedicated to a specific responsibility.
// </Expl>
//<Desc>
// Matches types with more than 200 lines of code (**JustMyCode methods
// only**): extremely complex to develop and maintain. Maybe a **God Class**:
// a class controlling too many others, grown into *The Class That Does
// Everything*. NbLinesOfCode metric:
// https://www.ndepend.com/docs/code-metrics#NbLinesOfCode
//</Desc>
//<HowToFix>
// Split into smaller types. Refactoring a *God Class* takes patience:
//
// - Split the logic into smaller classes (possibly private nested ones the
// *God Class* becomes composed of).
//
// - Partition by responsibilities: look for subsets of methods strongly
// coupled with subsets of fields.
//
// - If mostly logic (few states), consider static classes with only pure
// static methods (no field read/assigned), which are easily testable.
//
// - Keep the *God Class* interface at first, delegating to the extracted
// classes, until it is a pure facade; then keep or discard it.
//
// - Write tests for each method before extracting it.
//
// Estimated Debt: linear from 1 hour (200 loc) to 10 hours (2.000+ loc).
// Static types with no mutable fields cost less: their static methods are
// easily moved between types.
//</HowToFix>
Open in the interactive Rules Explorer · All default rules
Code Smells: all 10 items
- Avoid types too big ND1000
- Avoid types with too many methods ND1001
- Avoid types with too many fields ND1002
- Avoid methods too big, too complex ND1003
- Avoid methods with too many parameters ND1004
- Avoid methods with too many overloads ND1005
- Avoid methods potentially poorly commented ND1006
- Avoid types with poor cohesion ND1007
- Avoid methods with too many local variables ND1008
- Avoid unmaintainable code ND1009