Роберт Мартин - Чистая архитектура. Искусство разработки программного обеспечения
- Название:Чистая архитектура. Искусство разработки программного обеспечения
- Автор:
- Жанр:
- Издательство:Питер
- Год:2018
- Город:СПб.
- ISBN:978-5-4461-0772-8
- Рейтинг:
- Избранное:Добавить в избранное
-
Отзывы:
-
Ваша оценка:
Роберт Мартин - Чистая архитектура. Искусство разработки программного обеспечения краткое содержание
Роберт Мартин дает прямые и лаконичные ответы на ключевые вопросы архитектуры и дизайна. «Чистую архитектуру» обязаны прочитать разработчики всех уровней, системные аналитики, архитекторы и каждый программист, который желает подняться по карьерной лестнице или хотя бы повлиять на людей, которые занимаются данной работой.
Чистая архитектура. Искусство разработки программного обеспечения - читать онлайн бесплатно ознакомительный отрывок
Интервал:
Закладка:
Я уже упоминал пару причин, почему многоуровневую архитектуру следует считать неудовлетворительной, но это еще не все. Цель многоуровневой архитектуры — отделить код, выполняющий схожие функции. Веб-интерфейс отделяется от бизнес-логики, которая, в свою очередь, отделяется от механизмов доступа к данным. Как было показано на UML-диаграмме классов, с точки зрения реализации уровень примерно соответствует пакету. С точки зрения доступности кода, чтобы OrdersController мог зависеть от интерфейса OrdersService, последний должен быть объявлен общедоступным, потому что класс и интерфейс находятся в разных пакетах. Аналогично общедоступным должен быть объявлен интерфейс OrdersRepository, так как он используется классом OrdersServiceImpl, находящимся за пределами пакета, определяющего функции доступа к хранилищу.
В настоящей многоуровневой архитектуре стрелки зависимостей всегда должны быть направлены вниз. Уровни должны зависеть только от соседнего, нижележащего уровня. В результате введения некоторых правил, определяющих, как должны зависеть элементы в базе кода, получается красивый, чистый, ациклический граф зависимостей. Большая проблема в том, что мы можем хитрить, вводя некоторые нежелательные зависимости, и при этом получать замечательный ациклический граф зависимостей.
Предположим, что на работу был нанят новый специалист, он присоединился к вашей команде и вы поручаете ему реализовать другой вариант использования, связанный с заказами. Как всякий новичок, этот человек хочет произвести впечатление и реализовать порученное ему задание максимально быстро. Посидев несколько минут с чашкой кофе, новичок замечает существующий класс OrdersController и решает, что это именно тот код, который должен использоваться новой веб-страницей, порученной ему. Но ему нужны некоторые данные о заказах из базы данных. Новичка озаряет: «О, здесь уже есть интерфейс OrdersRepository. Я могу просто внедрить реализацию в мой контроллер. Отлично!» Спустя несколько минут он создает действующую веб-страницу. Но получившаяся UML-диаграмма выглядит, как показано на рис. 34.5.
Стрелки зависимостей все еще направлены вниз, но теперь для некоторых вариантов использования OrdersController минует OrdersService. Такую организацию часто называют нестрогой многоуровневой архитектурой , так как уровням позволено перепрыгивать через смежные, соседние уровни. В некоторых ситуациях это делается намеренно, например, если вы пытаетесь следовать шаблону CQRS [68] В шаблоне CQRS (Command Query Responsibility Segregation — разделение ответственности команд и запросов) для чтения и изменения данных используются разные шаблоны.
. Во многих других случаях нежелательно перепрыгивать через уровень бизнес-логики, особенно если эта бизнес-логика отвечает за авторизацию доступа к отдельным записям, например.

Рис. 34.5.Нестрогая многоуровневая архитектура
Новый вариант использования работает, но наверняка реализован не так, как вам хотелось бы. Нечто подобное я видел во многих командах, которые посещал как консультант, и обычно это проявляется, когда команды начинают выяснять, как выглядит база кода, часто в первый раз.
В такой ситуации необходимо установить правило — архитектурный принцип, — которое гласит, например: «Веб-контроллеры никогда не должны обращаться к хранилищу непосредственно». Проблема, конечно, заключается в исполнении правила. Многие команды, с которыми я встречался, заявляли: «Мы обеспечиваем соблюдение этого принципа строгой дисциплиной и обзорами кода, потому что доверяем нашим разработчикам». Это хорошо, что есть такая уверенность, но все мы знаем, что происходит, когда бюджет и сроки начинают приближаться к концу.
Намного меньше команд сообщали мне, что они используют инструменты статического анализа (например, NDepend, Structure101, Checkstyle) для автоматической проверки и выявления архитектурных нарушений во время сборки. Возможно, вы уже видели такие правила; обычно они имеют форму регулярных выражений или строк с шаблонными символами, которые указывают: «типы в пакете **/web не должны использоваться типами в **/data» и проверяются после этапа компиляции.
Это немного грубоватый подход, но он может помочь, сообщая о нарушениях архитектурных принципов, которые (по вашему мнению) должны помешать вашей команде разработчиков выполнить сборку. Проблема обоих подходов в том, что они чреваты ошибками и цикл обратной связи дольше, чем хотелось бы. Если отключить проверку, в результате код может превратиться в «большой ком грязи» [69] http://www.laputan.org/mud /.
. Лично я хотел бы, чтобы за соблюдением архитектурных принципов следил компилятор.
Это ведет нас к варианту «упаковка по компонентам». Цель этого гибридного подхода, обсуждавшегося до сих пор, — упаковать все обязанности, связанные с одним крупным компонентом, в единый Java-пакет. Речь идет о сервис-ориентированном представлении программной системы, что, собственно, мы наблюдаем в архитектурах микрослужб. Подобно портам и адаптерам, интерпретирующим Веб как всего лишь еще один механизм доставки, методика «упаковка по компонентам» помогает отделить пользовательский интерфейс от этих крупных компонентов. На рис. 34.6 показано, как мог бы выглядеть вариант «просмотр заказов».
По сути, этот подход связывает «бизнес-логику» и код для работы с хранилищем в единое нечто, что мы называем «компонентом». Выше в книге дядюшка Боб дал такое определение компонента:
Компоненты — это единицы развертывания. Они представляют наименьшие сущности, которые можно развертывать в составе системы. В Java — это jar-файлы.

Рис. 34.6.Вариант использования «просмотр заказов»
Мое определение компонента немного отличается: «Группа функциональных возможностей, находящихся за общим чистым интерфейсом, которые постоянно находятся внутри среды выполнения, такой как приложение». Это определение взято из описания модели C4 программной архитектуры («C4 software architecture model») [70] Дополнительные сведения можно найти по адресу https://www.structurizr.com/help/c4 .
, которая определяет простую иерархическую организацию статических структур программной системы в терминах контейнеров, компонентов и классов (или кода). В этом описании говорится, что программная система состоит из одного или нескольких контейнеров (например, веб-приложений, мобильных приложений, обычных приложений, баз данных, файловых систем), каждый из которых содержит один или несколько компонентов, которые, в свою очередь, реализуются одним или несколькими классами (или кодом). Находится ли каждый компонент в отдельном jar-файле — это уже второстепенный вопрос.
Интервал:
Закладка: