Перейти к содержимому

Конструирование системы. Часть 4 — Организация кода

Domain-Driven Development with Clean Architecture

Вспомним что нам предлагает DDD:

PoEAA

  • Domain (Шаблоны домена)
    TransactionScript (сценарий транзакции)
    набор действий объединённый в единую транзакцию
    DomainModel (модель предметной области)
    модели объединяющие в себе действия
    ServiceLayer (слой служб)
    сервисы объединяющие в себе логические действия
  • Source (Шаблоны источника данных)
    TableDataGateway (шлюз таблицы данных)
    работа с таблицами и строками, подходит к TransactionScript, DomainModel
    RowDataGateway (шлюз записи данных)
    работа со строкой, подходит к TransactionScript, DomainModel, ServiceLayer
    DataMapper (преобразователь данных)
    гибрид первых двух, подходит к DomainModel, ServiceLayer
  • Presentation (Шаблоны представления)
    ModelViewController (Модель-Вьюха-Контроллер)
    — FrontController (контроллер запросов)
    Контроллер обработки общего поведения для всех запросов
    — ApplicationController (контроллер приложения)
    Контроллер обработки запроса извлекающий данные для навигации и т.д.

    — PageController (контроллер страниц)
    Контроллер для страниц, у запроса свои контроллеры страниц обрабатывающие ввод

    — TemplateView (шаблонизатор)
    преобразование данных представляется по шаблону
    — TransformView (трансформатор)
    преобразование данных представляется с трансформацией
    TwoStepView (преобразователь)
    гибрид преобразований — трансформация с последующей шаблонизацией

 

Теперь вспомним что нам предлагает Clean Architecture:

Чистая архитектура

  • Тестируемая, не зависимая от UI, БД, фреймворков и библиотек архитектура
  • Более верхние слои ничего не знают о существовании более нижних
  • Более нижние слои используют более верхние внедряя их через интерфейсы

 

Учитывая всё это, попробуем сделать сплит этих вариантов:

Framework Application Domain Source
FrontController
ApplicationControllerDrivers
Database
Services
PageController
— Run UseCase
— Send DomainEvents
TemplateView
TransformView
TwoStepView
UseCase
— TransactionScript
— ServiceLayer
— DomainModel
— .. GoFCollection
Entity
TableDataGateway
RowDataGateway
DataMapper
Слой фреймворка/библиотек, слой отвечает за стабильную работу приложения и предоставляет ему необходимые библиотеки Слой приложения, слой отвечает за запуск необходимого варианта использования и возвращает его результат в необходимом виде Слой обработки данных (слой домена), слой отвечает за работу вариантов использования (UseCase) Слой доступа к данным, слой отвечает за работу с хранилищами данных

Невозможно не заметить, что у нас появились четыре ярко выделенных блока. Связь между ними организуется с помощью «портов» (интерфейсов) и «адаптеров» (реализаций).

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

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

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

Теперь у нас есть «варианты использования» системы, возможно детализированные до конкретных шагов, и выбранная архитектура бизнес-логики. Теперь осталось дело за малым, перенести варианты использования в выбранную архитектуру и покрыть её тестами.

назад

Опубликовано вОбщее