How to design the calculated model fields in DDD?

I become a big fan of DDD . So, I am thinking about applying it correctly to my current system, which I am developing.

Suppose we have two aggregate roots: Order and User . Order has two properties, referring to User : owner and contractor . The owner created the Order , the contractor completed it.

Owners can appreciate the quality with which Order performed by the contractor. So, we have a Feedback object associated with Order containing a rating.

Now the User object contains the average rating of each user through the completed orders. And this part bothers me a little.

User rating is not just a static property, but actually the average value of all ratings in Feedbacks . And it changes (should be recounted) at the time of joining Order Feedback .

Currently, I have some services encapsulating the domain logic: OrderService and UserService (I know that this actually does not correspond to DDD, but I will reorganize it later). When the OrderService receives a command to attach feedback to the order, it issues an OrderFeedbackAttachedEvent , which the UserService listens to recalculate the user rating.

What does not satisfy me is that now the information about the root unit of the order has now been leaked to UserService. And I see no way to avoid this. I'm starting to think that for such cases there must be some kind of model.

Rating

Rating seems to be an ideal property of the user. But the fact that this is not a static, constant value, but rather something that is calculated based on data from other objects, causes me doubts.

Rating is also not an entity. This is not an object of value. What is interesting in DDD? And how do I model estimates (or any other calculated values) in my system without sacrificing performance and ease of use)?

+6
source share
2 answers

To be fair, an event emitted from another AR or another BC is not a leak. There is no problem for User AR to handle the OrderFeedbackGiven event, in my opinion. If Feedback VO is part of the event, then the client should not depend on anything else to handle the event. Having a limited feedback context may be cleaner, but I would not have implemented a fully exploded sun for this, or you would have a micro-BC blast ...

I am concerned about the fact that after the feedback has been received, all feedback should be aggregated to calculate the user rating. This creates a dependency on the user for the order (the repository of the calling order to retrieve the rating from the user's service when the event was caught). This is normal, what do you think?

I think it doesn’t matter if you do it. The service level of the application depends on the level of the domain as a whole. However, there is no need to do this at all, as you can calculate a moving cumulative average .

eg. Where this.ordersFeedbackAvg is a MovingAvg value object that tracks the average value and the number of data points from which it was calculated.

when(OrderFeedbackGiven feedback) { this.ordersFeedbackAvg = this.ordersFeedbackAvg.cumulate(feedback.mark); }

+2
source

It seems you can have at least two separate limited contexts: one for streamlining and the other for feedback.

Aknowleging Bounded Contexts allows you to see different abstractions of the same physical thing: in the context of “orders” the order seems to be a legitimate aggregate, but it can be a Value object in the “feedback” BC, where it will hold the order identifier (the value of which comes from the order BC through the event).

Here is a suggestion:

enter image description here enter image description here

Using this model, you calculate the average rating of the contractor when processing the "FeedbackEmitted" event from the feedback aggregate in the event handler of the contractor aggregate

Hope this helps :)

+7
source

All Articles