Hi Marc,
On 2010-03-07 23.19, Marc Grue wrote:
Qi4j beautifully makes it possible to separate state and behaviour.
And even generic behavior like an Assignable; "assign GenericA to
GenericB" (as shown in Rickards excellent presentation
http://oredev.org/prod/oredev/site.nsf/docsbycodename/session?opendocument&sid=88EF79931A074A1AC125759A003AB0ED&track=24116556E47101EAC12575A50049A141&day=5).
Doesn't this rock the DDD boat some (in a great way!) in the sense
that the "classical" BC/Module/AR/Entity boundaries would have the
behavior dimension extracted into "Cross cutting (domain?)
behavior"?!
I'm happy that you have noticed this. As you note, the DDD mailing list
are quite a lot "stuck" in the POJO world, where everything is
difficult. Since we don't have that limitation we focus on more
interesting things, and creating cross-cutting domains in one such thing.
I have found that what is traditionally thought of as "Bounded Context"
can usually coexist in entities quite happily, since the code is not
mangled together. As long as the entity identities have the same
structure, it works quite well.
As for aggregates, I'm more and more thinking that such rules can
actually quite well be handled by DCI. Since an interaction has access
to a number of entities at once, through a context map, it becomes
trivial to handle many aggregate rules without having to create a new
method for it.
Let's say that you, for example, have an Order with Lineitems. In a
traditional aggregate implementation, when the Lineitem quantity changes
that would have to be a method on Order, since the total price has to be
recalculated: order.changeQuantity(lineItem,newQuantity). But this leads
to a lot of duplication of methods.
With DCI, where each method in a context represents a usecase
interaction, this can be captured differently:
public class LineitemContext
extends Context
{
public void changeQuantity(int newQuantity)
{
context.role(Lineitem.class).changeQuantity(newQuantity);
context.role(Order.class).calculateTotal();
}
}
---
This quite simply captures the "algorithm" that happens when a lineitem
quantity is updated, and also handles the aggregate rule from Order to
Lineitem. I think this is better than to put the
changeQuantity(LineItem,int) method into the Order interface.
When it comes to entity structure, that's another interesting part. Due
to how you can structure mixin dependencies, and use private mixins to
specify what is your public API from an entity, I have found that
entities typically have 5 internal layers: data, structural roles,
interaction roles, query roles, and glue roles. It is layered in the
same sense as in layered archiectures, i.e. query roles may refer to
interaction roles, but not the other way round.
So there's a whole lot of interesting things that become possible, and
the code (especially when DCI is used for the application layer) is just
super-pretty. :-)
I'm trying to dive into the new paradigm and to practically organize
my folder/package structure accordingly. I have read heated
discussions about bounded contexts etc in the DDD Yahoo group, and I
wonder if/how you qi4j folks are physically/conceptually organizing
the behavioral part (used across domain contexts) in larger
applications (with several BC's)? Or, simply put: where does generic
behavior belong?
Please look at the StreamFlow code for one extensive example of this. In
short, I have the following package structure:
/domain
/entity
/<domain-package> : contains EntityComposite interfaces, query
mixins, and glue mixins
/interaction
/<domain-package> : contains mixins for a specific interaction
context (like /gtd in my case), including data mixins
/structure
/<domain-package> : contains structural mixins for a specific
context (like users, organization, projects and tasks in my case),
including data mixins
If you do this, then it becomes really easy to verify if you are
following the dependency rules, by using Structure101. Entity should
depend on interaction and structure. Preferably interaction and
structure should not depend on each other, so that they can be used and
composed independently.
What differences are there in organizing a project namespace in DCI
and in DDD (if you can put them up against each other). Any directory
structure examples would be much appreciated.
The way I use DCI is for creating a REST API. The REST API then matches
the UI layout. My client has a "workspace" so I have a /workspace REST
URI, which then maps to a .workspace package. Very straightforward. The
goal is to have the users mental model map directly to the code.
Note that this is VERY different from many other REST approach where the
domain model is exposed directly as URL's (which I think is basically
nuts). When you do the above, it really enforces that API means
Application Programmer Interface, whereas the typical "expose your
domain using URL's" is a DPI: Domain Programmer Interface. Which, to me,
is the wrong level to expose.
I was originally planning to post this in the Yahoo DDD group, but I
find that they are a little slow to pick up on the powers of qi4j :)
so I imagined the subject would fit better here...
Probably a good call...
/Rickard
_______________________________________________
qi4j-dev mailing list
[email protected]
http://lists.ops4j.org/mailman/listinfo/qi4j-dev