Interfețe mici
Principiul segregării interfețelor spune: nicio clasă nu trebuie forțată să implementeze metode de care nu are nevoie. În locul unei singure interfețe prea încărcate, cu multe metode, creează mai multe interfețe mici — fiecare clasă implementează doar ceea ce este adevărat pentru ea.
Interfețele din PHP se potrivesc firesc acestei reguli: o clasă declară exact interfețele pe care le implementează — nimic mai mult — iar atunci când un cod are cu adevărat nevoie de mai multe capacități, interfețele mici se combină cu extends. Menținând fiecare interfață minusculă, fiecare listă implements rămâne sinceră.
Interfața prea încărcată
O interfață Worker cu work() și eat() pare inofensivă — până când un robot candidează pentru post. Robotul lucrează fără probleme, dar trebuie să implementeze și eat(), cu... ceva. Răspunsurile fără sens ca acesta sunt semnătura unei interfețe prea încărcate.
Robotul obligat să mănânce
Robotul implementează eat() doar pentru că interfața o cere. Pauza de masă afișează un răspuns care nu ar trebui să existe niciodată — clasa a fost forțată să mintă.
Ieșire: script PHP
<?php
// O singură interfață prea încărcată — fiecare lucrător TREBUIE să și mănânce.
interface Worker {
public function work(): string;
public function eat(): string;
}
class Human implements Worker {
public function work(): string {
return "human: working";
}
public function eat(): string {
return "human: eating lunch";
}
}
class Robot implements Worker {
public function work(): string {
return "robot: working";
}
// Impusă de interfață — roboții nu mănâncă.
public function eat(): string {
return "robot: ERROR, cannot eat";
}
}
$team = [new Human(), new Robot()];
foreach ($team as $w) {
echo $w->work(), "\n";
}
foreach ($team as $w) {
echo $w->eat(), "\n";
}
Divizează interfața
Împarte interfața prea încărcată în Worker și Eater. Omul le implementează pe ambele; robotul implementează doar Worker. Turul de lucru primește lucrători, pauza de masă primește mâncători — robotul pur și simplu nu este invitat niciodată la masă și nicio metodă nu minte.
Fiecare clasă implementează doar adevărul ei
Două interfețe mici în locul unei singure interfețe prea încărcate. Robotul nu mai are deloc o metodă eat() — indicația de tip Eater îl ține în afara pauzei de masă în mod automat.
Ieșire: script PHP
<?php
// Două interfețe mici — fiecare clasă implementează doar ce este adevărat pentru ea.
interface Worker {
public function work(): string;
}
interface Eater {
public function eat(): string;
}
class Human implements Worker, Eater {
public function work(): string {
return "human: working";
}
public function eat(): string {
return "human: eating lunch";
}
}
class Robot implements Worker {
public function work(): string {
return "robot: working";
}
}
function workShift(Worker ...$team): void {
foreach ($team as $w) {
echo $w->work(), "\n";
}
}
function lunchBreak(Eater ...$guests): void {
foreach ($guests as $e) {
echo $e->eat(), "\n";
}
}
workShift(new Human(), new Robot());
lunchBreak(new Human());
Piesele mici se compun
Interfețele mici nu sunt o limitare — ele se combină. Atunci când o funcție are cu adevărat nevoie de ambele capacități, compune-le într-o singură interfață: WorkingEater extends Worker, Eater.
Acesta este modelul: definește interfețe mici și lipește-le cu extends numai acolo unde este într-adevăr nevoie de mai mult.
Compune atunci când ai nevoie de ambele
WorkingEater este construită din cele două interfețe mici cu extends. Omul declară acea singură interfață și astfel este considerat și Worker și Eater — turul de o zi întreagă are nevoie de ambele capacități, așa că doar omul este potrivit.
Ieșire: script PHP
<?php
interface Worker {
public function work(): string;
}
interface Eater {
public function eat(): string;
}
// Interfețele mici se compun în unele mai mari atunci când este nevoie.
interface WorkingEater extends Worker, Eater {
}
class Human implements WorkingEater {
public function work(): string {
return "human: working";
}
public function eat(): string {
return "human: eating lunch";
}
}
function fullDay(WorkingEater $we): void {
echo $we->work(), "\n";
echo $we->eat(), "\n";
echo $we->work(), "\n";
}
fullDay(new Human());