OOP Course
Сьогодні

Підрозділ 20.5

ISP — Принцип розподілу інтерфейсів

20.5. ISP — Принцип розподілу інтерфейсів Interface Segregation Principle ISP сформулював Роберт Мартін у 1996 році у статті для журналу C++ Report. Принцип звучить так: «Клієнти не повинні залежати від методів

20.5. ISP — Принцип розподілу інтерфейсів

Interface Segregation Principle (ISP) сформулював Роберт Мартін у 1996 році у статті для журналу C++ Report. Принцип звучить так: «Клієнти не повинні залежати від методів, яких вони не використовують». Або у іншому формулюванні: «Краще багато вузькоспеціалізованих інтерфейсів, ніж один великий».

ISP — це принцип про проектування інтерфейсів з точки зору клієнта. Інтерфейс «поганий» не тому, що він великий сам по собі, а тому, що він змушує реалізатора брати на себе зобов'язання, які йому не потрібні. Якщо клас ReceptionDesk реалізує IClinicService і мусить написати GeneratePdfReport() та ExportToCsv() — хоча йому вони ніколи не знадобляться — це і є порушення ISP.

Наслідки такого «жирного» інтерфейсу (fat interface):

  • Реалізатор пише «заглушки» — методи, що кидають NotImplementedException або просто нічого не роблять
  • Зміна в інтерфейсі (навіть у методах, що клас не використовує) вимагає перекомпіляції і перевірки всіх реалізаторів
  • Тест на ReceptionDesk раптом залежить від PDF-бібліотеки, хоча ReceptionDesk з PDF нічого спільного не має

«Жирний» інтерфейс: класична помилка

Коли систему проектують поспіхом або «зверху вниз» без аналізу клієнтів, природно з'являється один великий інтерфейс, що об'єднує всі можливості системи:

До ISP — «жирний» інтерфейс примушує реалізовувати непотрібне

Рефакторинг: розбиття на вузькі інтерфейси

Відповідно до ISP, кожна «група» методів, що обслуговує окремого клієнта, стає окремим інтерфейсом. Клас реалізує стільки інтерфейсів, скільки «ролей» він виконує:

Після ISP — маленькі інтерфейси, кожен клієнт бере лише потрібне

ISP і принцип найменшого знання

ISP тісно пов'язаний із «принципом найменшого знання» (Principle of Least Knowledge або Law of Demeter): компонент повинен знати якомога менше про решту системи. Якщо ReceptionDesk реалізує IReportService, він «знає» про PDF і Email — навіть якщо сам їх не використовує. Вузькі інтерфейси природно мінімізують це «зайве знання».

ISP у реальному коді: інтерфейси як «ролі»

Хороший спосіб думати про ISP: кожен інтерфейс — це роль, яку клас може виконувати. Один клас може грати кілька ролей. Роль описана мінімально: лише те, що потрібно клієнту цієї ролі.

Коли ISP не потрібен

Варто розуміти: ISP — не заклик дробити кожен інтерфейс до одного методу. Інтерфейс IComparable<T> з одним методом CompareTo — правильний приклад вузького інтерфейсу. Але IEnumerable<T> з одним GetEnumerator — теж правильний. Розмір інтерфейсу не є самоціллю.

Інтерфейс потрібно розбивати тоді, коли різні клієнти використовують різні підмножини методів. Якщо всі клієнти використовують всі методи — об'єднаний інтерфейс абсолютно правильний. Критерій: «Чи є хоч один клієнт, що змушений залежати від методу, який йому не потрібен?» — якщо так, ISP застосовується.

Клас PatientDashboard залежить від трьох методів ILabResultProvider, а не від усього великого API лабораторної системи. Якщо лабораторна система повністю замінюється — пишеться новий адаптер, PatientDashboard не змінюється.

Розроблено Tomka Yurii · © 2026 ·