OOP Course
Сьогодні

Підрозділ 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 — три відповідальності в одному класі

Рефакторинг: розбиваємо на три класи

Відповідно до SRP, кожна «вісь змін» стає окремим класом. Бізнес-логіка, збереження і сповіщення — три різні відповідальності, три різні класи.

Тепер кожен клас має рівно одну причину для зміни:

  • Змінюються правила бронювання → редагуємо лише AppointmentService
  • Переходимо з SQL на MongoDB → редагуємо лише AppointmentRepository
  • Додаємо SMS замість Email → редагуємо лише AppointmentNotifier

Після SRP — кожен клас незалежний і має одну відповідальність

Переваги 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.

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