Avoid making complex methods even more complex
Runs only in diff mode (baseline defined). Warns when an already complex method (Cyclomatic Complexity > 6) became even more complex since baseline. Metric: https://www.ndepend.com/docs/code-metrics#CC
Requires PDB files and source code at analysis time. See: https://www.ndepend.com/docs/ndepend-analysis-inputs-explanation
To visualize changes, right-click a matched method and select:
- Compare older and newer versions of source file
- or Compare older and newer versions decompiled with Reflector
Requires PDB files and source code at analysis time. See: https://www.ndepend.com/docs/ndepend-analysis-inputs-explanation
To visualize changes, right-click a matched method and select:
- Compare older and newer versions of source file
- or Compare older and newer versions decompiled with Reflector
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: linear from 15 to 60 minutes with the extra complexity. Severity is High: fix these issues now, before such code gets released in production.
Estimated Debt: linear from 15 to 60 minutes with the extra complexity. Severity is High: fix these issues now, before such code gets released in production.
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 making complex methods even more complex</Name>
// <Id>ND1104:AvoidMakingComplexMethodsEvenMoreComplex</Id>
warnif count > 0
let complexityScoreProc = new Func<IMethod, double>(m =>
(m.CyclomaticComplexity + m.ILCyclomaticComplexity/3 + 2*m.ILNestingDepth).Value)
from m in JustMyCode.Methods where
// Don't match async methods here to avoid
// false positives because of special compiler tricks.
!m.IsAsync &&
!m.IsAbstract &&
m.IsPresentInBothBuilds() &&
m.CodeWasChanged() &&
m.OlderVersion().CyclomaticComplexity > 6
let complexityScore = complexityScoreProc(m)
let oldComplexityScore = complexityScoreProc(m.OlderVersion())
where complexityScore > oldComplexityScore
let complexityScoreDiff = complexityScoreProc(m) - complexityScoreProc(m.OlderVersion())
orderby complexityScoreDiff descending
select new {
m,
oldComplexityScore ,
complexityScore ,
diff= complexityScoreDiff,
Debt = complexityScoreDiff.Linear(1, 15, 50, 60).ToMinutes().ToDebt(),
// The annual interest varies linearly from interest for severity Medium for a tiny complexity increment
// to interest for severity critical for 2000 loc
AnnualInterest = complexityScoreDiff.Linear(1, Severity.High.AnnualInterestThreshold().Value.TotalMinutes,
50, 4*(Severity.High.AnnualInterestThreshold().Value.TotalMinutes)).ToMinutes().ToAnnualInterest()
}
//<Expl>
// The *{0}* was already too complex in the baseline
// and is now even more complex.
// Consider splitting it into smaller, less complex methods.
//</Expl>
//<Desc>
// Runs only in *diff mode* (baseline defined). Warns when an already complex
// method (*Cyclomatic Complexity* > 6) became even more complex since
// baseline. Metric: https://www.ndepend.com/docs/code-metrics#CC
//
// Requires PDB files and source code at analysis time. See:
// https://www.ndepend.com/docs/ndepend-analysis-inputs-explanation
//
// To visualize changes, right-click a matched method and select:
//
// - Compare older and newer versions of source file
//
// - or Compare older and newer versions decompiled with Reflector
//</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: linear from 15 to 60 minutes with the extra complexity.
// Severity is **High**: fix these issues **now**, before such code gets
// released in production.
//</HowToFix>
Open in the interactive Rules Explorer · All default rules
Code Smells Regression: all 9 items
- From now, all types added should respect basic quality principles ND1100
- From now, all types added should be 100% covered by tests ND1101
- From now, all methods added should respect basic quality principles ND1102
- Avoid decreasing code coverage by tests of types ND1103
- Avoid making complex methods even more complex ND1104
- Avoid making large methods even larger ND1105
- Avoid adding methods to a type that already had many methods ND1106
- Avoid adding instance fields to a type that already had many instance fields ND1107
- Avoid transforming an immutable type into a mutable one ND1108