Re: Working with domain events. Referencing leaf / sub-entity of aggregate

"Rikard Pavelic [email protected] [domaindrivendesign]" <[email protected]> Fri, 13 May 2016 09:12:42 +0200
Newsgroups gmane.comp.programming.domain-driven-design
Message-ID <[email protected]>
--nXe7K36MCPmeT49MPMVm0vEFbFaMjCKLj
Content-Type: multipart/mixed; boundary="WJmGccnImb2NJBquiitTj2s7Jbd2b8H90"
From: Rikard Pavelic <[email protected]>
To: [email protected]
Message-ID: <[email protected]>
Subject: Re: [domaindrivendesign] Working with domain events. Referencing leaf
 / sub-entity of aggregate
References: <[email protected]>
In-Reply-To: <[email protected]>

--WJmGccnImb2NJBquiitTj2s7Jbd2b8H90
Content-Type: text/plain; charset=utf-8
Content-Transfer-Encoding: quoted-printable

On 12.5.2016. 15:56, [email protected] [domaindrivendesign] wrote:
>=20=20
>=20
> Hello everyone,
>=20
>=20
> I know my topic is not new and was discussed many times before. I read a =
lot but not sure whether I am going the best path. So I will place this top=
ic here again with another concrete example.
>=20
>=20
> In the sales department we work with orders. Obviously this is, what a cu=
stomer orders.=20
>=20
>=20
> A) Understanding an order with its items:
>=20
> Our stakeholder often fall back and say: We need an order and order items=
. But this is only because of giving the =E2=80=9Cthing=E2=80=9D an order n=
umber to talk about. Like brackets around all order items. So our
> understanding in the dev-Team is, the order items are aggregates and we w=
ill do something to group then by an order number.

This is not how people usually think of items for such use cases.
There are several rules of thumb to follow when thinking about aggregate bo=
undary:
 1) do I need to save it as a whole
 2) can I put it into an invalid state if I save it in parts

So obviously Order must have at least one item, therefore you should not al=
low manipulation of a single item since that can put order into an invalid =
state.

> We think of order items as aggregates, because a customer will never requ=
est an order with three items in it. Furthermore he will order three articl=
es with a specific number. It is only for
> communication reasons that a number for these three items makes it easier=
. What do you think about that?

I think that leads to description of an entity.

> B) Conflict with sub-entity within order-item-aggregate
>=20
> Think of order item. This is an article in a specific quantity a customer=
 would like to have. Order item is an aggregate. Assigned to the order item=
 there are multiple =E2=80=9Ccall off=E2=80=9D. A call off describes
> when the customer requests a certain quantity and whether it must be deli=
vered (DDP) or whether it will be fetched (=E2=80=9Cex works=E2=80=9D). Act=
ually call off is an aggregate on its own. Here is our conflict:

Again, not sure why you think Call off is an aggregate. To me it sounds lik=
e an event.
Again, some rules:

 1) can it mutate, or is it one of description of an event
 2) does it have meaning on its own, or it's part of something larger

> 1.Sum of quantities for all call off must be less than or equal to order =
item quantity. So making call off an sub entity of order item seems to be t=
he best choice, than making it an own aggregate.

This looks like call offs can be either an event referencing order aggregat=
e or an entity within an aggregate.
If call offs are actually referencing entities (items) that too is ok.

> 2.On the other side call off will be referenced in the dispatch departmen=
t. This is, because every call off leads at least to an =E2=80=9Cgoods issu=
e request=E2=80=9D in the dispatch department. But refering to book
> from Eric Evans it is absolutely not allowed to reference a sub-entity - =
except for a single operation. It is only allowed to reference aggregates.

He also said objects within aggregate can hold references to each other.
Therefore if both items and call offs are entities withing Order aggregate =
you are allowed to reference each-other.

I think avoiding referencing entities within aggregate is a good rule to fo=
llow, but not a requirement.
If you do reference entity within an aggregate that will probably make you =
life harder as a developer, but it can also make some things easier.

> We are afraid of having 90% our objects being an aggregate and placing do=
main logic not within the aggregates but within services around two or more=
 aggregates.

Yes, you probably want to avoid most of your objects being an aggregate.
There are systems where bulky objects with domain logic are preferred and w=
here services for those bulky objects are preferred.
I think you can practice very good domain modeling/DDD and still use servic=
es. I actually prefer that design most of the time.

> From what I have already read and got as responses from experts like Paul=
 Rayner I should start to think about "call off" as an "domain event". Okay=
, it's no problem to imagine that order item will
> have an "customer requested quantity"-Event or something like this.
>=20
>=20
> Problem is when leaving bounded context of let's say "customer care". In =
dispatch department it is no problem to imagine that this domain event can =
lead to an action and new aggregate there. At this
> point I do not need a reference to the "call off"/domain event. But when =
dispatch has problems or work is done, sales department needs to be informe=
d that "call off" needs attention or is done and
> possibly order item can be given to "invocement"-bounded-context?

I dislike the idea of context as point-of-view, since that usually leads to=
 reuse of same objects with different rules on them.
That leads to mess since rules are not actually enforced, unless they are d=
efined as a single set of rules, eg. within same context.

If you use context as application boundary, this means that you use loose r=
eferencing, eg. through identity value instead of something along the lines=
 of foreign key.
Therefore communication between context is best done be sending events arou=
nd and reacting on them.
So you can have CallOffNeedsAttention event, or something along those lines=
.

> Is it okay, when aggregate in dispatch holds composed key on order item a=
nd sub-entity / aggregate leaf? What other possibilitites do you see? Must =
"call off" be an aggregate and a domain-service must
> check sum of call off quantities agains order item? Is this something for=
 the "Process Manager" presented to me the first time at the DDD Europe in =
Belgium by Mathias Verraes?
>=20
>=20
> I will be very happy getting a lot of ideas and responses. Thank you very=
 much for reading my story :-).

I think reasoning about domain without short description is really hard.
You should try and put your domain in some model, this will make it easier =
for others to grasp what you are talking about.
And it would probably flush out some of you own inconsistencies.

Regarding the original problem and referencing entity within an aggregate.
If I put it in DSL model I understand that would look like this:

    aggregate Order {
      OrderItem Items;
    }
    entity OrderItem;

    event CallOff {
      OrderItem *Item;
    }

DSL Platform don't allow this since *Item property can't actually be loaded=
 (technically it could, but it's only allowed to be loaded as a part of Agg=
regate).
Instead what you can do in such modeling is define an read-only structure f=
or order items.
Something like:

    snowflake<OrderItem> CallOffCandidate;

    event CallOff {
      CallOffCandidate *Item;
    }

This is allowed since snowflake allows referencing; and snowflake can be de=
fined for every identifiable object (such as entity).
Thus, my point is that since entity has an identity, it could be referenced=
, but this should be discouraged.
What I think is perfectly fine is projecting that entity into some other re=
ad-only structure and use that instead.
This way if you change OrderItem from entity to an aggregate, you will not =
actually change the CallOff model since to it it's the same.
And this way you can't invalidate the Order aggregate, since snowflake is r=
ead-only.

Regards,
Rikard

--=20
Rikard Pavelic
https://dsl-platform.com/
http://templater.info/


--WJmGccnImb2NJBquiitTj2s7Jbd2b8H90--

--nXe7K36MCPmeT49MPMVm0vEFbFaMjCKLj
Content-Type: application/pgp-signature; name="signature.asc"
Content-Description: OpenPGP digital signature
Content-Disposition: attachment; filename="signature.asc"

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v2

iQEcBAEBCAAGBQJXNX5uAAoJELBms/fUcNQTe1cH/3H4N3Ic8+MZO6yQNHS/O2ah
dMJDPJFdfbBWzm7WgybeqRPZ3pGpY/p/go4xoGQ4fnmGhUeH5/mqev/By4OjQPsV
TnEcXcZLCqbFU9Xlhs2XF1DqvwqxuGxLPEPNEQNkf6899hFQ0PIjpqN1EpV3Qfbt
fyI+0v2GgN7cBXJ8fXDMe4MPcsSAcLyeE8vb9SZgWQDTGMNgyaClonoHgdTQYifX
JEyOGjcxalqLWDN5GHXgtxTe+8klfYif9RT5vRztKqKUib4tqFiSvL4v/zUffZKK
sMdjUEjnWfIWbQICQfbqenGVfX/vN/M3GMX1e2j4p0FVhO+TUEU47TNxxeiSl3Y=
=TceQ
-----END PGP SIGNATURE-----

--nXe7K36MCPmeT49MPMVm0vEFbFaMjCKLj--