Чистая архитектура. Искусство разработки программного обеспечения
Шрифт:
Эти принципы детально описаны во множестве публикаций [22] . Последующие главы освещают влияние этих принципов на проектирование архитектур, не повторяя подробное обсуждение из этих публикаций. Если вы еще не знакомы с перечисленными принципами, обсуждения, следующего далее, будет недостаточно, чтобы понять их во всех подробностях, поэтому я рекомендую обратиться к документам, перечисленным в сноске.
7. Принцип единственной ответственности
22
Например, Agile Software Development, Principles, Patterns, and Practices, Robert C. Martin, Prentice Hall, 2002 (Роберт С. Мартин. Гибкая разработка программ на Java и C++: принципы, паттерны и методики. М.: Вильямс, 2017. – Примеч. пер.), http://www.butunclebob.com/ArticleS.UncleBob.PrinciplesOfOod и https://en.wikipedia.org/wiki/SOLID_(object-oriented_design) (можно просто выполнить поиск в Google по слову «SOLID»).
Из всех принципов SOLID наиболее трудно понимаемым является принцип единственной ответственности (Single Responsibility Principle, SRP). Это, вероятно, обусловлено выбором названия, недостаточно точно соответствующего сути. Услышав это название, многие программисты решают: оно означает, что каждый модуль должен отвечать за что-то одно.
Самое интересное, что такой принцип действительно существует. Он гласит: функция должна делать что-то одно и только одно. Этот принцип мы используем, когда делим большие функции на меньшие, то есть на более низком уровне. Но он не является одним из принципов SOLID – это не принцип единственной ответственности.
Традиционно принцип единственной ответственности описывался так:
Модуль должен иметь одну и только одну причину для изменения.
Программное обеспечение изменяется для удовлетворения нужд пользователей и заинтересованных лиц. Пользователи и заинтересованные лица как раз и есть та самая «причина для изменения», о которой говорит принцип. Фактически принцип можно перефразировать так:
Модуль должен отвечать за одного и только за одного пользователя или заинтересованное лицо.
К сожалению, слова «пользователь» и «заинтересованное лицо» не совсем правильно использовать здесь, потому что одного и того же изменения системы могут желать несколько пользователей или заинтересованных лиц. Более правильным выглядит понятие группы, состоящей из одного или нескольких лиц, желающих данного изменения. Мы будем называть такие группы акторами (actor).
Соответственно, окончательная версия принципа единственной ответственности выглядит так:
Модуль должен отвечать за одного и только за одного актора.
Теперь определим, что означает слово «модуль». Самое простое определение – файл с исходным кодом. В большинстве случаев это определение можно принять. Однако некоторые языки среды разработки не используют исходные файлы для хранения кода. В таких случаях модуль – это просто связный набор функций и структур данных.
Слово «связный» подразумевает принцип единственной ответственности. Связность – это сила, которая связывает код, ответственный за единственного актора.
Пожалуй, лучший способ понять суть этого принципа – исследовать признаки его нарушения.
Признак 1: непреднамеренное дублирование
Мой любимый пример – класс Employee из приложения платежной ведомости. Он имеет три метода:
Рис. 7.1. Класс Employee
Этот класс нарушает принцип единственной ответственности, потому что три его метода отвечают за три разных актора.
• Реализация метода
• Реализация метода
• Реализация метода
Поместив исходный код этих трех методов в общий класс
Например, представьте, что функции
Рис. 7.2. Общий алгоритм
Теперь вообразите, что сотрудники бухгалтерии решили немного изменить алгоритм расчета не сверхурочных часов. Сотрудники отдела по работе с персоналом были бы против такого изменения, потому что вычисленное время они используют для других целей.
Разработчик, которому было поручено внести изменение, заметил, что функция
Разработчик внес требуемые изменения и тщательно протестировал результат. Сотрудники бухгалтерии проверили и подтвердили, что обновленная функция действует в соответствии с их пожеланиями, после чего измененная версия системы была развернута.
Разумеется, сотрудники отдела по работе с персоналом не знали о произошедшем и продолжали использовать отчеты, генерируемые функцией
Все мы видели нечто подобное. Эти проблемы возникают из-за того, что мы вводим в работу код, от которого зависят разные акторы. Принцип единственной ответственности требует разделять код, от которого зависят разные акторы.
Признак 2: слияния
Слияния – обычное дело для исходных файлов с большим количеством разных методов. Эта ситуация особенно вероятна, если эти методы отвечают за разных акторов.
Например, представим, что коллектив администраторов баз данных решил внести простое исправление в схему таблицы
Два разных разработчика, возможно, из двух разных команд, извлекли класс
Я думаю, мне не нужно рассказывать вам, что всякое слияние сопряжено с некоторым риском. Современные инструменты довольно совершенны, но никакой инструмент не сможет правильно обработать все возможные варианты слияния. В итоге риск есть всегда.
В нашем примере процедура слияния поставила под удар администраторов баз данных и отдел по работе с персоналом. Вполне возможно, что риску подверглась также бухгалтерия.