(actor).

Соответственно, окончательная версия принципа единственной ответственности выглядит так:

Модуль должен отвечать за одного и только за одного актора.

Теперь определим, что означает слово «модуль». Самое простое определение – файл с исходным кодом. В большинстве случаев это определение можно принять. Однако некоторые языки среды разработки не используют исходные файлы для хранения кода. В таких случаях модуль – это просто связный набор функций и структур данных.

Слово «связный» подразумевает принцип единственной ответственности. Связность – это сила, которая связывает код, ответственный за единственного актора.

Пожалуй, лучший способ понять суть этого принципа – исследовать признаки его нарушения.

Признак 1: непреднамеренное дублирование

Мой любимый пример – класс Employee из приложения платежной ведомости. Он имеет три метода: >calculatePay(), >reportHours() и >save() (рис. 7.1).


Рис. 7.1. Класс Employee


Этот класс нарушает принцип единственной ответственности, потому что три его метода отвечают за три разных актора.

• Реализация метода >calculatePay() определяется бухгалтерией.

• Реализация метода >reportHours() определяется и используется отделом по работе с персоналом.

• Реализация метода >save() определяется администраторами баз данных.

Поместив исходный код этих трех методов в общий класс >Employee, разработчики объединили перечисленных акторов. В результате такого объединения действия сотрудников бухгалтерии могут затронуть что-то, что требуется сотрудникам отдела по работе с персоналом.

Например, представьте, что функции >calculatePay() и >reportHours() используют общий алгоритм расчета не сверхурочных часов. Представьте также, что разработчики, старающиеся не дублировать код, поместили реализацию этого алгоритма в функцию с именем >regularHours() (рис. 7.2).


Рис. 7.2. Общий алгоритм


Теперь вообразите, что сотрудники бухгалтерии решили немного изменить алгоритм расчета не сверхурочных часов. Сотрудники отдела по работе с персоналом были бы против такого изменения, потому что вычисленное время они используют для других целей.

Разработчик, которому было поручено внести изменение, заметил, что функция >regularHours() вызывается методом >calculatePay(), но, к сожалению, не заметил, что она также вызывается методом >reportHours().

Разработчик внес требуемые изменения и тщательно протестировал результат. Сотрудники бухгалтерии проверили и подтвердили, что обновленная функция действует в соответствии с их пожеланиями, после чего измененная версия системы была развернута.

Разумеется, сотрудники отдела по работе с персоналом не знали о произошедшем и продолжали использовать отчеты, генерируемые функцией >reportHours(), но теперь содержащие неправильные цифры. В какой-то момент проблема вскрылась, и сотрудники отдела по работе с персоналом разом побледнели от ужаса, потому что ошибочные данные обошлись их бюджету в несколько миллионов долларов.

Все мы видели нечто подобное. Эти проблемы возникают из-за того, что мы вводим в работу код, от которого зависят разные акторы. Принцип единственной ответственности требует разделять код, от которого зависят разные акторы.

Признак 2: слияния

Слияния – обычное дело для исходных файлов с большим количеством разных методов. Эта ситуация особенно вероятна, если эти методы отвечают за разных акторов.

Например, представим, что коллектив администраторов баз данных решил внести простое исправление в схему таблицы >Employee. Представим также, что сотрудники отдела по работе с персоналом пожелали немного изменить формат отчета, возвращаемого функцией