-
Notifications
You must be signed in to change notification settings - Fork 10
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Primitive types only in command #14
Comments
What about |
My general rule is to have only immediately serializable data in a DTO (that is, primitive types). I know some people who add "getters" to a DTO which produce actual (domain) objects based on those primitive values. I don't do it like that, but always explicitly convert to objects inside the command handler. |
Agree! But do you even handle dates as strings instead of DateTimeImmutable? |
Having them always serializable is good for offloading to external queue. If serializing with an serializer like symfony/serializer or jms' it should be fine to even use object types as properties since they would be denormalized as expected. DateTime would be no problem then. |
Even though I'm often not actually serializing DTO's, I like them to be very flat, since that's in the spirit of a DTO. Any type of object would not be able to cross application boundaries (within the application it would probably cause incorrect coupling and to the world outside it would be completely impossible ;)). |
Thanks for your opinion! Currently I'm using For now most of my commands are populated by Symfony Forms (e.g. via Converting the date strings to |
@webdevilopers DateTime::ATOM can be parsed by php and js natively. |
I've been using Commands w/ value objects form a long time. But now that we are working with DTOs for read models from projections in a DDD CQRS environment I'm thinking about switching back again. Recently there is discussion going on wether Commands (and Handlers) belong to the Domain Layer too: Currently having Commands using Value Objects would even support this Credo. And that makes it easier for our UI team to identify tasks:
In the end the Application Layer somehow has to be aware of the Domain Layer. At least when transforming the primitive types to Value Objects and then pass them to the Domain Model. Though I think "Actor Models" also directly accept the Commands inside the Model and then transform them there. The Application Layer and orchestration is "skipped". Any thoughts about that? Similar discussion: |
Another advantage of moving the validation of creating object to the Handler would be the improvement of catching errors in a single place e.g.: |
I'm using commands and view models which have primitive types and won't throw any exceptions. I think this is a useful aspect of them. For commands it's very useful because now (if you use Symfony) the Form component can populate it, and validate it afterwards. Then if you pass the command to the application service, it will use the raw data from the command to construct value objects and entities. So any violations of domain invariants will appear in the application service only. |
That is exactly the approach I would like to use @matthiasnoback in the future. Thanks for the feedback! |
Cool, you're welcome. |
We are currently decoupling our UI from our (mostly Symfony w/ Forms) applications. Now we no longer separate between a "CommandDTO" and the actual "Domain Command". The latter is sometimes directly passed to an aggregate root. This solution by @vkhorikov works fine for us:
|
When I started decoupling from Symfony Form and the
EntityType
I switched to primitive types only that would then be used on thedata_class
which is the Command / DTO.In conlusion my command only uses integers (for IDs) and strings (also UUID) or arrays of these types.
I'm sometimes asked if objects e.g. value objects should be used. As I mentioned I don't use objects in a DTO at all. As @jeremyb states in his slides:
Most examples I see follow these "guidelines":
https://github.com/SimpleBus/MessageBus/blob/master/doc/command_bus.md#using-the-command-bus-an-example @matthiasnoback
Sometimes a DTO property transfers a string coming from a constant:
People ask how to ensure (validate) that the string
$contractState
of the DTO is a correct string from the constants.If you are using Symfony Form you already set the choices and a user cannot select a different choice.
When the input comes directly from the Request I guess you could add a custom Constraint to the Command that could check if the strings exists:
Since I'm using Symfony Form I prefer validating the input inside the Value Object. The handler will try to create an object from String:
The
fromString
method then will throw an Exception if the string was invalid.What are your thoughts on this?
Related issues:
The text was updated successfully, but these errors were encountered: