Увійти Реєстрація
Блог Серії
Кар'єра
Вакансії Компанії
Навчання
Документація Співбесіди Тестування Відео
Екосистема
Пакети Ресурси Проєкти Інструменти Події
Інше
Про нас Реклама

Що таке принцип розділення інтерфейсів (ISP)?

Принцип розділення інтерфейсів (Interface Segregation Principle, «I» в SOLID): клієнти не повинні залежати від методів, якими вони не користуються. Краще кілька вузьких інтерфейсів, ніж один «товстий».

Порушення:

interface Storage
{
    public function read(string $path): string;
    public function write(string $path, string $contents): void;
    public function delete(string $path): void;
    public function temporaryUrl(string $path, DateTimeInterface $expires): string;
    public function listContents(string $dir): array;
}

Клас, якому потрібно лише читати файли, залежить від усього інтерфейсу. Реалізація для сховища, де немає тимчасових посилань, змушена кидати NotSupportedException - а це вже порушення й принципу Лісков.

Відповідно до ISP:

interface ReadsFiles
{
    public function read(string $path): string;
}

interface WritesFiles
{
    public function write(string $path, string $contents): void;
    public function delete(string $path): void;
}

interface GeneratesTemporaryUrls
{
    public function temporaryUrl(string $path, DateTimeInterface $expires): string;
}

final class ReportGenerator
{
    public function __construct(private ReadsFiles $files) {}   // лише те, що потрібно
}

Один клас може реалізовувати кілька інтерфейсів, а кожен споживач залежить лише від потрібного.

Навіщо:

  • простіші тести: фейк для ReadsFiles - один метод, а не п'ять заглушок;
  • менше зв'язності: зміна методу запису не зачіпає класи, що лише читають;
  • чесні реалізації: немає методів, що кидають «не підтримується»;
  • зрозумілі залежності: з конструктора видно, що саме клас використовує.

Приклади в PHP і Laravel:

  • PHP: Countable, IteratorAggregate, ArrayAccess, JsonSerializable, Stringable - маленькі інтерфейси, кожен про одну можливість;
  • Laravel: ShouldQueue, ShouldBroadcast, HasLocalePreference, Arrayable, Jsonable, Responsable - вузькі контракти, які клас реалізує за потреби.

Межа здорового глузду: інтерфейс з одним методом на кожен метод класу - теж крайність. Групувати варто за тим, як інтерфейс використовують клієнти: методи, які завжди потрібні разом, - в одному інтерфейсі.

Докладніше в документації: Принцип розділення інтерфейсів

1

Перевір себе

20 випадкових питань за спробу, після завершення - розбір кожної помилки

Схожі питання