Avoid types with too many fields
Matches types with more than 15 fields (constants, static-readonly and enumerations excluded): hard to understand and maintain, symptom of too many responsibilities.
How to fix
Group subsets of fields into smaller types and dispatch the methods logic into them. More advices in Types too Big, HowToFix section.
Estimated Debt: linear from 1 hour (15 fields) to 10 hours (200+).
Estimated Debt: linear from 1 hour (15 fields) to 10 hours (200+).
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 types with too many fields</Name>
// <Id>ND1002:AvoidTypesWithTooManyFields</Id>
warnif count > 0
// Unity class tend to have more fields.
// Hence set a threshold of 30 instead of 15 for other kinds of projects.
let threshold = ThirdParty.Assemblies.Any(a => a.Name.StartsWith("UnityEngine")) ? 30 : 15
from t in JustMyCode.Types
// Optimization: Fast discard of non-relevant types
where !t.IsEnumeration &&
t.Fields.Count() > threshold
// Count instance fields and non-constant static fields
let fields = t.Fields.Where(f =>
!f.IsGeneratedByCompiler &&
!f.IsLiteral &&
!(f.IsStatic && f.IsInitOnly) &&
JustMyCode.Contains(f) )
where fields.Count() > threshold
let methodsAssigningFields = fields.SelectMany(f => f.MethodsAssigningMe)
orderby fields.Count() descending
select new {
t,
instanceFields = fields.Where(f => !f.IsStatic),
staticFields = fields.Where(f => f.IsStatic),
nbFields = fields.Count(),
methodsAssigningFields ,
// See definition of Size of Instances metric here:
// https://www.ndepend.com/docs/code-metrics#SizeOfInst
t.SizeOfInst,
Debt = fields.Count().Linear(15, 1, 200, 10).ToHours().ToDebt(),
// The annual interest varies linearly from interest for severity major for 30 methods
// to interest for severity critical for 200 methods
AnnualInterest = fields.Count().Linear(15, Severity.Medium.AnnualInterestThreshold().Value.TotalMinutes,
200, Severity.Critical.AnnualInterestThreshold().Value.TotalMinutes).ToMinutes().ToAnnualInterest()
}
//<Expl>The *{0}* has {3} fields.
// This may be excessive, and you might need to consider grouping
// related fields into smaller and more cohesive implementations.
// </Expl>
//<Desc>
// Matches types with more than 15 fields (constants, static-readonly and
// enumerations excluded): hard to understand and maintain, symptom of too
// many responsibilities.
//</Desc>
//<HowToFix>
// Group subsets of fields into smaller types and dispatch the methods logic
// into them. More advices in **Types too Big**, *HowToFix* section.
//
// Estimated Debt: linear from 1 hour (15 fields) to 10 hours (200+).
//</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