Architecture & Patterns110 min total · 26 parts
ACID, SOLID, and Design Patterns: A Complete Software Design Reference
Part 10 of 26 · ~2 min
Interface Segregation Principle
No implementer should end up writing code for a capability that plainly doesn't apply to it. Pack unrelated abilities into one wide interface and every class that implements it is stuck between two bad options: actually build out every listed ability whether it makes sense for that class or not, or fake the ones that don't.
A sixteen-year-old signs up to volunteer at the shelter. She can check in at the kiosk and she's cleared the minors' background-check track — but she legally can't drive the shelter's van on supply runs, which the original interface assumed every volunteer could do:
// Violates ISP — a minor volunteer has no honest way to implement
// DriveShelterVan(), but the interface forces some implementation to exist.
public interface IVolunteer
{
void CheckIn(int shiftId);
void SubmitBackgroundCheckResult(bool passed);
void DriveShelterVan(string route);
}
public class MinorVolunteer : IVolunteer
{
public void CheckIn(int shiftId) { /* real implementation */ }
public void SubmitBackgroundCheckResult(bool passed) { /* real implementation */ }
public void DriveShelterVan(string route) => throw new NotSupportedException(); // a lie the compiler can't catch
}
// Segregated into focused interfaces — implement only what genuinely applies.
public interface ICheckInable { void CheckIn(int shiftId); }
public interface IBackgroundCheckable { void SubmitBackgroundCheckResult(bool passed); }
public interface IVanDriver { void DriveShelterVan(string route); }
public class AdultVolunteer : ICheckInable, IBackgroundCheckable, IVanDriver
{
public void CheckIn(int shiftId) { }
public void SubmitBackgroundCheckResult(bool passed) { }
public void DriveShelterVan(string route) { }
}
public class MinorVolunteer : ICheckInable, IBackgroundCheckable
{
public void CheckIn(int shiftId) { } // no forced implementation of a capability that doesn't apply
public void SubmitBackgroundCheckResult(bool passed) { }
}
That thrown NotSupportedException is exactly the smell worth flagging when reviewing someone else's pull request: an override whose entire body amounts to refusing the method makes a statement about the interface, not about whoever wrote the implementing class. The right response is splitting the interface, never asking the class to somehow try harder.