Кое-кто из программистов считает, что сочетание этих трех функций в одном классе вполне уместно. В конце концов, классы и должны собирать вместе функции, работающие с одними и теми же переменными. Однако проблема в том, что все три функции изменяются по совершенно разным причинам. Функция calculatePay (рассчитать зарплату) изменяется вместе с бизнес-правилами расчета заплаты. Функция reportHours (отчитаться о часах) изменяется, когда требуется другой формат отчета. Функция save (сохранить) изменяется, когда администратор базы данных меняет схему базы данных. В совокупности эти три причины делают Employee очень неустойчивым классом. Он будет меняться по каждой из этих причин. И что еще важнее, эти изменения затронут любые классы, которые зависят от Employee.

В хорошей архитектуре система разделена на компоненты, которые можно развернуть независимо. Независимость развертывания означает, что изменение одного компонента не требует повторного развертывания других. Но если Employee интенсивно используется многими классами в других компонентах, каждое изменение Employee может требовать повторного развертывания других компонентов, что сводит на нет основное преимущество компонентного подхода к проектированию (или SOA, если вам нравится это более модное название). Следующее простое разделение решает проблему:

public class Employee {

   public Money calculatePay()…

}

public class EmployeeReporter {

   public String reportHours(Employee e)…

}

public class EmployeeRepository {

   public void save(Employee e)…

}

Каждый класс можно поместить в отдельный компонент. Или, выражаясь точнее, все классы, создающие отчеты, поместить в компонент отчетов. Все классы, связанные с базами данных, можно поместить в компонент хранилища. А все бизнес-правила поместить в компонент бизнес-правил.

Внимательный читатель заметит, что в приведенном решении остаются зависимости. Другие классы по-прежнему зависят от Employee. Поэтому если Employee изменится, вполне возможно, что эти классы придется заново скомпилировать и развернуть. Таким образом, Employee невозможно модифицировать, а потом развернуть независимо. Однако другие классы можно модифицировать и независимо развернуть. Никакая их модификация не требует перекомпиляции и повторного развертывания остальных классов. Даже Employee можно независимо развернуть, если тщательно применить принцип инверсии зависимости (DIP, dependency inversion principle), но это уже тема для другой книги.[27]

Продуманное применение принципа единственной ответственности, то есть разделение тех сущностей, которые изменяются по разным причинам, является одной из основ создания архитектур со структурой независимо развертываемых компонентов.

<p>Сначала скажите «да»</p><p>Алекс Миллер</p>

Недавно я был в продуктовом магазине и обыскался там эдамаме, зеленых соевых бобов (я лишь приблизительно догадывался, что это какие-то овощи). Я не знал, где мне искать этот продукт: в овощном отделе, в отделе замороженных продуктов или на полках с консервами? Наконец я сдался и обратился за помощью к сотруднице магазина. Она тоже не знала!

Сотрудница магазина могла отреагировать на мою просьбу по-разному. Она могла дать мне понять, что только дурак не знает, где это искать, или отделаться туманными намеками, или даже просто сказать, что у них нет такого товара. Но она посчитала возможным найти решение и помочь покупателю. Позвав других сотрудников, она уже через пару минут отвела меня к нужному товару. Эдамаме оказались в отделе замороженных продуктов.

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

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

В какой-то момент на меня снизошло прозрение, и я увидел, что возможен другой подход к работе, который отличается от моего всего лишь начальным да вместо начального нет. Я пришел к убеждению, что начинать разговор с положительного ответа — важнейшая часть работы технического руководителя.

Перейти на страницу:

Все книги серии Профессионально

Похожие книги