Книга Чистая архитектура. Искусство разработки программного обеспечения, страница 18. Автор книги Роберт Сесил Мартин

Разделитель для чтения книг в онлайн библиотеке

Онлайн книга «Чистая архитектура. Искусство разработки программного обеспечения»

Cтраница 18

Классы, отмеченные символами , — это интерфейсы; отмеченные символами — это структуры данных (data structures). Простые стрелки соответствуют отношениям использования. Стрелки с треугольным наконечником соответствуют отношениям реализации или наследования.

Первое, на что следует обратить внимание, — все зависимости определены на уровне исходного кода. Стрелка, направленная от класса A к классу B, означает, что в исходном коде класса A упоминается имя класса B, но в коде класса B не упоминается имя класса A. Так, на рис. 8.2 диспетчер финансовых данных знает о существовании шлюза через отношение реализации, а шлюз финансовых данных ничего не знает о диспетчере.


Чистая архитектура. Искусство разработки программного обеспечения

Рис. 8.2. Выделение процессов в классы и выделение классов в компоненты


Также важно отметить, что каждая двойная линия пересекается только в одном направлении. Это означает, что все отношения компонентов однонаправленны, как показано на графе компонентов (рис. 8.3). Эти стрелки указывают на компоненты, которые мы стремимся защитить от изменения.

Позволю себе повторить еще раз: если компонент A требуется защитить от изменений в компоненте B, компонент B должен зависеть от компонента A.

Нам нужно защитить контроллер от изменений в презентаторах. Нам нужно защитить презентаторы от изменений в представлениях. Нам нужно защитить интерактор от изменений в... во всех остальных компонентах.

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


Чистая архитектура. Искусство разработки программного обеспечения

Рис. 8.3. Отношения компонентов однонаправленны


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

Несмотря на то что контроллер является не таким важным компонентом, как интерактор, он важнее презентаторов и представлений. А презентаторы, хотя и менее важные, чем контроллеры, в свою очередь, важнее представлений.

Обратите внимание, что в результате выстраивается иерархия защиты, основанная на понятии «уровня». Интеракторы занимают самый верхний уровень, поэтому они должны быть самыми защищенными. Представления занимают самый низкий уровень, поэтому они наименее защищены. Презентаторы находятся уровнем выше представлений, но ниже контроллера или интерактора.

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

Управление направлением

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

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

Сокрытие информации

Интерфейс заказчика финансового отчета служит другой цели — защитить контроллер финансового отчета от необходимости знать внутренние особенности интерактора. В отсутствие этого интерфейса контроллер получил бы транзитивные зависимости от финансовых сущностей.

Транзитивные (переходящие) зависимости нарушают общий принцип, согласно которому программные сущности не должны зависеть от того, что они не используют непосредственно. Мы вновь встретимся с этим принципом, когда будем обсуждать принципы разделения интерфейсов и совместного повторного использования (Common Reuse Principle; CRP).

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

Заключение

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

Глава 9. Принцип подстановки Барбары Лисков
Чистая архитектура. Искусство разработки программного обеспечения

В 1988 году Барбара Лисков написала следующие строки с формулировкой определения подтипов.

Здесь требуется что-то вроде следующего свойства подстановки: если для каждого объекта o1 типа S существует такой объект o2 типа T, что для всех программ P, определенных в терминах T, поведение P не изменяется при подстановке o1 вместо o2, то S является подтипом T [24].

Чтобы понять эту идею, известную как принцип подстановки Барбары Лисков (Liskov Substitution Principle; LSP), рассмотрим несколько примеров.

Руководство по использованию наследования

Представьте, что у нас есть класс с именем License, как показано на рис. 9.1. Этот класс имеет метод с именем calcFee(), который вызывается приложением Billing. Существует два «подтипа» класса License: PersonalLicense и BusinessLicense. Они реализуют разные алгоритмы расчета лицензионных отчислений.


Вход
Поиск по сайту
Ищем:
Календарь
Навигация