Domain-Driven Design
> >
ImplementationOfAggregates

Tue Oct 28, 2003 2:18 pm

I do have one question about how to implement aggregates. I was
wondering if you could clarify, with some examples, exactly how to
enforce the idea of an aggregate root.

Thanks,
GriffinCaprio



Good question.
I have seen three basic approaches to aggregates.

1. Noone thinks about aggregates, but to make the system work, they
implicitely and intuitively do apply some boundaries of transaction
scope in the model.

2. Aggregates are explicitely defined but not enforced by the system
formally. The developers follow the rules as they write their code.
(For example, they only create repositories for the roots, and never
add persistent references from outside to an internal entity.)

3. A framework allows the declaration of aggregates and assists the
management of aggregates (for example, by deleting a whole aggregate
together, or automatically applying the appropriate locks to an
entire aggregate). Such a framework may enforce some, but not
necessarily all, of the rules.

A team can also progress from 2 to 3. If aggregates are known and
the rules have been followed, then introducing an automation of some
of the management of an aggregate is a feasible refactoring.

This is not the concrete example you asked for. I'll see if I can
come up with something more satisfying there. I'm usually in the
position of using and advising on the features of that piece of
infrastructure, and haven't built one. (Anyone else have something
to share on that?)

Infrastructure support is great, but even without it, aggregates can
bring order to the transactional model, and can even guide design
decisions such as which associations to implement directly between
objects.

EricEvans


Thanks for the insight, Eric.

Since I have sent the email, I have begun my own
little experiment in the actual implementation of an
aggregate root. I think have found one implementation
that I believe will assist me in enforcing the
aggregate root concept.

In my small example, I am taking a XML file and
creating a small object model for it. This is so we
can create and manipulate these XML files, without
introducing XML all over the place.

The result is a small object model, containing about 7
objects. In this case, DocBundle is the aggregate
root, and the other objects make up the rest of the
aggregate.

I have implemented the DocBundle as a class, and the
rest of the objects as structs. I did this because
the environment I am in, .NET, treats structs as value
types. So, whenever a reference to a struct is passed
to another object, it is passed by value instead of by
reference. The runtime automatically enforces the
concept of not maintaining direct references to any
object within the aggregate.

Is this a viable, if not partial, solution?

Has anyone else implemented something like this
before?

Thanks Eric,

GriffinCaprio


Griffin, one thing to consider is creating Value Objects rather than value
structs. I know you are only "exploring", but be aware of boxing issues which simply put, will hit performance. Your other solution is to create a read-only Object.

Best regards

NickRobinson


> Griffin, one thing to consider is creating Value
> Objects rather than value structs. I know you
> are only "exploring", but be aware of boxing issues
> which simply put, will hit performance.

Could you quantify what you mean by "boxing issues"?
I am always interested in hearing about possible
performance hits.

>Your other solution is to create a read-only Object.

That was my original implementation. Unfortunately,
we are using .NET XML Serialization, which requires
both get/set for properties to be able to
serialize/de-serialize objects.

Thanks,

GriffinCaprio


> Could you quantify what you mean by "boxing issues"?
> I am always interested in hearing about possible
> performance hits.
>

When you pass structs around, they are passed by value. To improve
performance you will need to "box/unbox", but this involves copying data
around too. For ints and chars and the like, this isnt too great a problem,
but if your structs start to get large, then potentially you could be hit.

> >Your other solution is to create a read-only Object.
>
> That was my original implementation. Unfortunately,
> we are using .NET XML Serialization, which requires
> both get/set for properties to be able to
> serialize/de-serialize objects.

Why not have some form of flag that allows something to be initialised only
once. So if you have a set method, it can only be set once by the
deserializer. Further attempts cause an exception. I have seen this
implemented in many places.

NickRobinson


> ...isnt too great a problem,
> but if your structs start to get large, then
> potentially you could be hit.

Good point. But, I think one of the reasons I
implemented them as structs was because they are
passed by value. I was looking for a way to enforce
the concept of Aggregate Root passing references to
objects inside the aggregate as value objects instead
of actual references.

Structs allow me to do this explicitly, as opposed to
crafting another solution around classes.

But I do agree that I have to watch how big they get.

> Why not have some form of flag that allows something
> to be initialised only
> once. So if you have a set method, it can only be
> set once by the
> deserializer. Further attempts cause an exception.
> I have seen this
> implemented in many places.

Another good point.

Thanks for the input, Nick.

GriffinCaprio


> passed by value. I was looking for a way to enforce
> the concept of Aggregate Root passing references to
> objects inside the aggregate as value objects instead
> of actual references.
>
When an object is passed out of the aggregate, no reference to it can
be held. It isn't really a value object, though (unless it already
was, inside the aggregate). Which isn't to say that this mechanism
won't be useful to you. But the modeling distinction of entities and
values is not determined by which object is looking at them.

EricEvans


> When an object is passed out of the aggregate, no
> reference to it can
> be held. It isn't really a value object, though
> (unless it already
> was, inside the aggregate).

Right. That's what I trying to accomplish. I was
trying to create the objects inside the aggregate as
value objects, so I wouldn't have to go through a
separate step when an object wanted one of them.

> Which isn't to say that
> this mechanism
> won't be useful to you. But the modeling distinction
> of entities and
> values is not determined by which object is looking
> at them.

Right. I wasn't confused on how these two concepts
are modeled. That's pretty clear. I was looking for
more of an implementation example.

GriffinCaprio


> Right. That's what I trying to accomplish. I was
> trying to create the objects inside the aggregate as
> value objects, so I wouldn't have to go through a
> separate step when an object wanted one of them.

Eric, in the above do I take it you mean, "During the lifetime of an
aggregate part, it may transiently be referenced by collaborators, but only
for the duration of a method call"?

NickRobinson






ImplementationOfAggregates is mentioned on: ThreadView


VeryQuickWiki Version 2.6.3 - HTML Export