[TYPO3-50-general] FLOW3 and DDD
Nino Martincevic
don at zampano.com
Mon Jan 19 16:02:15 CET 2009
Ok Robert, here are some further thoughts on this...
Robert Lemke schrieb:
> There can be Domain Objects without connection to the repository which
> are then not persisted. I call them "Transient Entities".
That was somehow misunderstood. Entities have no "connection" to a
repository but are maintained, i.e. generally queried and in
circumstances saved, by it. They should not know nothing about the
existence of a repository, they just "are" (although there are dicussion
about entities calling repositories...).
And in the domain model the question is: Who does create them?
(see below example of form)
> Do you've got a copy of Jimmy Nilsson's "Applying Domain-Driven Design
> and Patterns"? Check out p. 281, the table which gives a summary of
> the Semantics for the Life Cycle of Domain Model instances.
I have this book and have read it.
And I know of transient entities but in the following example you forgot
to mention some details.
> $customer = new Customer; // $customer is a Transient Entity
> $customerRepository->add($customer); // $customer added to the
> repository
> $persistenceManager->persistAll(); // $customer becomes a Persisted
> Entity
>
> $address = new Address; // $address is transient
> $customer->setAddress($address); // $address now has connection to a
> repository through the
> Customer Aggregate
>
> $persistenceManager->persistAll(); // $address will be persisted
(Sorry be being a little too extensive or sounding educational here, I
noticed that you are firm with the material, sure you are. But perhaps
people are reading this thread anyway, not that firm with DDD concepts
but willing to learn some terms of it and get some more information out
of it)
Creating an entity Customer without identity is simply not possible.
An entity without identity is a paradoxon. It may be a prototype or
something else but not "the" domain object.
You forgot to mention that in Nilsson example there is only "create
new", but create new Customer means create one with clear identity.
Without it: how can you add it to the repository when you don't know its
identity, how will you get it back? Therefore you first have to check if
one with that identity exists (via a repository).
And the address in that example is perhaps a value object.
If it were a entity, you also would first check its existence through an
repository. If it does not exist you would create a new valid one.
Then you can even persist a few steps later.
So, the example should read:
$customer = new Customer(12345); // where 12345 is the identity,
something like UUID
($addressRepository->find(bla, blub);)
none found
$address = new Address(bla, blub); // again "bla/blub" is identity
$customer->setAdress($adress);
$customerRepository->add($customer);
$persistenceManager->persistAll();
[Btw: that's a point where two sentiments exist and most of the DDD-guys
I know tend to say that there cannot be an "invalid" entity. It has to
be created with full identity.]
The goal of repository is to avoid entities with same identity at any
price - there are simply not two identical entities in the system, they
never have a copy.
Without a repository you could create two identical objects that would
exist separately and you'll have a bunch of trouble, not at least at
persistion time.
> Yes, for example you'll want to create a Customer object without
> persisting
> it until it's valid. Imagine a multi step form which carries a
> Customer in
> a session until the form is finally submitted.
That's perhaps the problem!?
This example would never be possible in an isolated layer and especially
not in the domain model, never. This is domain leaking into application,
that should be avoided by any circumstances.
If by "until it's valid" you don't only mean some of its attributes,
that's fine. But if it is the identity that would mean you already have
it persisted, how would you else know (if it is in memory or db) it?
E.g. username is the identity (stupid example). For creating new
customers you have to check if no other with the same username exists
and to reserve it you'd had to persist it (or check again if you want to
do it later by risking that it throws an exception).
A form is not part of the domain, it's application. And in the
application you can create 100 identical customers but when it comes to
put them into the domain (for persistance or not) you only have one
choice and one way. And this gatekeeper will only store the first one,
the other forms will get an exception.
You can do it this way, of course (two people could try to register with
same identity) but you would only have one, and only one, responsible
place to check the identity and then add it to the repository.
Mostly this is done by some kind of gateway, facade etc., depending on
you domain.
As I re-read this I think we both know what the problem is.
And perhaps it isn't really one:
The second method ($customerRepository->add($customer)) should be
impossible because Customer is not a valid entity.
But that's primarly not the problem of Flow3 but of the developer.
This would throw at least an exception.
IMHO Flow3 should have these constraint:
Never save invalid Entities to the repository, i.e. they must have at
least identity set.
Is that already provided? If not, that would not be much work, would it?
But that's your problem :-)
Nino
More information about the TYPO3-project-5_0-general
mailing list