Skip to content

18 · 32 · 5 min

Interface segregation and dependency inversion

The last two, and the second is the most useful idea in the course.

I: interface segregation

No client should be forced to depend on methods it does not use.

java
interface Worker {
    void work();
    void eat();
    void sleep();
}

class Robot implements Worker {
    public void work()  { }
    public void eat()   { throw new UnsupportedOperationException(); }
    public void sleep() { throw new UnsupportedOperationException(); }
}

Two of those three are lies. Split the interface:

java
interface Workable { void work(); }
interface Feedable { void eat(); }

class Robot implements Workable { }
class Human implements Workable, Feedable { }

D: dependency inversion

Depend on abstractions, not concretions. And the part people miss: both sides depend on the abstraction, including the high-level one.

java
class OrderService {
    private final MySqlDatabase db = new MySqlDatabase();  // welded on
}

class OrderService {
    private final Repository repo;                          // an interface
    OrderService(Repository repo) { this.repo = repo; }     // handed in
}

The second can be tested with an in-memory fake, can switch database without touching order logic, and states its dependency in its constructor where a reader can see it.

Handing a dependency in rather than constructing it is dependency injection, and it is how dependency inversion is achieved in practice.

Interface segregation and dependency inversion