Should I separate DTO between Command and Query

Suppose, I want to design an E-commerce system. I want to create a ProductDTO here which contains general information of a product.

data class ProductDTO(
        val productId: String,
        @get:PostiveOrZero
        val amount: Long
)

data class CreateOrderCommand(
        @TargetAggregateIdentifier
        val orderId: String,
        val product: ProductDTO
)

// my aggregate
class OrderAggregate {
        @AggregateIdentifier
        lateinit var orderId: String
        lateinit var product: ProductDTO
        
}

// my query model
data class Order(
        val orderId: String,
        val product: ProductDTO
)

my question is, should I separate ProductDTO between Command and Query. Should command model and query model has its own ProductDTO. For the command model, it may need validation constraint to validate the input but query model may not need it. How should I design it in this case?

Hi Lincoln,

It is recommended to keep the structure of your messages as flat as possible. It is also a good practice to keep the message as small as possible and not to have unused attributes in them. Only the attributes needed to make a decision should be added to the Aggregate state.
The reason behind this is that if you need to change the structure of your event it is easier when you have a flat structure.
Changes in the event structure can be done but you still need to be able to handle old versions of that event as well.
When applying CQRS the Command Message structure and the Query Message structure should be separate. The Command Message serves a different purpose than the Query message. Attributes used on the command side may not be of interest to the Query side and vice versa.

I hope this helps,

Yvonne

1 Like