1

I’m doing an task based application using Vertical Slice Architecture (VSA) and domain driven design (DDD). Tasks split into commands and queries and using Mediator pattern.

Say I’m having an Order domain object but multiple commands, which do some work and based on that, has to create one or more orders in the system. That could be commands for multiple integrations to retrieve the orders (e-mail, FTP etc.). What is the best options to share some validation logic before allowing each of these to create these orders (verify not already exists in database given some unique keys, verify some limits etc.)?

One option could be to create a specific CreateOrder command to contain that logic, but it seems like an anti-pattern to call commands from commands.

Right now I have created and injected an OrderFactory-class to each of these commands (similar to a service) which returns the domain object (uncommitted), but that does not feel like the right solution.

1
  • "One option could be to create a specific CreateOrder command to contain that logic, but it seems like an anti-pattern to call commands from commands." - on the contrary, seems like composition to me, the bread and butter of OOP. If your commands all have the same interface, you can use the Decorator pattern to attach this validation logic to your commands. If they take different parameters, then maybe you could pass this object into the command as a dependency, and then pass the necessary data to it from the inside. Dec 26, 2021 at 16:02

1 Answer 1

2

You've mentioned that you want to design your application by the patterns of DDD. Eric Evans strongly recommends the "Rich Domain Model" pattern what means that all business logic belongs into domain entities not into commands or elsewhere. Also validations are business rules and belong there.

For interactions with Factorys and Repositories implement a "Domain-Service" to create a solid and reusable "Domain-Core". In this service you can implement some orchestration (on a "createOrder"-command the service creates multiple orders with the "OrderFactory" and stores them to database) and higher order validations (verify not already exists in database given some unique keys, verify some limits etc.).

The different input channels (e-mail, FTP etc.) belong into an seperated integration layer. Each input channel calls the reusable service methods of the "Domain-Service".

Don't create one command per input channel. A command is also part of the Domain-Layer. The input channels are responsible to convert incoming data into the "createOrder"-command and to call the Domain-Service with that command.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.