Watch it segregate
The large yellow ring is a fat interface. Red spokes show unused method connections. Press Segregate to split it into focused role interfaces.
Code example
IWorker forcing a Robot to implement Eat(). Toggle to compare C# and JavaScript.
// ? BAD — fat interface forces Robot to implement Eat() and Sleep()
public interface IWorker
{
void Work();
void Eat(); // robots don't eat!
void Sleep(); // robots don't sleep!
}
public class Robot : IWorker
{
public void Work() { /* does work */ }
public void Eat() { throw new NotImplementedException(); } // forced stub!
public void Sleep() { throw new NotImplementedException(); } // forced stub!
}
// ? GOOD — segregated into focused role interfaces
public interface IWorkable { void Work(); }
public interface IEatable { void Eat(); }
public interface ISleepable { void Sleep(); }
public class Human : IWorkable, IEatable, ISleepable
{
public void Work() { /* works */ }
public void Eat() { /* eats */ }
public void Sleep() { /* sleeps */ }
}
public class Robot : IWorkable // only what it needs
{
public void Work() { /* works */ }
// No forced stubs — no Eat, no Sleep
}
// ? BAD — one interface forces everything onto all implementors
class Robot {
work() { console.log('working'); }
eat() { throw new Error('Robots do not eat!'); } // forced!
sleep() { throw new Error('Robots do not sleep!'); } // forced!
}
// ? GOOD — compose only the behaviours you need
// Role mixins (simulating interfaces in JS)
const Workable = (Base) => class extends Base { work() { console.log('working'); } };
const Eatable = (Base) => class extends Base { eat() { console.log('eating'); } };
const Sleepable = (Base) => class extends Base { sleep() { console.log('sleeping'); } };
class Human extends Workable(Eatable(Sleepable(Object))) {}
// Human: work ? eat ? sleep ?
class Robot extends Workable(Object) {}
// Robot: work ? (no eat, no sleep — not forced)
const r = new Robot();
r.work(); // 'working' ?
// r.eat() ? TypeError — method doesn't exist, as intended
Key concepts
Interface Segregation
Many small, client-specific interfaces beat one general-purpose interface. Each client only imports what it needs.
Fat Interface
An interface with too many methods forces clients to implement irrelevant methods as stubs or throws — a design smell and a test burden.
Role Interface
Each interface represents a single role or capability: IWorkable, IEatable, ISleepable. Classes pick and choose what roles they play.
Client-Specific Design
Interfaces should be defined by what callers need, not by what implementations provide. Let usage shape the abstraction.