Przedostatnia zasada mnemoniku SOLID. Według tej wytycznej interfejsy należy odpowiednio segregować. Nie jest zalecane tworzenie interfejsu “od wszystkiego”. Powinno się je konstruować w taki sposób, aby miały tylko jedną odpowiedzialność (Single Responsible Principle). Klas implementujących dany interfejs nie należy zmuszać do implementowania funkcjonalności, których nie potrzebują. Naruszono by w ten sposób zasadę Barbary Liskov (Liskov Substitution Principle). Można więc powiedzieć, że jest to reguła korzystająca z dobrodziejstw dwóch innych wytycznych.

Interface segregation principle
Należy dzielić duże interfejsy na mniejsze

Można powiedzieć, że interfejs jest kontraktem zawieranym pomiędzy wywołującym a klasą. Jeśli będzie on zbyt długi to łatwo się w nim pogubić (tak jak w prawdziwym życiu). Z tego powodu reguła Interface segregation principle zaleca, aby takie kontrakty zmniejszać, aby miały tylko jedną odpowiedzialność. W ten sposób uzyskujemy luźne powiązania pomiędzy poszczególnymi elementami, a co za tym idzie uzyskujemy łatwość testowania, refaktoringu oraz utrzymania kodu. Przejdźmy zatem do przykładu łamiącego zasadę Segregacji Interfejsów:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
public interface Tasks {
  void organizeMeetings();
  void motivateTeam();
}

public class OrganizationManager implements Tasks {

  public void organizeMeetings() {
    // organize meetings
  }

  public void motivateTeam() {
    throw new TypeOfWorkNotSupportedException();
  }
}

public class MotivationManager implements Tasks {

  public void organizeMeetings() {
    throw new TypeOfWorkNotSupportedException();
  }

  public void motivateTeam() {
    // motivate team
  }
}

Załóżmy sytuację, w której wiele innych projektów korzysta z tego interfejsu w podobny sposób. Klasy go implementujące tak naprawdę potrzebują tylko jedną metodę z dwóch dostępnych. Przypuśćmy, że nagle przychodzi wymaganie, które karze nam zrobić zmianę w tym konkretnym interfejsie. W rezultacie w każdym projekcie trzeba obsłużyć to nowe ulepszenie co wiąże się z wieloma zmianami. Z tego powodu zasada Segregacji Interfejsów ma sens, ponieważ znacznie ułatwia nam pracę.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
public interface OrganizationTasks {
  void organizeMeetings();
}

public interface MotivationTasks {
  void motivateTeam();
}

public class OrganizationManager implements OrganizationTasks {

  public void organizeMeetings() {
    // organize meetings
  }
}

public class MotivationManager implements MotivationTasks {

  public void motivateTeam() {
    // motivate team
  }
}

W ten sposób unikniemy niepotrzebnych zmian we wszystkich projektach. Dodatkowo atutem jest to, że zadania są odpowiednio posegregowane. Kod jest łatwiejszy do zarządzania i utrzymania.

Podsumowanie

Według mnie zasada Segregacji Interfejsów jest zwieńczeniem dwóch innych reguł. Trzymanie się jej pozwala nam nie tworzyć klas “od wszystkiego”. Jak wszystko, tak i Interface segregation principle nie uchroni nas przed całym złem. Jednak moim zdaniem warto brać ją pod uwagę podczas pisania kodu źródłowego. Z pewnością nasze klasy będą czytelniejsze i łatwiejsze w utrzymaniu. Warto więc się zastanowić czy dobrze rozumiem tę regułę i wiem jak poprawnie ją stosować.

Jak zawsze będę wdzięczny za to, że przekażesz mi swoją opinię na poruszony wyżej temat. Z chęcią zapoznam się również z jakimiś innymi przypadkami łamania zasady Segregacji Interfejsów i próbą ich naprawienia. Zachęcam Cię do wyrażenia swojego zdania w komentarzu bądź wysłania go do mnie bezpośrednio na maila!