На це немає чіткої відповіді. Хоча питання вузьке, пояснень немає.
Для мене це щось на зразок бритва Оккама, якщо ви хочете. Це ідеал, де я намагаюся порівняти свій поточний код. Це важко забити це простими і простими словами. Ще одна метафора - це «одна тема», яка є настільки ж абстрактною, тобто важкою для розуміння, як «одна відповідальність». Третім описом буде "робота з одним рівнем абстракції".
Що це означає практично?
Останнім часом я використовую стиль кодування, який складається здебільшого з двох фаз:
Першу фазу найкраще описати як творчий хаос. У цій фазі я записую код у міру течії думок - тобто сирих і негарних.
Фаза II - це повна протилежність. Це як прибирання після урагану. Для цього потрібна найбільше праці та дисципліни. А потім я дивлюся на код з точки зору дизайнера.
Зараз я працюю здебільшого в Python, що дозволяє мені мислити предмети та класи пізніше. Перша фаза I - я записую лише функції та поширюю їх майже випадковим чином у різних модулях. На II фазі , після того, як я все розібрався, я детальніше ознайомлююся з тим, який модуль має справу з якою частиною рішення. І, переглядаючи модулі, у мене виникають теми . Деякі функції пов'язані тематично. Це хороші кандидати на заняття . І після того, як я перетворив функції на класи - що майже робиться з відступом та додаванням self
до списку параметрів у python;) - я використовую, SRP
як Occam's Razor, щоб викреслити функціональність для інших модулів та класів.
Поточним прикладом може бути написання функцій невеликого експорту днями.
Виникла потреба у форматі csv , excel та комбінованих листах excel на блискавці.
Простий функціонал виконувався в трьох видах (= функції). Кожна функція використовувала загальний метод визначення фільтрів та другий метод для отримання даних. Потім у кожній функції відбувалася підготовка експорту і була доставлена у відповідь від сервера.
Занадто багато рівнів абстракції змішалося:
I) розгляд вхідного / вихідного запиту / відповіді
II) визначення фільтрів
III) отримання даних
IV) перетворення даних
Найпростішим кроком було використання однієї абстракції ( exporter
) для обробки шарів II-IV на першому кроці.
Залишилася лише тема, яка стосувалась запитів / відповідей . На тому ж рівні абстрагування відбувається вилучення параметрів запиту, що нормально. Тому я мав за цей погляд одну "відповідальність".
По-друге, мені довелося розбити експортера, який, як ми бачили, складався щонайменше з трьох інших шарів абстракції.
Визначення критеріїв фільтру та фактичного вилучення майже на одному рівні абстракції (фільтри потрібні для отримання потрібного підмножини даних). Ці рівні були розміщені на щось подібне до рівня доступу до даних .
На наступному кроці я розбив фактичні механізми експорту: Де потрібно було записувати у тимчасовий файл, я розділив це на два "обов'язки": один для фактичного запису даних на диск та інший, який стосувався фактичного формату.
У ході формування класів і модулів все стало зрозуміліше, що належало куди. І завжди латентне питання, чи робить клас занадто багато .
Як Ви визначаєте, які обов'язки повинен мати кожен клас, і як Ви визначаєте відповідальність у контексті СРП?
Важко дати рецепт, який слід дотримуватися. Звичайно, я міг би повторити криптовалюту «один рівень абстракції» - правило, якщо це допомагає.
Переважно для мене це свого роду "художня інтуїція", яка призводить до сучасного дизайну; Я моделюю код, як художник може ліпити глину або займатися живописом.
Уявіть мене як кодуючого Боб Росса ;)