API Breaking Changes: Interfaces and Abstract Classes

Rule ND1503 API Breaking Changes

Runs only in diff mode (baseline defined). Warns if a publicly visible interface or abstract class got abstract methods added or removed: client code implementing or deriving from it will be broken.

How to fix

Keep public contracts of interfaces and abstract classes stable, now and in the future. If a contract must change, tag abstract methods to be removed with System.ObsoleteAttribute and a workaround message for a few releases first.

Severity is High (not Critical, since an interface is not necessarily meant to be implemented by API consumers).

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>API Breaking Changes: Interfaces and Abstract Classes</Name>
// <Id>ND1503:APIBreakingChangesInterfacesAndAbstractClasses</Id>

warnif count > 0 from tNewer in Application.Types where 
 (tNewer.IsInterface || tNewer.IsClass && tNewer.IsAbstract) && 
  tNewer.IsPubliclyVisible && 
  tNewer.IsPresentInBothBuilds()

let tOlder = tNewer.OlderVersion() where tOlder.IsPubliclyVisible

let methodsRemoved = tOlder.Methods.Where(m => m.IsAbstract && m.WasRemoved())
let methodsAdded = tNewer.Methods.Where(m => m.IsAbstract && m.WasAdded())

where methodsAdded.Count() > 0 || methodsRemoved.Count() > 0
select new { 
   tNewer, 
   methodsAdded, 
   methodsRemoved,
   usage = tNewer.IsInterface ? "implementing" : "deriving from",
   Debt = 10.ToMinutes().ToDebt(),
   Severity = Severity.High
}

//<Expl>
// The *{0}* is *public* and its member set have been 
// changed since the baseline.
// This breaks client classes {3} it.
// New methods: *{1}* Removed methods: *{2}*
//</Expl>

//<Desc>
// Runs only in *diff mode* (baseline defined). Warns if a publicly visible
// interface or abstract class got abstract methods added or removed: client
// code implementing or deriving from it will be broken.
//</Desc>

//<HowToFix>
// Keep public contracts of interfaces and abstract classes stable, now and
// in the future. If a contract must change, tag abstract methods to be
// removed with *System.ObsoleteAttribute* and a *workaround message* for a
// few releases first.
//
// Severity is **High** (not **Critical**, since an interface is not
// necessarily meant to be implemented by API consumers).
//</HowToFix>

API Breaking Changes: all 9 items