SOLID - Zasada segregacji interfejsu
Reguła skupiająca się na interfejsach, dzięki której kod staje się łatwiejszy w utrzymaniu i rozwijaniu. Jej stosowanie zapewnia równoczesnie spełnienie pozostałych zasad akronimu SOLID.
S – Zasada pojedynczej odpowiedzialności (Single Responsibility Principle – SRP)
O – Zasada otwarte-zamknięte (Open-Close Principle – OCP)
L – Zasada podstawiania Liskov (Liskov Substitution Principle – LSP)
I – Zasada segregacji interfejsu (Interface Segregation Principle – ISP)
D – Zasada odwrócenia zależności (Dependency Inversion Principle – DIP)
Definicja
Interfejsy powinny być tworzone jako małe i specyficzne dla klas, które je wykorzystują, zamiast być ogólne i zawierać wiele funkcjonalności.
Innymi słowy, interfejsy powinnny być dostosowane do konkretnych potrzeb klientów i nie zawierać zbędnych metod, które nie są używane przez wszytkie implementujące je klasy.
Przykład
Stowrzymy interfejs EmployeeMenager, które będzie zawierał metody potrzebne do zatrudnienia, zwolnienia pracownika, wypłacanie mu pensji, przyznawanie bonusów i przydzielanie zadań.
interface EmployeeManager {
void hire(Employee employee); // zatrudnij pracownika
void fire(Employee employee); // zwolnij pracownika
void paySalary(Employee employee); // wypłać pensję pracownikowi
void giveBonus(Employee employee); // przyznaj premię pracownikowi
void assignTask(Employee employee, Task task); // przydziel zadanie pracownikowi
} Następnie stworzymy klasę HRManager i Project Manager, które będą implementować powyższy interfejs.
class HRManager implements EmployeeManager {
// Metody związane z rekrutacją i zwalnianiem pracowników
public void hire(Employee employee) {
// logika zatrudniania pracownika
}
public void fire(Employee employee) {
// logika zwalniania pracownika
}
// Metody związane z wypłatą pensji i premii
public void paySalary(Employee employee) {
// logika wypłacania pensji
}
public void giveBonus(Employee employee) {
// logika przyznawania premii
}
// Metoda związana z przydzielaniem zadań
public void assignTask(Employee employee, Task task) {
// logika przydzielania zadań
}
} class ProjectManager implements EmployeeManager {
// Metody związane z rekrutacją i zwalnianiem pracowników
public void hire(Employee employee) {
// logika zatrudniania pracownika
}
public void fire(Employee employee) {
// logika zwalniania pracownika
}
// Metody związane z wypłatą pensji i premii
public void paySalary(Employee employee) {
// logika wypłacania pensji
}
public void giveBonus(Employee employee) {
// logika przyznawania premii
}
// Metoda związana z przydzielaniem zadań
public void assignTask(Employee employee, Task task) {
// logika przydzielania zadań
}
} W powyższym przykładzie interfejs jest zbyt duży i zbyt ogólny. Zawiera metody, które nie są związane z jednym obszarem odpowiedzialności. Na przykład klasa HRManager zajmuje się rekrutowaniem i zwalnianiem pracowników, ale nie powinna przydzielać im zadań. Podobny problem widzimy w klasie ProjectManager, który zajmuje się przydzielaniem zadań, a nie zadaniami HRManager’a. Jest to przykład naruszenia zasady segregacji interfejsów.
Aby poprawić ten kod należy podzielić interfejst EmployeeManager na mniejsze i bardziej specyficzne interfejsy, takie jak:
// Interfejs, który zawiera metody do rekrutacji i zwalniania pracowników
interface Recruiter {
void hire(Employee employee);
void fire(Employee employee);
} // Interfejs, który zawiera metody do wypłacania pensji i premii
interface Payroll {
void paySalary(Employee employee);
void giveBonus(Employee employee);
} // Interfejs, który zawiera metodę do przydzielania zadań
interface ProjectLeader {
void assignTask(Employee employee, Task task);
} Dzięki temu klasy HRManager i Project Manager mogłyby implementować tylko te interfejsy, których metody są dla nich istotne, na przykład:
// Klasa, która implementuje interfejsy Recruiter i Payroll
class HRManager implements Recruiter, Payroll {
// Metody związane z rekrutacją i zwalnianiem pracowników
public void hire(Employee employee) {
// logika zatrudniania pracownika
}
public void fire(Employee employee) {
// logika zwalniania pracownika
}
// Metody związane z wypłatą pensji i premii
public void paySalary(Employee employee) {
// logika wypłacania pensji
}
public void giveBonus(Employee employee) {
// logika przyznawania premii
}
} // Klasa, która implementuje interfejs ProjectLeader
class ProjectManager implements ProjectLeader {
// Metoda związana z przydzielaniem zadań
public void assignTask(Employee employee, Task task) {
// logika przydzielania zadań
}
} Dzięki temu rozwiązaniu kod stał się duży łatwiejszy w utrzymaniu i nie ma zbędnych zależności. Jest to prosty przykład, ale pokazuje o co chodzi w tej zasadzie.
[…] I – Zasada Segregacji interfejsu (Interface Segregation Principle – ISP) […]
[…] I – Zasada Segregacji interfejsu (Interface Segregation Principle – ISP) […]
[…] I – Zasada segregacji interfejsu (Interface Segregation Principle – ISP) […]