Class shouldn't be too deep in inheritance tree
Warns about classes with 4 or more base classes (third-party base classes not counted: this rule is about your design).
In theory a well-thought long inheritance chain is fine; in practice it is more often a sign of confused design, hard to work with and maintain.
In theory a well-thought long inheritance chain is fine; in practice it is more often a sign of confused design, hard to work with and maintain.
How to fix
Favor Composition over Inheritance: a derived class is bound to the base class implementation, and inheritance breaks encapsulation. Composition binds to interfaces instead, preserving encapsulation with a clearer, less coupled design — a powerful way to break a long inheritance chain. See: http://en.wikipedia.org/wiki/Composition_over_inheritance and http://stackoverflow.com/questions/49002/prefer-composition-over-inheritance
Estimated Debt: linear in the depth of inheritance.
Estimated Debt: linear in the depth of inheritance.
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>Class shouldn't be too deep in inheritance tree</Name>
// <Id>ND1202:ClassShouldntBeTooDeepInInheritanceTree</Id>
warnif count > 0 from t in JustMyCode.Types
where t.IsClass
let baseClasses = t.BaseClasses.ExceptThirdParty()
where baseClasses.Count() >= 4
orderby baseClasses.Count() descending
select new {
t,
baseClasses,
// The metric value DepthOfInheritance takes account
// of third-party base classes. See its definition here:
// https://www.ndepend.com/docs/code-metrics#DIT
t.DepthOfInheritance,
Debt = (baseClasses.Count() -2)*3.ToMinutes().ToDebt(),
Severity = Severity.Medium
}
//<Expl>The *{0}* derives from *{1}*. A lengthy inheritance chain indicates a confusing design that can be challenging to manage and maintain.</Expl>
//<Desc>
// Warns about classes with 4 or more base classes (third-party base classes
// not counted: this rule is about your design).
//
// *In theory* a well-thought *long inheritance chain* is fine; *in practice*
// it is more often a sign of confused design, hard to work with and maintain.
//</Desc>
//<HowToFix>
// **Favor Composition over Inheritance**: a derived class is bound to the
// base class implementation, and inheritance breaks encapsulation.
// *Composition* binds to interfaces instead, preserving encapsulation with a
// clearer, less coupled design — a powerful way to break a *long inheritance
// chain*. See:
// http://en.wikipedia.org/wiki/Composition_over_inheritance and
// http://stackoverflow.com/questions/49002/prefer-composition-over-inheritance
//
// Estimated Debt: linear in the depth of inheritance.
//</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