Як визначити, чи відповідає клас єдиному принципу відповідальності?


34

Принцип єдиної відповідальності базується на принципі високої згуртованості. Різниця між ними полягає в тому, що високо згуртовані класи мають набір обов'язків, які тісно пов'язані між собою, тоді як класи, які дотримуються SRP, несуть лише одну відповідальність.

Але як ми можемо визначити, чи відповідає певний клас набором обов'язків і таким чином є дуже згуртованим, чи він несе лише одну відповідальність і таким чином дотримується SRP? Іншими словами, чи не є це більш-менш суб'єктивним, оскільки деякі можуть вважати клас дуже детальним (і як такий вважають, що клас дотримується SRP), а інші можуть вважати його недостатньо деталізованим?



Відповіді:


21

Чому так, це дуже суб'єктивно, і це тема багатьох гарячих, червоноликих дебатів, в які потрапляють програмісти.

Адже насправді немає жодної відповіді, і відповідь може змінюватися, коли ваше програмне забезпечення стає складнішим. Те, що колись було одним чітко визначеним завданням, з часом може стати декількома погано визначеними завданнями. Це завжди теж руб. Як вибрати правильний спосіб поділу програми на завдання?

Про єдину пораду, яку я можу дати, це таке: використовуйте найкращі судження (та своїх колег). І пам’ятайте, що помилки можна (як правило) виправити, якщо ви їх досить швидко вловите.


Я хотів би, щоб інформатика була більше схожа на фактичну науку. Суб’єктивізм не має місця в реальній науці. Незважаючи на те, що принципи SOLID самі по собі є чудовими, їх потрібно переробити, щоб мінімізувати суб'єктивність і максимально об'єктивувати. Цього ще не сталося, що змушує мене ставити під сумнів їхню легітимність у реальному світі.
DarkNeuron

13

Боб Мартін (дядько Боб), який заснував тверді принципи, з яких SRP є першим, говорить про це (я перефразую, не можу згадати фактичні слова):

Клас повинен мати лише одну причину зміни

Якщо у неї є кілька причин, вона не дотримується SRP.


14
Це просто повторення цього визначення дійсно, але насправді дотримання srp є все ще досить суб'єктивним.
Енді

7

Я можу дати вам кілька правил.

  • Наскільки легко назвати клас? Якщо клас важко назвати, він, ймовірно, робить занадто багато.
  • Скільки публічних методів має клас? 7 +/- 2 - це хороше правило. Якщо в класі є більше, слід подумати про поділ його на кілька класів.
  • Чи є згуртовані групи публічних методів, що використовуються в окремих контекстах?
  • Скільки приватних методів або членів даних є? Якщо клас має складну внутрішню структуру, вам, ймовірно, слід переробляти його, щоб внутрішні пакунки були розбиті в окремі менші класи.
  • І найпростіше правило: наскільки великий клас? Якщо у вас є заголовочний файл C ++, що містить один клас, довжиною якого є кілька сотень рядків, ймовірно, слід розділити його.

2
Щодо вашого другого пункту, дивіться uxmyths.com/post/931925744/…
Cameron Martin

7
Різко не погоджуються щодо 7 +/- 2 - принцип єдиної відповідальності полягає в смисловій згуртованості, а не в довільних числах.
ЖакБ

1
Правило великих пальців не потребує незалежного наукового підтвердження. Сучасний науковий метод столітній, архітектура та інженерія - тисячоліттями. Для загальнодоступних методів правило "кілька", а жодних параметрів - "кілька". Іншими новинами, хоча деякі дитячі малюнки показують, що інакше зброя людей не виходить з голови [потрібна цитата].
abuzittin gillifirca

@CameronMartin Залежно від налаштувань, інтерфейс для класу може бути або не бути доступним для читання. Пошук у користувальницькому інтерфейсі навряд чи такий, як написання коду - якщо мені доведеться щомісяця звертатися з документацією, я, принаймні, подвоюю час, необхідний для виконання будь-якої реальної роботи.
Чіткіший

6

Принципи єдиної відповідальності говорять, що кожен програмний модуль повинен мати лише одну причину для зміни. У останній статті дядько Боб пояснив "причину зміни",

Однак, думаючи про цей принцип, пам’ятай, що причини змін - це люди. Саме люди вимагають змін. І ви не хочете плутати цих людей або себе, змішуючи разом код, про який піклуються багато різних людей з різних причин.

Далі він пояснив цю концепцію прикладом ТУТ .


Це чудова стаття, написана самою людиною.
MrDustpan

4

Щоб відповісти на це, зробіть крок назад і врахуйте намір принципу єдиної відповідальності. Чому це в першу чергу рекомендований принцип дизайну?

Метою принципу є "розділення" кодової бази, тому код, що відноситься до однієї "відповідальності", виділений в єдине ціле. Це полегшує пошук і розуміння коду, і що ще важливіше, це означає, що зміни на "відповідальність" вплинуть лише на одну одиницю коду.

Те, чого ви абсолютно ніколи не хочете в системі, - це коли один невеликий шанс викликає збій або зміну поведінки якоїсь іншої, мабуть, незв'язаної частини коду. SRP допомагає виділити помилки та зміни.

То яка ж це "відповідальність" тоді? Це те, що можна мислити незалежно від інших змін. Скажімо, у вас є програма, яка може зберегти деякі параметри до файлу конфігурації XML, і ви можете прочитати їх із цього файлу. Це одна відповідальність, або це "навантаження" та "збереження" двох різних обов'язків? Будь-яка зміна формату файлу або структури вимагає зміни як завантаження, так і збереження логіки. Тому це єдина відповідальність, яку повинен представляти один клас. Тепер розглянемо додаток, який може експортувати деякі дані у формат CVS, Excel та XML. У цьому випадку легко уявити, що один формат міг би змінитися, не впливаючи на інший. Якщо ви вирішили змінити роздільник у форматі CVS, це не повинно впливати на вихід Excel.


2

ОО каже, що класи - це групування даних, які є функціональними. Це визначення залишає багато місця для суб'єктивної інтерпретації.

Ми знаємо, що класи повинні бути чітко і легко визначені. Але, щоб визначити такий клас, ми повинні мати чітке уявлення про те, як клас вписується в загальний дизайн. Без вимог типу водоспадів, які, як це не парадоксально, вважаються анти-зразком ... цього важко досягти.

Ми можемо реалізувати дизайн класу з архітектурою, яка працює в більшості випадків, як MVC. У програмах MVC ми припускаємо, що вони мають лише дані, користувальницький інтерфейс та вимоги для спілкування обох.

З базовою архітектурою простіше визначити випадки, коли порушуються єдині правила відповідальності. EG Передача екземпляра керування користувачем до модального.


1

Просто заради обговорення я виведу клас з JUCE під назвою AudioSampleBuffer . Зараз цей клас існує, щоб вмістити фрагмент аудіо (або, можливо, досить довгий фрагмент) аудіо. Він знає кількість каналів, кількість вибірок (на канал), схоже, прихильне до 32-бітового IEEE float, а не зі змінним числовим поданням чи розміром слів (але це не є проблемою для мене). Існують функції членів, які дозволяють отримати numChannels або numSamples та покажчики на будь-який конкретний канал. Ви можете зробити AudioSampleBuffer довше або коротше. Я припускаю, що колишній нуль-прокладки буфера, а другий скорочується.

Є кілька приватних членів цього класу, які використовуються для виділення місця в спеціальній купі, яку використовує JUCE.

Але цього не вистачає AudioSampleBuffer (і я мав кілька дискусій з Жулем про це): член подзвонив SampleRate. Як міг цього пропустити?

Єдиною відповідальністю, яку потрібно виконати AudioSampleBuffer, є адекватне представлення фізичного звуку, який він чує, що представляють його зразки. Коли ви вводите AudioSampleBuffer з чогось, що читає звуковий файл або з потоку, є додатковий параметр, який потрібно отримати та передати разом з AudioSampleBuffer методам обробки (скажімо, це фільтр), який повинен знати швидкість вибірки або, врешті-решт, до методу, який відтворює буфер, щоб його почули (або передає його кудись інше). Що б там не було.

Але ви повинні продовжувати передавати цей SampleRate, який притаманний конкретному звуку, що живе в AudioSampleBuffer, всюди. Я бачив код, де постійну 44100.0f передавали функції, тому що програміст, здавалося, не знав, що ще робити.

Це приклад невиконання своєї єдиної відповідальності.


1

Конкретний спосіб може бути зроблений, виходячи з того, що ви сказали - що висока згуртованість веде за собою єдину відповідальність, ви можете виміряти згуртованість. Максимальний згуртований клас містить усі поля, які використовуються у всіх методах. Незважаючи на те, що максимально згуртований клас не завжди можливий і бажаний, все-таки найкраще досягти цього. Завдяки цій меті проектування класу досить легко зробити висновок, що ваш клас не може мати багато методів або полів (деякі кажуть, щонайбільше 7).

Ще один спосіб - з чистої основи OOP - моделювання реальних об'єктів. Набагато простіше бачити відповідальність за реальні об’єкти. Однак, якщо реальний об'єкт занадто складний, розбийте його на кілька об'єктів, що контактують, кожен з них несе власну відповідальність.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.