„Clients should not be forced to depend on interfaces they do not use.”
— Robert C. Martin

O co chodzi z ISP?

Zasada ISP mówi: interfejsy powinny być małe, konkretne i dopasowane do potrzeb danej klasy. Klasy nie powinny być zmuszane do implementowania metod, których nie potrzebują.

Mówiąc prościej – dziel interfejsy na mniejsze, zamiast tworzyć jedną klasę bazową, która „robi wszystko”. To jak z pilotem: łatwiej użyć prostego z 5 przyciskami niż uniwersalnego kombajnu z 80 opcjami, z których potrzebujesz 2.

Przykład łamania ISP – interfejs „kombajn”

Załóżmy, że tworzysz system dla różnych typów urządzeń biurowych: drukarek, skanerów, faksów. Ktoś tworzy taki interfejs:

public interface UrzadzenieWielofunkcyjne {
    void drukuj(String tekst);
    void skanuj();
    void faxuj(String numer);
}

Dobrze, jeśli urządzenie faktycznie wszystko potrafi. Ale co, jeśli masz prostą drukarkę?

public class DrukarkaHP implements UrzadzenieWielofunkcyjne {
    public void drukuj(String tekst) {
        // drukuj tekst
    }

    public void skanuj() {
        throw new UnsupportedOperationException
        ("Brak funkcji skanowania");
    }

    public void faksuj(String numer) {
        throw new UnsupportedOperationException
        ("Brak funkcji faksu");
    }
}

Drukarka musi implementować metody, których nie potrzebuje. To nie tylko brzydkie – to łamie zasadę ISP.

Lepsze podejście – mniejsze, konkretne interfejsy

Zamiast jednego wielkiego interfejsu, dzielimy go na mniejsze:

public interface Drukujace {
    void drukuj(String tekst);
}

public interface Skanujace{
    void skanuj();
}

public interface Faksujace{
    void faksuj(String numer);
}

Teraz każda klasa implementuje tylko to, co faktycznie potrafi:

public class DrukarkaHP implements Drukujace {
    public void drukuj(String tekst) {
        // drukowanie
    }
}

public class UrzadzenieWielofunkcyjneHP implements 
             Drukujace, Skanujace, Faksujace {
    public void drukuj(String tekst) {
        // drukuj
    }

    public void skanuj() {
        // skanuj
    }

    public void faksuj(String numer) {
        // faksuj
    }
}

Każda klasa implementuje tylko te interfejsy, których metody wykorzystuje. Prosto, czysto i przede wszystkim zgodnie z zasadą ISP.

Korzyści z ISP

  • Brak pustych implementacji i wyjątków,
  • Lepsza czytelność – wiadomo, co klasa potrafi,
  • Mniejsza zależność między klasami,
  • Łatwiejsze testowanie i utrzymanie kodu,
  • Większa elastyczność – dodajesz tylko to, co potrzebne.

Podsumowanie

Interface Segregation Principle to manifest zdrowego rozsądku. Jeśli klasa musi implementować coś, czego nie potrzebuje – to znak, że interfejs jest za duży. Małe interfejsy = duża wygoda.

Pamiętaj: Twoje klasy nie powinny znać metod, których nigdy nie użyją.


Dodaj komentarz

Twój adres e-mail nie zostanie opublikowany. Wymagane pola są oznaczone *