Щоб розкрити дуже гарну відповідь Вадима, я відповім на питання "чи це спірне" з "ні, не дуже".
Загалом, розділення інтерфейсів - це гарна річ, зменшуючи загальну кількість "причин зміни" різних об'єктів, що беруть участь. Основний принцип полягає в тому, що коли інтерфейс з декількома методами потрібно змінити, скажімо, щоб додати параметр до одного з методів інтерфейсу, тоді всі споживачі інтерфейсу повинні бути принаймні перекомпільовані, навіть якщо вони не використовували метод, який змінився. "Але це просто перекомпіляція!", Я чую, як ви говорите; це може бути правдою, але майте на увазі, що зазвичай все, що ви перекомпілюєте, повинно бути витіснене як частина програмного патчу, незалежно від того, наскільки суттєві зміни в двійковому. Ці правила були спочатку осмислені ще на початку 90-х, коли середня робоча станція на робочому столі була менш потужною, ніж телефон у вашій кишені, набір 14,4 тис. Бод був блазним, а 3,5-дюймові "дискети" 1,44 МБ були основним знімним носієм. Навіть у сучасну епоху 3G / 4G користувачі бездротового Інтернету часто мають плани даних з обмеженнями, тож, випускаючи оновлення, тим менше бінарних файлів, які потрібно завантажити, тим краще.
Однак, як і всі хороші ідеї, розмежування інтерфейсу може погіршитись, якщо неправильно реалізовано. По-перше, існує ймовірність, що, розділяючи інтерфейси, зберігаючи об'єкт, який реалізує ці інтерфейси (виконуючи залежності), відносно незмінними, ви можете опинитися з "Hydra", родичем антитіл "Об'єкт Бога", де всезнаючий, всесильний характер об'єкта прихований від залежних вузькими інтерфейсами. У вас опинилося багатоголове чудовисько, яке, як мінімум, так важко підтримувати, як і об'єкт Бога, плюс накладні витрати на підтримку всіх його інтерфейсів. Не існує важкої кількості інтерфейсів, яку ви не повинні перевищувати, але кожен інтерфейс, який ви реалізуєте на одному об’єкті, повинен бути попереднім, відповівши на питання: "Чи сприяє цей інтерфейс об'єкту"
По-друге, інтерфейс для методу може не знадобитися, незважаючи на те, що SRP може вам сказати. Ви можете отримати "код равіолі"; так багато шматочків укусу, що важко простежити, щоб дізнатися, де саме відбуваються речі. Також непотрібно розділяти інтерфейс двома методами, якщо всі поточні користувачі цього інтерфейсу потребують обох методів. Навіть якщо одному із залежних класів потрібен лише один із двох методів, загальноприйнятно не розділяти інтерфейс, якщо його методи концептуально мають дуже високу згуртованість (хорошими прикладами є "антонімічні методи", які є точними протилежностями один одного).
Сегрегація інтерфейсу повинна базуватися на класах, які залежать від інтерфейсу:
Якщо є лише один клас, залежний від інтерфейсу, не відокремлюйте. Якщо клас не використовує один або декілька методів інтерфейсу, і він є єдиним споживачем інтерфейсу, шанси на те, що ви не повинні були викривати ці методи в першу чергу.
Якщо існує більше одного класу, який залежить від інтерфейсу, і всі залежні використовують всі методи інтерфейсу, не відокремлюйте їх; якщо вам потрібно змінити інтерфейс (додати метод або змінити підпис), зміна впливатиме на всіх поточних споживачів, незалежно від того, розділите ви їх чи ні (хоча якщо ви додаєте метод, який хоча б одному залежному не знадобиться, врахуйте обережно, якщо натомість зміна повинна бути реалізована як новий інтерфейс, можливо, успадкований від існуючого).
Якщо від інтерфейсу існує більше одного класу, і вони не використовують усі однакові методи, це кандидат на сегрегацію. Подивіться на "узгодженість" інтерфейсу; чи всі методи надають єдину, дуже конкретну мету програмування? Якщо ви можете визначити більше однієї основної мети інтерфейсу (та його реалізаторів), подумайте про розділення інтерфейсів по цих лініях, щоб створити менші інтерфейси з меншою кількістю "причин для зміни".