2017-02-22 36 views
2

Я реализую бэкэнд для какого-то магазина, который полностью написан на интерфейсе, и только конечное состояние (данные) отправляются на сервер. Я пытаюсь использовать DDD с CQRS/ES.Можно разбить большие команды на более мелкие, если в действительности не нужны в настоящее время?

Счастливый сценарий UseCase (например, обобщенное):

  • Учитывая, что пользователь, Корзина и CartItem существует.
  • Пользователь может добавить CartItem типа X в корзину

  • Пользователь может указать (установить некоторые Params) из CartItem Y

  • Пользователь может добавить CartItem типа Y

  • Пользователь может выбрать адрес от его создания (адресов их беспокойство других до н.э.)

  • Пользователь может разместить заказ

Теперь, поскольку это все происходит на Frontend, мой единственный механизм доставки - это некоторые необработанные данные из GraphQL. Должен ли я иметь на уровне приложения некоторый CreateNewOrderFromGraphQL с методом create ($ someGraphQLData); что просто создает относительно большой CreateNewOrderCommand (потому что он должен содержать адрес, CartItems, промо-код и т. д.) и передает его через командную шину в мою модель домена, которая создает весь заказ?

Или я должен думать о своей модели домена так же, как это делается на интерфейсе, а затем в моем CreateNewOrderFromGraphQL разбивать большие необработанные данные GraphQL на отдельные команды, такие как CreateCartCommand, AddItemToCartCommand, CreateOrderCommand (который будет состоять из идентификатора корзины, идентификатора адреса , а может быть, некоторые детали), а затем вызвать их последовательно?

Какие соображения я должен взять на себя?

+0

Ваши достоинства? В каких условиях «порядок» может быть создан и размещен?Вы должны создавать команды на основе ваших инвариантов 'Агрегата '. –

+0

@ConstantinGALBENU Заказ может быть создан, если: 1) Пользователь данного идентификатора существует 2) Адрес данного идентификатора существует 3) Корзина действительна, это означает, что каждый CartItem в корзине заказа передал свои собственные инварианты. Поэтому, я полагаю, более разумно нарушить это, поэтому я могу сначала создать корзину, а затем добавить элементы один за другим и в конце концов просто передать идентификатор этой тележки для заказа. Тогда я могу, возможно, в конечном итоге сообщить об ошибке на конкретный элемент (но все остальное может обрабатываться нормально) при создании тележки (и, возможно, на многих этапах) вместо того, чтобы запретить «создавать весь порядок со всем данным»? – Tom

+0

У вас нет контроля над интерфейсом? Поскольку в идеале с DDD, ваше намерение вашего пользователя соответствует действиям в пользовательском интерфейсе полностью на бэкэнд. Если вы не можете этого сделать, я бы попытался работать так, как если бы мог, и создать фасад для вашего интерфейса, который заставит интерфейс выглядеть так, как будто он сам генерировал команды. С некоторой удачей однажды интерфейс может быть обновлен/обновлен до идеальной ситуации, но если нет, то ваш бэкэнд не пострадает за это. – Arwin

ответ

2

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

Я думаю, что вы должны проектировать свою модель домена (командная сторона) как агностик UI, где интерфейс GraphQL является своего рода пользовательским интерфейсом.

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

Тележка может быть выполнена как другая Aggregate. Он должен иметь команды вроде CreateCartCommand и AddItemToCartCommand. Или это можно сделать как CRUD, если нет реальных инвариантов.

Затем OrderAggregate может иметь PlaceOrderCommand, с элементами из корзины в качестве аргументов и AddressId и UserId, которые уже проверены на наличие на уровне приложений. Этот Aggregate защищает свои собственные инварианты, например total price <= some max value или проверяет статус инвентаря (в случае, если инвентарь не находится в другом BC).