Этого можно добиться, выделив процессы в классы, а классы в компоненты, ограниченные двойными линиями на рис. 8.2. Компонент в левом верхнем углу на этом рисунке –
Классы, отмеченные символами , – это интерфейсы; отмеченные символами
– это структуры данных (data structures). Простые стрелки соответствуют отношениям
Первое, на что следует обратить внимание, – все зависимости определены на уровне
Рис. 8.2. Выделение процессов в классы и выделение классов в компоненты
Также важно отметить, что каждая двойная линия пересекается
Позволю себе повторить еще раз: если компонент A требуется защитить от изменений в компоненте B, компонент B должен зависеть от компонента A.
Нам нужно защитить
Интерактор находится в позиции, лучше соответствующей принципу открытости/закрытости. Изменения в
Рис. 8.3. Отношения компонентов однонаправленны
Почему
Несмотря на то что
Обратите внимание, что в результате выстраивается иерархия защиты, основанная на понятии «уровня».
Именно так работает принцип открытости/закрытости на архитектурном уровне. Архитекторы разделяют функциональные возможности, опираясь на то, как, почему и когда их может потребоваться изменить, и затем организуют их в иерархию компонентов. Компоненты, находящиеся на верхних уровнях в такой иерархии, защищаются от изменений в компонентах на нижних уровнях.
Управление направлением
Если вы испытали шок от схемы классов, представленной выше, взгляните на нее еще раз. Основная сложность в ней заключается в необходимости сориентировать зависимости между компонентами в правильных направлениях.
Например, интерфейс шлюза финансовых данных между генератором финансового отчета и диспетчером финансовых данных добавлен с целью обратить направление зависимости, которая иначе была бы направлена из компонента
Сокрытие информации
Интерфейс заказчика финансового отчета служит другой цели – защитить контроллер финансового отчета от необходимости знать внутренние особенности
Транзитивные (переходящие) зависимости нарушают общий принцип, согласно которому программные сущности не должны зависеть от того, что они не используют непосредственно. Мы вновь встретимся с этим принципом, когда будем обсуждать принципы разделения интерфейсов и совместного повторного использования (Common Reuse Principle; CRP).