Interface Segregation Principle

No client should be forced to depend on methods it does not use. Split a fat interface into small ones, each shaped by one kind of client.

Overview

The Interface Segregation Principle (ISP) is the I in SOLID. Robert C. Martin stated it in his fourth C++ Report column in 1996: clients should not be forced to depend upon interfaces that they do not use. A fat interface is one whose methods fall into groups, each used by a different set of clients. When two clients share one fat interface, a change asked for by one of them reaches the other, even though the other never called the method that changed.

The principle is about the client's point of view. SRP asks what a class should do. ISP asks what a client should have to know. An interface designed from the client side is small, because each client needs only a few methods.

  • Fat interface — one interface whose methods serve several unrelated clients
  • Interface pollution — a base type forced to carry methods only some subtypes need
  • Segregated interface — one small interface per kind of client

Where fat interfaces come from

Martin's example is a security system with a Door type that can be locked, unlocked and checked. One kind of door, a timed door, must sound an alarm if it stays open too long, so it registers with a Timer. The Timer calls back through a TimerClient type. The quick fix is to make Door inherit TimerClient, so every door can be a timer client.

Now a bug fix in the timer, such as adding a timeout id to the callback, changes TimerClient, which changes Door, which forces every door and every door user to rebuild and retest. A plain door has to carry an empty time_out method. The interface of Door has been polluted by a client it does not serve.

Segregate by client

The fix is to keep the two interfaces apart and let the one object that needs both implement both. Martin shows two ways: an adapter object that implements TimerClient and forwards to the timed door, or multiple inheritance so TimedDoor implements both Door and TimerClient. Either way, Door clients never see TimerClient.

The same shape appears in Martin's ATM example. Each transaction (deposit, withdraw, transfer) needs a different slice of the user interface. One fat UI interface means a change for transfers forces deposits to recompile. Segregating it into DepositUI, WithdrawUI and TransferUI, all implemented by one concrete UI, keeps each transaction tied only to its slice.

Before and after

A Worker interface with work, eat and rest. A human worker does all three; a robot only works, so it must stub two methods it cannot honor.

The fix splits the interface by client. The scheduler needs Workable; the cafeteria needs Feedable. Robot implements only what it can honor, and lunch_break cannot be handed a robot by mistake.

Role interfaces in Python and Go

Languages without a keyword for interfaces still support ISP, and some make it the default.

  • Java, C# — interface; a class implements several — the natural home of ISP
  • Python — abc.ABC with @abstractmethod, or typing.Protocol — Protocol (added in 3.8) is structural: any class with the right methods matches
  • Go — interfaces are satisfied implicitly — a type implements an interface by having its methods; io.Reader is one method

Small interfaces are cheap in Go and in Python protocols because nothing has to declare that it implements them. A function that takes an io.Reader accepts every type with a Read method, which is ISP with no ceremony.

What you will be able to do

  • State the principle from the client's side and explain interface pollution with the door example.
  • Spot a fat interface by its forced stubs and thrown unsupported errors.
  • Split it into role interfaces and show one class implementing several.
  • Apply the same idea in Python with Protocol and in Go with implicit interfaces.

Interview questions

  • How do you identify a fat interface that needs splitting?
  • How does ISP relate to the other SOLID principles?
  • How do you apply ISP in Python, which has no interface keyword?
  • What is the difference between a role interface and a header interface?
  • When does having many small interfaces become a problem?

Sign up free to read the full topic

More Low-Level Design topics

Start free on Cariara · Coding problems · System design studio