Підрозділ 20.2
SRP — Принцип єдиної відповідальності
20.2. SRP — Принцип єдиної відповідальності Single Responsibility Principle SRP — перший і найфундаментальніший принцип SOLID. Його формулювання звучить коротко: «Клас повинен мати лише одну причину для зміни».
20.2. SRP — Принцип єдиної відповідальності
Single Responsibility Principle (SRP) — перший і найфундаментальніший принцип SOLID. Його формулювання звучить коротко: «Клас повинен мати лише одну причину для зміни». Ця одна фраза є одночасно і простою для запам'ятовування, і досить тонкою для правильного розуміння.
Ключове слово тут — «причина». Не «одна функція», не «одна задача» у звичайному розумінні. Роберт Мартін пояснював «причину для зміни» як актора — конкретну роль або підрозділ організації, чиї вимоги диктують зміни в коді. Клас порушує SRP, якщо його може «змусити змінитися» більш ніж один актор.
У контексті медичної системи: якщо клас AppointmentManager змінюється і коли відділ бронювання переглядає правила запису, і коли ІТ-відділ переходить на нову базу даних, і коли маркетинг хоче додати SMS-сповіщення — він обслуговує трьох акторів, а значить має три причини для зміни. Це порушення SRP.
Чому «одна відповідальність» — це не «одна функція»
Поширена помилка — інтерпретувати SRP буквально: «один клас = один метод». Це хибне прочитання. Клас може мати десятки методів і при цьому повністю дотримуватися SRP, якщо всі ці методи служать одній меті, одному актору, одній «осі змін».
Прикладом правильного і повного класу з однієї відповідальністю є клас Patient з усіма своїми властивостями та методами перевірки: вони всі разом відповідають за коректне представлення і поведінку пацієнта в системі. Ніхто окрім «доменної моделі» не є причиною їх зміни.
Навпаки, клас із двома методами — SaveToDatabase() і SendEmail() — порушує SRP, навіть якщо у ньому лише ці два методи: зміна бази даних і зміна поштового шлюзу — це дві різні причини.
Приклад порушення SRP: клас із трьома акторами
Розглянемо клас AppointmentManager, що традиційно «виростає» в системах без архітектурних принципів:
Що не так із цим класом? Щоразу, коли будь-який із трьох акторів змінює вимоги — змінюється весь клас. Це ризик регресії: правлячи логіку збереження, можна ненавмисно зачепити логіку сповіщень. Тестуючи правила бронювання, доводиться поднімати базу даних і SMTP-сервер.

Рефакторинг: розбиваємо на три класи
Відповідно до SRP, кожна «вісь змін» стає окремим класом. Бізнес-логіка, збереження і сповіщення — три різні відповідальності, три різні класи.
Тепер кожен клас має рівно одну причину для зміни:
- Змінюються правила бронювання → редагуємо лише
AppointmentService - Переходимо з SQL на MongoDB → редагуємо лише
AppointmentRepository - Додаємо SMS замість Email → редагуємо лише
AppointmentNotifier

Переваги SRP для тестування
Найвідчутніша практична перевага SRP — тестованість. Коли відповідальності розділені, кожен клас можна тестувати ізольовано:
Зверніть увагу: жодного SMTP-сервера, жодної бази даних. AppointmentService тестується в ізоляції, бо він нічого не знає про інфраструктуру.
Реальний SRP: клас `Patient` як зразок
Правильно побудований клас Patient є хорошим прикладом дотримання SRP: він повністю відповідає за представлення і валідацію пацієнта як доменної сутності і не робить нічого іншого.
Ознаки порушення SRP
На практиці порушення SRP легко впізнати за кількома симптомами:
Клас має методи, що змінюються з різних причин. Якщо ви описуєте клас і вживаєте слово «і» — «цей клас зберігає дані і надсилає повідомлення» — скоріш за все, є порушення.
Клас ImportManager, ExportManager, ProcessManager. Суфікси -Manager і -Helper часто є сигналом «сміттєвого» класу, куди скинули все, що не вклалося в чітку відповідальність.
Методи класу природно групуються у непересічні підмножини. Якщо методи А, В, С ніколи не використовують спільного стану класу, і методи X, Y, Z — теж ніколи не перетинаються з першою групою — це два кандидати на розбиття.
Тест одного методу вимагає ініціалізації непов'язаних залежностей. Якщо для тесту методу BookAppointment треба налаштовувати SMTP — SRP порушено.
SRP і розмір класу
SRP не означає, що класи мають бути крихітними. Добре спроектований PatientService може мати 20–30 методів і при цьому повністю дотримуватися принципу — якщо всі ці методи обслуговують одну бізнес-відповідальність «управління пацієнтами». SRP — це про осі змін, а не про кількість рядків.
Водночас SRP не рекомендує нескінченно дробити класи. «Мікроклас» на два рядки, що нічого не приховує і нічого не інкапсулює — це не дотримання принципу, а його карикатура. Баланс досягається питанням: «Чи є тут більше однієї причини для зміни?» — і не більше.
Шість методів, одна відповідальність — «бути реєстром пацієнтів». Це правильне застосування SRP.