Seven Jobs That Throw

interface Job {
    void run();
    void pause();
    void resume();
    void progress(ProgressSink sink);
}

final class VacuumTablesJob implements Job {
    public void run()  { /* 40 minutes of DDL, not interruptible */ }
    public void pause()  { throw new UnsupportedOperationException(); }
    public void resume() { throw new UnsupportedOperationException(); }
    public void progress(ProgressSink s) { /* nothing to report */ }
}

There are 11 implementations of Job. Seven of them throw from pause and resume. The team proposes splitting the interface into Job { run(); progress(); } and PausableJob extends Job { pause(); resume(); }.

Which principle does that split most directly serve, and what disappears first?

A

Single Responsibility. VacuumTablesJob currently runs DDL and reports progress, and the split gives each resulting class exactly one reason to change.

B

Interface Segregation. Martin's statement is that many client-specific interfaces beat one general purpose interface; after the split, the scheduler's pause button binds to PausableJob and the seven UnsupportedOperationException stubs get deleted rather than relocated.

C

Open/Closed. New job types can be added without editing Job, so the interface stops changing every time a job with new capabilities arrives.

D

Dependency Inversion. The scheduler stops depending on concrete job classes and depends on an abstraction instead, so the concrete jobs become replaceable.