Hi Rickard,
Thank you very much for your thorough answer and reflections on the
subject!!!
It has helped me a lot, and I will look carefully into the Streamflow
code as you suggest. That will take me a while ;) and I will probably
get back with some more questions once I start to understand the
implementations. I think I will also then better be able to reflect on
your examples and explanations. A lot of good stuff to digest!
Thank you for confirming my suspicions about the POJO -> Qi4j paradigm
shift. I'm definitely on the right bandwagon ;)
Keep up the excellent work - very much appreciated!
Cheers,
Marc
On 08/03/2010, at 08.17, Rickard Öberg wrote:
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
_______________________________________________
qi4j-dev mailing list
[email protected]
http://lists.ops4j.org/mailman/listinfo/qi4j-dev