groups of objects, not just discrete objects. Yet cautious locking schemes cause
multiple users to interfere pointlessly with each other and make a system unusable.
Put another way, how do we know where an object made up of other objects begins and ends? In
any system with persistent storage of data, there must be a scope for
a transaction that changes
data, and a way of maintaining the consistency of the data (that is, maintaining its invariants).
Databases allow various locking schemes, and tests can be programmed. But these ad hoc
solutions divert attention away from the model, and soon you are back to hacking and hoping.
In fact, finding a balanced solution to these kinds of problems calls for deeper understanding of the
domain, this time extending to factors such as the frequency of change between the instances of
certain classes. We need to find a model that leaves high-contention points looser and strict
invariants tighter.
Although this problem surfaces as technical difficulties in database transactions,
it is rooted in the
model—in its lack of defined boundaries. A solution driven from the model will make the model
easier to understand and make the design easier to communicate. As the model is revised, it will
guide our changes to the implementation.
Schemes have been developed for defining ownership relationships in the model. The following
simple but rigorous system, distilled from those concepts, includes a set of rules for implementing
transactions that modify the objects and their owners.
[1]
[1]
David Siegel devised and used this system on projects in the 1990s but has not published it.
First we need an abstraction for encapsulating references within the model. An
AGGREGATE
is a
cluster of associated objects that we treat as a unit for the purpose of data changes. Each
AGGREGATE
has a root and a boundary. The boundary
defines what is inside the
AGGREGATE
. The
root is a single, specific
ENTITY
contained in the
AGGREGATE
. The root is the only member of the
AGGREGATE
that outside objects are allowed to hold references to, although objects within the
boundary may hold references to each other.
ENTITIES
other than the root have local identity, but
that identity needs to be distinguishable only within the
AGGREGATE
, because
no outside object can
ever see it out of the context of the root
ENTITY
.
A model of a car might be used in software for an auto repair shop. The car is an
ENTITY
with
global identity: we want to distinguish that car from all other cars in the world, even very similar
ones. We can use the vehicle identification number for this, a unique identifier assigned to each
new car. We might want to track the rotation history of the tires through the four wheel positions.
We might want to know the mileage and tread wear of each tire. To know which tire is which, the
tires
must be identified
ENTITIES
also. But it is very unlikely that we care about the identity of
those tires outside of the context of that particular car. If we replace the tires and send the old
ones to a recycling plant, either our software will no longer track them at all, or they will become
anonymous members of a heap of tires. No one will care about their rotation histories. More to the
point, even while they are attached to the car, no one will try to
query the system to find a
particular tire and then see which car it is on. They will query the database to find a car and then
ask it for a transient reference to the tires. Therefore, the car is the root
ENTITY
of the
AGGREGATE
whose boundary encloses the tires also. On the other hand, engine blocks have serial numbers
engraved on them and are sometimes tracked independently of the car. In some applications, the
engine might be the root of its own
AGGREGATE
.
Do'stlaringiz bilan baham: