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

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

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

Cтраница 40

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

Рис. 17.6. ReSharper зависит от Visual Studio


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

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

Границы проводятся там, где есть ось изменения. Компоненты по разным сторонам границы изменяются с разными скоростями и по разным причинам.

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

Это снова простой принцип единственной ответственности, подсказывающий, где провести границы.

Заключение

Прежде чем провести линии границ в архитектуре программного обеспечения, систему нужно разделить на компоненты. Некоторые из этих компонентов реализуют основные бизнес-правила; другие являются плагинами, содержащими функции, которые не имеют прямой связи с бизнес-правилами. Затем можно организовать код в компонентах так, чтобы стрелки между ними указывали в одном направлении — в сторону бизнес-правил.

В этом без труда можно заметить принципы инверсии зависимостей (Dependency Inversion Principle) и устойчивости абстракций (Stable Abstractions Principle). Стрелки зависимостей направлены от низкоуровневых деталей в сторону высокоуровневых абстракций.

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

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

Пересечение границ

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

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

Ужасный монолит

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

С точки зрения развертывания это единый выполняемый файл — так называемый монолит. Этот файл может быть статически скомпонованным проектом на C или C++, множеством файлов классов Java, объединенных в выполняемый jar-файл, множеством двоичных ресурсов .NET, объединенных в один выполняемый файл .EXE, и т.д.

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

Такие архитектуры почти всегда зависят от некоторой разновидности динамического полиморфизма [38], используемой для управления внутренними зависимостями. Это одна из причин, почему объектно-ориентированная парадигма приобрела такую важность в последние десятилетия. В отсутствие объектно-ориентированной или эквивалентной формы полиморфизма архитекторы вынуждены возвращаться к порочной практике использования указателей на функции, чтобы добиться требуемого разделения. Большинство архитекторов считают, что использование указателей для ссылки на функции слишком рискованно, и они вынужденно отказываются от любых видов разделения на компоненты.

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

На рис. 18.1 изображен поток управления, пересекающий границу слева направо. Компонент Client вызывает функцию f(), находящуюся в компоненте Service. Выполняя вызов, он передает экземпляр данных Data. Метка просто сообщает, что это структура данных (Data Structure). Структура Data может передаваться как аргумент функции или каким-то иным, более сложным способом. Обратите внимание, что определение структуры Data находится на вызываемой стороне.


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

Рис. 18.1. Поток управления пересекает границу в направлении  от нижнего уровня к верхнему


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

На рис. 18.2 изображен поток управления, пересекающий границу слева направо, как и прежде. Высокоуровневый компонент Client вызывает функцию f(), находящуюся в низкоуровневом компоненте ServiceImpl, посредством интерфейса Service. Но обратите внимание, что все зависимости пересекают границу в направлении справа налево и указывают в сторону высокоуровневого компонента. Отметьте также, что теперь определение структуры данных находится на вызывающей стороне.

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