0 XP · 0 scenes

Interface Segregation

Many small interfaces beat one fat one
The problem

A Worker interface has work() and eat().

The idea

Cut the interface along who uses it.

Reach for it when

Implementers leave methods empty or throw

1

The picture from life

A restaurant gives a vegetarian guest a veg-only menu, not a thick book with every dish. Nobody has to read or answer for sections they cannot use. A single huge menu forces every guest and every waiter to carry things they never touch.

2

The problem

What goes wrong when you do not use it.

A Worker interface has work() and eat(). A Robot must implement eat() even though it never eats, so it writes an empty method or throws. Every implementer of the fat interface carries methods it does not need.

✗ Before
«interface»Workerwork()eat()Humanwork()eat()Robotwork()eat() ← fake / raises
  • implements
One fat interface forces Robot to fake an eat() it can never do.
Reach for it when
  • Implementers leave methods empty or throw
  • Callers use only two of the ten methods of an interface
  • A change to one method forces recompiling unrelated clients
3

The idea

How the pattern fixes it.

Cut the interface along who uses it. Workable has work(), Eatable has eat(). A human implements both, a robot only the first. Each client depends only on the small piece it needs.

✓ After
«interface»Workablework()«interface»Eatableeat()Robotwork()Humanwork()eat()
  • implements
Small interfaces: each class picks only the abilities it really has.

Who is who

Workable
Tiny interface: work().
Eatable
Tiny interface: eat().
Human, Robot
Implement only the interfaces that are true for them.

Build it in steps

  1. 1List the methods of the fat interface.
  2. 2Group them by which callers use them together.
  3. 3Make one small interface per group.
  4. 4Let classes implement only what applies.
4

Watch it run

Step through the calls. Tap an arrow to jump to it.

run_shiftHumanRobot1work()2'coding'3work()4'welding'
Step 1/4

run_shift needs only work(), so it asks for Workable and nothing more.

work()
5

The code

Python and Java. Try writing the classes yourself from the diagram first.

class Workable:
    def work(self):
        raise NotImplementedError


class Eatable:
    def eat(self):
        raise NotImplementedError


class Human(Workable, Eatable):
    def work(self):
        return "coding"

    def eat(self):
        return "lunch"


class Robot(Workable):                   # no eat() to fake
    def work(self):
        return "welding"


def run_shift(workers):                  # needs only work()
    return [worker.work() for worker in workers]


def demo():
    return run_shift([Human(), Robot()])

What you gain

  • Implementers carry no dead methods
  • Changes ripple to fewer classes

What it costs

  • More interface names to manage
  • Cutting too finely makes the code scattered

You have already met it in

  • Java's Runnable, Comparable and Closeable are tiny interfaces
  • Go's one-method interfaces such as Reader and Writer

Often mixed up with

6

Make it stick

Design a Printer / Scanner / Fax machine with interfaces so that a cheap printer is not forced to implement scan() and fax().

Confidence