Tom
Tom

Reputation: 199

Favor breaking up big commands into smaller ones if not actually necessary at present time?

I am implementing backend for some shop, that is fully written on frontend and only final state (data) are sent to backend. I am trying to use DDD with CQRS/ES.

Happy scenario usecase (for example, generalized):

Now, because this all happens on Frontend, my only delivery mechanism now is some raw data from GraphQL. Should I have in Application layer some CreateNewOrderFromGraphQL with method create($someGraphQLData); that just creates relatively big CreateNewOrderCommand (because it needs to contain adress, CartItems, promo code etc) and passes it through command bus into my domain model that creates whole order?

Or should I think about my domain model same way as it is done on frontend and so then in my CreateNewOrderFromGraphQL break big raw GraphQL data into separate commands like CreateCartCommand, AddItemToCartCommand, CreateOrderCommand (which would consist of cart id, adress id, and maybe some details) and then call them in sequence?

What considerations should I take on that?

Upvotes: 2

Views: 70

Answers (1)

Constantin Galbenu
Constantin Galbenu

Reputation: 17683

Because you have many behavior in the front-end and the front-end can't be trusted you are forced to duplicate behavior in the back-end as well. So, let's see what you have here.

I think that you should design your domain model (the command side) to be UI agnostic, where the GraphQL interface is a kind of UI.

So, if a user exists is a check that you already have to do, in the authorization phase of the request. If a user does not exist then the client request should not reach the domain model, it should be denied by the application layer (or similar layer that is between the UI and the domain).

The cart could be done as another Aggregate. It should have commands like CreateCartCommand and AddItemToCartCommand. Or it could be done as CRUD, if there are no real invariants.

Then, the OrderAggregate could have a PlaceOrderCommand, with items from cart as arguments and an AddressId and UserId that are already checked for existence by the Application layer. This Aggregate protects it's own invariants, like total price <= some max value or check inventory status (in case inventory is not in another BC).

Upvotes: 2

Related Questions