Avoid methods too big, too complex
Matches methods where ILNestingDepth > 2 and CyclomaticComplexity > 17: hard to understand and maintain, maybe a God Method (The Method That Does Everything, grown by adding ifs instead of new methods). Metrics: https://www.ndepend.com/docs/code-metrics#CC https://www.ndepend.com/docs/code-metrics#ILNestingDepth
How to fix
Split into smaller methods or even new classes. Question each local variable's scope: it may become an instance field of the new class(es). Large switch…case can become types implementing a common interface, polymorphism replacing the switch cases tests. Write tests for each method before extracting it.
Estimated Debt: 20 minutes to 3 hours, linear in a weighted complexity score.
Estimated Debt: 20 minutes to 3 hours, linear in a weighted complexity score.
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 methods too big, too complex</Name>
// <Id>ND1003:AvoidMethodsTooBigTooComplex</Id>
warnif count > 0 from m in JustMyCode.Methods where
// Don't match async methods here to avoid
// false positives because of special compiler tricks.
!m.IsAsync &&
m.ILNestingDepth > 2 &&
m.CyclomaticComplexity > 17
let complexityScore = m.NbLinesOfCode/2 + m.CyclomaticComplexity + m.ILCyclomaticComplexity/3 + 3*m.ILNestingDepth
orderby complexityScore descending,
m.CyclomaticComplexity descending,
m.ILCyclomaticComplexity descending,
m.ILNestingDepth descending
select new {
m,
m.NbLinesOfCode,
m.CyclomaticComplexity,
m.ILCyclomaticComplexity,
m.ILNestingDepth,
complexityScore,
Debt = complexityScore.Linear(30, 20, 400, 3*60).ToMinutes().ToDebt(),
// The annual interest varies linearly from interest for severity minor
// to interest for severity major
AnnualInterest = complexityScore .Linear(30, Severity.Medium.AnnualInterestThreshold().Value.TotalMinutes,
200, 2*(Severity.High.AnnualInterestThreshold().Value.TotalMinutes)).ToMinutes().ToAnnualInterest()
}
//<Expl>
// The *{0}* has a high *cyclomatic complexity* score of {2} and should be refactored into a set of smaller methods.
//</Expl>
//<Desc>
// Matches methods where *ILNestingDepth* > 2 and *CyclomaticComplexity* > 17:
// hard to understand and maintain, maybe a **God Method** (*The Method That
// Does Everything*, grown by adding *if*s instead of new methods).
// Metrics: https://www.ndepend.com/docs/code-metrics#CC
// https://www.ndepend.com/docs/code-metrics#ILNestingDepth
//</Desc>
//<HowToFix>
// Split into smaller methods or even new classes. Question each local
// variable's scope: it may become an instance field of the new class(es).
// Large *switch…case* can become types implementing a common interface,
// polymorphism replacing the *switch cases tests*. Write tests for each
// method before extracting it.
//
// Estimated Debt: 20 minutes to 3 hours, linear in a weighted complexity
// score.
//</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