Avoid interfaces too big
Matches interfaces with more than 14 methods, properties or events (a property or event counts as one member). Interfaces should have a single responsibility; overly large ones have too many.
The Interface Segregation Principle (ISP) warns that a large interface used by consumers each needing only specific methods couples those consumers unnecessarily. Large interfaces also lead to larger classes handling too many unrelated tasks.
The Interface Segregation Principle (ISP) warns that a large interface used by consumers each needing only specific methods couples those consumers unnecessarily. Large interfaces also lead to larger classes handling too many unrelated tasks.
How to fix
Refactor into smaller single-responsibility interfaces, e.g. split IFoo handling read and write into IFooReader and IFooWriter. A large public interface with many clients may make splitting impactful or unfeasible.
Estimated Debt: linear from 20 minutes (10 methods) to 7 hours (100+), halved if the interface is not publicly visible (only the current project is impacted).
Estimated Debt: linear from 20 minutes (10 methods) to 7 hours (100+), halved if the interface is not publicly visible (only the current project is impacted).
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 interfaces too big</Name>
// <Id>ND1200:AvoidInterfacesTooBig</Id>
warnif count > 0
from i in JustMyCode.Types
where i.IsInterface && i.NbMethods >= 14 // Optimization First threshold
// Don't count property or event accessors within the sequence methods
let methods = i.Methods.Where(m => !m.IsPropertyGetter && !m.IsPropertySetter && !m.IsEventAdder && !m.IsEventRemover)
let membersCount = methods.Count() + i.Properties.Count() + i.Events.Count()
where membersCount >= 14
let publicFactor = i.IsPubliclyVisible ? 1 : 0.5
orderby membersCount descending
select new {
i,
Members= methods.Concat<IMember>(i.Properties).Concat(i.Events),
Events = i.Events,
membersCount,
Debt = (publicFactor*membersCount.Linear(10, 20, 100, 7*60)).ToMinutes().ToDebt(),
// The annual interest varies linearly from interest for severity Medium for an interface with 10 methods
// to interest for severity Critical for an interface with 100 methods and more
AnnualInterest = (publicFactor*membersCount .Linear(
10, Severity.Medium.AnnualInterestThreshold().Value.TotalMinutes,
100, Severity.Critical.AnnualInterestThreshold().Value.TotalMinutes))
.ToMinutes().ToAnnualInterest()
}
//<Expl> The *{0}* has {3} members. It is too large and it might indicate
// the need to split it into several smaller interfaces that each,
// handles a single responsibility.</Expl>
//<Desc>
// Matches interfaces with more than 14 methods, properties or events (a
// property or event counts as one member). Interfaces should have a single
// responsibility; overly large ones have too many.
//
// The *Interface Segregation Principle* (ISP) warns that a large interface
// used by consumers each needing only specific methods couples those
// consumers unnecessarily. Large interfaces also lead to larger classes
// handling too many unrelated tasks.
//</Desc>
//<HowToFix>
// Refactor into smaller *single-responsibility* interfaces, e.g. split *IFoo*
// handling read and write into *IFooReader* and *IFooWriter*. A large public
// interface with many clients may make splitting impactful or unfeasible.
//
// Estimated Debt: linear from 20 minutes (10 methods) to 7 hours (100+),
// halved if the interface is not publicly visible (only the current project
// is impacted).
//</HowToFix>
Open in the interactive Rules Explorer · All default rules
Object Oriented Design: all 14 items
- Avoid interfaces too big ND1200
- Base class should not use derivatives ND1201
- Class shouldn't be too deep in inheritance tree ND1202
- Class with no descendant should be sealed if possible ND1203
- Overrides of Method() should call base.Method() ND1204
- Do not hide base class methods ND1205
- A stateless class or structure might be turned into a static type ND1206
- Non-static classes should be instantiated or turned to static ND1207
- Methods should be declared static if possible ND1208
- Constructor should not call a virtual method ND1209
- Avoid the Singleton pattern ND1210
- Don't assign static fields from instance methods ND1211
- Avoid empty interfaces ND1212
- Avoid types initialization cycles ND1213