Avoid methods with too many overloads
Matches sets of methods with 7 overloads or more, typically introduced to accommodate combinations of input parameters: hard to maintain, ambiguous, less readable.
The visitor design pattern http://en.wikipedia.org/wiki/Visitor_pattern requires a Visit() overload per sub type, so overloads starting with "visit" or "dispatch" (case-insensitive) are skipped; adapt to your naming convention. Sometimes many overloads are fine, e.g. a conversion method covering all numeric types. NbOverloads metric: https://www.ndepend.com/docs/code-metrics#NbOverloads
Overrides of third-party methods and constructors calling a base constructor are not counted (lower-level problems).
The visitor design pattern http://en.wikipedia.org/wiki/Visitor_pattern requires a Visit() overload per sub type, so overloads starting with "visit" or "dispatch" (case-insensitive) are skipped; adapt to your naming convention. Sometimes many overloads are fine, e.g. a conversion method covering all numeric types. NbOverloads metric: https://www.ndepend.com/docs/code-metrics#NbOverloads
Overrides of third-party methods and constructors calling a base constructor are not counted (lower-level problems).
How to fix
Use optional parameters, named arguments or a parameter array (params) instead.
Estimated Debt: 3 minutes per method overload.
Estimated Debt: 3 minutes per method overload.
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 with too many overloads</Name>
// <Id>ND1005:AvoidMethodsWithTooManyOverloads</Id>
warnif count > 0
let max = 7
let lookup = JustMyCode.Methods.Where(m =>
m.NbOverloads >= max &&
!m.IsOperator && // Don't report operator overload
// Don't match overloads due to the visitor pattern, based on a naming convention.
!m.SimpleName.StartsWithAny("visit", "dispatch", StringComparison.OrdinalIgnoreCase)
).ToLookup(m => m.ParentType.FullName + "."+ m.SimpleName)
from @group in lookup
let overloads = @group.ToArray()
// Prune not fixable situations.
let overloadsPruned = overloads.Where(
m =>
// Don't match a method that overrides a third-party methods
!m.OverriddensBase.Any(mo => mo.IsThirdParty) &&
// Don't match a constructor that calls a base constructor.
!(m.IsConstructor && m.MethodsCalled.Any(
mc => mc.IsConstructor &&
m.ParentType.DeriveFrom(mc.ParentType)))
).ToArray()
where overloadsPruned.Length > max
orderby overloads.Length descending
select new {
m = @group.First(),
overloadsPruned,
nbOverloads = overloadsPruned.Length,
Debt = (3*overloads.Length).ToMinutes().ToDebt(),
Severity = Severity.Medium
}
//<Expl>
// The *{0}* has {2} overloads which leads to ambiguity and maintenance burden.
// Consider instead optional parameters, named arguments or parameter array (with the *params* keyword).
//</Expl>
//<Desc>
// Matches sets of methods with 7 overloads or more, typically introduced to
// accommodate combinations of input parameters: hard to maintain, ambiguous,
// less readable.
//
// The **visitor design pattern** http://en.wikipedia.org/wiki/Visitor_pattern
// requires a *Visit()* overload per sub type, so overloads starting with
// "visit" or "dispatch" (case-insensitive) are skipped; adapt to your naming
// convention. Sometimes many overloads are fine, e.g. a conversion method
// covering all numeric types. *NbOverloads* metric:
// https://www.ndepend.com/docs/code-metrics#NbOverloads
//
// Overrides of third-party methods and constructors calling a base
// constructor are not counted (lower-level problems).
//</Desc>
//<HowToFix>
// Use optional parameters, named arguments or a parameter array (*params*)
// instead.
//
// Estimated Debt: 3 minutes per method overload.
//</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