Operations on entities within a aggregate root

2,343 views
Skip to first unread message

sudarshan

unread,
Aug 15, 2012, 10:25:22 AM8/15/12
to ddd...@googlegroups.com
If i have designed an AR like the below, how do you think i should go about say updating a property in one of the order line objects ?

For Example how can i change the title for one of my order lines (example question)

This is the Order Aggregate Root


public class Order
{
    private readonly int id;
    private readonly Customer customer; // Customer is another Aggregate
    private readonly IList<OrderLine> orderLines;
    private readonly IOrderLineFactory orderLineFactory;

    public Order(int id, Customer customer, IOrderLineFactory orderLineFactory)
    {
        this.id = id;
        this.customer = customer;
        this.orderLines = new List<OrderLine>();
        this.orderLineFactory = orderLineFactory;
    }

    public void AddOrderLine(Item item, int quantity)
    {
        OrderLine orderLine = orderLineFactory.Create(this, item, quantity);
        orderLines.Add(orderLine);
    }
}



One option i could think of is something like the below


Order order = orderRepository.find(orderId);
order.changeTitle(orderLineId, "New title");



However would'nt the above approach cause a bloat in the interface exposed by the AR? It Would need to expose the behavior of all its entities via its own interface. Also assume that orderline had a Set Of Tags which needed to be updated. Would we go along with something like order.changeTagTitle(orderLineId,tagId, "New title"); ?
  Are you sure you want to send this message?

rebo

unread,
Aug 15, 2012, 10:38:57 AM8/15/12
to ddd...@googlegroups.com
Within the command handler can you not just have a generic getOrderItem method on your AR.  You can then make the relevant calls to that object.   

i.e. 
orderItem = order.getOrderItem(orderId) 
orderItem.changeTitle;

As this is just a transient reference to the orderItem within a transaction you should be ok?  And the orderItem can still ask its AR parent if any aggregate invariants need to be enforced.

sudarshan

unread,
Aug 15, 2012, 12:15:11 PM8/15/12
to ddd...@googlegroups.com
I understood that " transient " implies read only, so we should not be making any state changes to the orderitem entity? Please correct me if i am wrong... i guess i am.

Where can i get more info on what transient implies in a ddd context ?

Thanks
Sudarshan

rebo

unread,
Aug 15, 2012, 1:32:15 PM8/15/12
to ddd...@googlegroups.com
Well I am not an expert at all.  However I do not see the problem with calling a method on an entity of an aggregate root, if you reach entity that only by querying the AR and within a single transaction.


On Wednesday, 15 August 2012 17:15:11 UTC+1, sudarshan wrote:
I understood that " transient " implies read only, so we should not be making any state changes to the orderitem entity? Please correct me if i am wrong... i guess i am.

Where can i get more info on what transient implies in a ddd context ?

Thanks
Sudarshan

On Wednesday, 15 August 2012 20:08:57 UTC+5:30, rebo wrote:
Within the command handler can you not just have a generic getOrderItem method on your AR.  You can then make the relevant calls to that object.   

i.e. 
orderItem = order.getOrderItem(orderId) 
orderItem.changeTitle;

As this is just a transient reference to the orderItem within a transaction you should be ok?  And the orderItem can still ask its AR parent if any aggregate invariants need to be enforced.


On Wednesday, 15 August 2012 15:25:22 UTC+1, sudarshan wrote:
If i have designed an AR like the below, how do you think i should go about say updating a property in one of the order line objects ?

For Example how can i change the title for one of my order lines (example question)

This is the Order Aggregate Root
...

@yreynhout

unread,
Aug 15, 2012, 4:32:41 PM8/15/12
to ddd...@googlegroups.com
Why not have a IncreaseProductAmount,DecreaseProductAmount method? Changing titles seems hardly realistic, no? What would be a reason to do so? As such, I do question what bloat you are referring to.

sudarshan

unread,
Aug 18, 2012, 12:30:05 PM8/18/12
to ddd...@googlegroups.com
By bloat I meant that the a ar interface will have to expose behaviour for all ours child entities

Greg Young

unread,
Aug 18, 2012, 1:37:57 PM8/18/12
to ddd...@googlegroups.com
Transient does not mean read only. Transient means temporarily held. http://www.google.lt/search?q=define:+transient&ie=UTF-8&oe=UTF-8&hl=en&client=safari
--
Le doute n'est pas une condition agréable, mais la certitude est absurde.

Benjamin Mapp

unread,
Aug 18, 2012, 2:48:52 PM8/18/12
to ddd...@googlegroups.com
the way I see it is although an aggregate root is responsible for the life cycle of entities within, that doesn't mean that it should be the exclusive interface ( other than returning a specific entity) to all methods called on any item within the aggregate. 

the whole reason for DDD is to provide some structure to OO applications. part of OO is being able to call methods on the relevant object. and if change order item title is more relevant for a orderitem entity that it's aggregate root then I will call it on that object. 

I guess the disadvantage to not calling via the AR is that the command handler has to be aware of  AR entity accessors  and entity methods but for me that's not a major issue as I consider the commas handler part of the domain. For me the interface to the aggregate is the command handler itself.

Greg Young

unread,
Aug 18, 2012, 3:16:18 PM8/18/12
to ddd...@googlegroups.com
Inline.


On Sunday, August 19, 2012, Benjamin Mapp wrote:
the way I see it is although an aggregate root is responsible for the life cycle of entities within, that doesn't mean that it should be the exclusive interface ( other than returning a specific entity) to all methods called on any item within the aggregate. 

+1 

the whole reason for DDD is to provide some structure to OO applications. part of OO is being able to call methods on the relevant object. and if change order item title is more relevant for a orderitem entity that it's aggregate root then I will call it on that object. 

I don't think this is the reason for ddd but instead perhaps ddd is a prism through which to look at things that can make some things more clear, like the light spectrum, this does not mean the spectrum represents the beauty of light or that you see the whole spectrum though the prism.


I guess the disadvantage to not calling via the AR is that the command handler has to be aware of  AR entity accessors  and entity methods but for me that's not a major issue as I consider the commas handler part of the domain. For me the interface to the aggregate is the command handler itself.

 
There is also the problem of coordination between objects if this is chosen. There is no one right way and there definitely a trade off between simplicity of interface and complexity of coordination...

Benjamin Mapp

unread,
Aug 18, 2012, 4:38:26 PM8/18/12
to ddd...@googlegroups.com
Yep I didn't mean to say DDD is only about a technical implementation of AR and Entity. It of course has a whole lot more to it, especially how it can enable stakeholders to use a ubiquitous language to define and develop the application etc.


Message has been deleted

sudarshan

unread,
Aug 19, 2012, 11:17:32 PM8/19/12
to ddd...@googlegroups.com
Thanks, this clears things up a fair bit

The main advantage I see of hiding entities within the ar and invoking their behaviour only via the ar is that the internal implementations of the ar could change without affecting the rest of the system. The side effect being that the AR interface becomes more complicated.

Do people usually consider this while designing their ar's ?

Greg Young

unread,
Aug 20, 2012, 2:58:33 AM8/20/12
to ddd...@googlegroups.com
Yes.

patryk

unread,
Sep 6, 2012, 4:13:31 AM9/6/12
to ddd...@googlegroups.com
I had the same problem and I did extend AR interface. I wonder when exposing entity from AR is better than complicate AR interface?.
I ask myself question: Is every behavior of entity can be invoke outside of AR boundries? and when anser is NO I would exnted AR interface. 
I wounder isnt better to use some kind of middle object which allowed only particular operation on AR entity, for example relationship object. 
What do you think?

Greg Young

unread,
Sep 6, 2012, 4:23:39 AM9/6/12
to ddd...@googlegroups.com
When can a behaviour in an entity inside an aggregate be outside of
the aggregate boundaries? I am a bit confused in reading this.

patryk

unread,
Sep 6, 2012, 7:00:00 AM9/6/12
to ddd...@googlegroups.com
Ok It seems that my english may not express what I meant to say.

When there is AR -> Order and Entity OrderItem.
and when we want to change order item title of id=123, we can do it like this: order.getOrderItem(123).setTitle("test"); // 1st option
or another way: order.setTitle(123,"test"); //2nd option

I would say first option is exposing behavior of Entity outside scope of AR.
When for example OrderItem has another behavior(e.g. changing state of OrderItem) which we didnt want to expose to client of our AR, first option alowed on it.

I hope now is better.
Sorry for my english.

Sudarshan Sreenivasan

unread,
Sep 6, 2012, 12:55:25 PM9/6/12
to ddd...@googlegroups.com
Can you please give me an example for the below

"I wounder isnt better to use some kind of middle object which allowed only particular operation on AR entity, for example relationship object. "

And ya i agree with 

"I ask myself question: Is every behavior of entity can be invoke outside of AR boundries? and when anser is NO I would exnted AR interface. "

Thanks
Sudarshan
Reply all
Reply to author
Forward
0 new messages