DDD Java с Spring - репозиторий, возвращающий Mono / Flux - PullRequest
0 голосов
/ 04 июня 2019

Меня интересует одна проблема, возникающая при реализации реактивного хранилища Mongo в проекте DDD, который я реализую с помощью Java и Spring Boot.Предположим, у нас есть такая структура пакета:

/app 
  |
  |------/application
  |        | 
  |        |------/order
  |                 |
  |                 |------OrderApplicationService.java
  |
  |------/domain
  |        |
  |        |------/order
  |                 |
  |                 |------Order.java
  |                 |------OrderRepository.java 
  |
  |------/infrastructure
           |
           |------/mongo
                    |
                    |------MongoOrderRepository.java

Я мой OrderRepository.java Я хочу иметь метод для сохранения моего ордера:

public interface OrderRepository {

    Order save(Order order);
}

И использовать его в моей службе приложений:

@Service
public class OrderApplicationService {

    private final OrderRepository orderRepository;

    public OrderApplicationService(OrderRepository orderRepository) {
        this.orderRepository = orderRepository;
    }

    public void createOrder() {
        //Dumb order creation
        Order createdOrder = clientRepository.save(new Order());
    }
}

Далее я хочу написать MongoOrderRepository, который реализует OrderRepository.Предположим, я буду использовать ReactiveMongoTemplate.Проблема в том, что все его методы возвращают Flux или Mono, поэтому я не могу реализовать свой метод из интерфейса OrderRepository.

Возможные решения, которые я вижу:

  1. Сделайте метод 'save' в OrderRepository вернуть ордер, завернутый в Mono.Этот подход создаст слой домена с типами, специфичными для Reactor, и нарушит правило, гласящее, что уровень домена должен быть свободен от кода структуры.
  2. Разработать некоторый слой обертки, но это приведет к некоторому шаблонному коду.
  3. Переместить OrderService.java на уровень инфраструктуры, но это также нарушает некоторые базовые концепции DDD.

Кто-нибудь видит какие-либо более эффективные решения?

1 Ответ

1 голос
/ 05 июня 2019

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

В чем выгода использования Flux или Mono и какова их реклама в качестве части интерфейса?Если их нет, вы можете сохранить детали реализации в реализации репозитория и освободить интерфейс от реактивных объектов.

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

При этом, возможно, вы захотите проверить другой подход: с CQRS и гексагональной архитектурой вы можете иметь лучшее из обоих миров:

  • Наличие чистого интерфейса репозитория для команды (часть «Обновление и создание»)
  • Использование службы запросов (простой POJO, если вы находитесь в Java, определенном в пакете приложения), возвращаяMono или Flux для запроса (часть для чтения)

    OrderApplicationService.java (здесь идет команда «Создать обновление для удаления с помощью команд») OrderQueryService.java (здесь идет часть для чтения)

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

В моих службах запросов я использовал простые JDBC-шаблоны, например, при использовании Hibernate в реализации репозитория.

...