Обычно мы разрешаем это кажущееся противоречие с использованием принципа инверсии зависимостей (Dependency Inversion Principle). В таких языках, как Java, например, мы можем определять интерфейсы и использовать механизм наследования, чтобы направление зависимостей в исходном коде было противоположно направлению потока управления на границах справа.
Допустим, что вариант использования должен вызвать презентатора. Такой вызов нельзя выполнить непосредственно, потому что иначе нарушится правило зависимостей: никакие имена, объявленные во внешних кругах, не должны упоминаться во внутренних. Поэтому вариант использования должен вызвать интерфейс (на рис. 22.1 подписан как «Порт вывода варианта использования»), объявленный во внутреннем круге, а презентатор во внешнем круге должен реализовать его.
Тот же прием используется для всех пересечений границ в архитектуре. Мы используем преимущество динамического полиморфизма, чтобы обратить зависимости в исходном коде в направлении, противоположном потоку управления, и тем самым соблюсти правило зависимостей при любом направлении потока управления.
Какие данные пересекают границы
Обычно через границы данные передаются в виде простых структур. При желании можно использовать простейшие структуры или объекты передачи данных (Data Transfer Objects; DTO). Данные можно также передавать в вызовы функций через аргументы. Или упаковывать их в ассоциативные массивы или объекты. Важно, чтобы через границы передавались простые, изолированные структуры данных. Не нужно хитрить и передавать объекты сущностей или записи из базы данных. Структуры данных не должны нарушать правило зависимостей.
Например, многие фреймворки для работы с базами данных возвращают ответы на запросы в удобном формате. Их можно назвать «представлением записей». Такие представления записей не должны передаваться через границы внутрь. Это нарушает правило зависимостей, потому что заставляет внутренний круг знать что-то о внешнем круге.
Итак, при передаче через границу данные всегда должны принимать форму, наиболее удобную для внутреннего круга.
Диаграмма на рис. 22.2 показывает типичный сценарий работы веб-системы на Java, использующей базу данных. Веб-сервер принимает исходные данные от пользователя и передает их контроллеру Controller в левом верхнем
Рис. 22.2.Типичный сценарий работы веб-системы на Java, использующей базу данных
углу. Контроллер упаковывает данные в простой Java-объект InputData и передает его через интерфейс InputBoundary классу UseCaseInteractor. Класс UseCaseInteractor интерпретирует данные и использует их для управления действиями сущностей Entities. Он также переносит данные из базы данных Database в память сущностей Entities через интерфейс DataAccessInterface. По завершении UseCaseInteractor забирает данные из сущностей Entities и конструирует из них другой простой Java-объект OutputData. Затем объект OutputData передается через интерфейс OutputBoundary презентатору Presenter.
Презентатор Presenter переупаковывает данные из объекта OutputData в объект ViewModel, еще один простой Java-объект, содержащий в основном строки и флаги, используемые представлением View для отображения данных. Объект OutputData мог бы содержать объекты типа Date, но Presenter преобразует их в процессе формирования ViewModel в строковые значения, пригодные для отображения. То же произойдет с объектами типа Currency и любыми другими бизнес-данными. Имена кнопок Button и пунктов меню MenuItem помещаются в ViewModel вместе с флагами, сообщающими представлению View, следует ли отобразить эти кнопки и пункты меню в неактивном состоянии.
В результате представлению View практически ничего не приходится делать, кроме как перенести данные из ViewModel в HTML-страницу.
Обратите внимание на направления зависимостей. Все они пересекают линии границ только в направлении внутрь, следуя правилу зависимостей.
Следование этим простым правилам не требует больших усилий и поможет сохранить душевный покой в будущем. Разделив программное обеспечение на уровни и соблюдая правило зависимостей, вы создадите систему, которую легко протестировать — со всеми вытекающими из этого преимуществами. Когда какой-либо из внешних элементов системы, например база данных или веб-фреймворк, устареет, вы сможете без всякой суеты заменить его.
Читать дальше
Конец ознакомительного отрывка
Купить книгу