You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@isis.apache.org by GESCONSULTOR - Óscar Bou <o....@gesconsultor.com> on 2013/05/13 15:44:29 UTC

Re: A heavier or smaller root aggregate


For contributing to this debate just referencing external sources:

There seems to be a "little" debate about "referencing ids vs lazy loading (with or without "direct" reference)" and more on the DDD Yahoo User group...

http://tech.groups.yahoo.com/group/domaindrivendesign/message/24048

The main point is that sometimes this "Domain Id." does not correspond to any Domain concept, so it shouldn't be introduced on the Domain model.


Also, there's an interesting blog post about this 2 ways of implementing DDD:

http://rogeralsing.com/2009/11/08/two-flavors-of-ddd/


But I simply would notice that both approaches can be mixed (specially on different Bounded Contexts). If one BC is implemented over a framework that supports by default "lazy loading" a direct reference will be exactly the same in size as a "referencing id" and none of the problems noticed on Vaughn's "Implementing DDD" would occurred.


During my evaluation, I think the following assumptions can be made about the Apache Isis default programming model (please, correct me if any of them is incorrect or if there are any additional points to consider):
- By default all referenced objects are lazy-loaded.
- Wicket viewer only implicitly loads a referenced object for showing it's name. For the referenced object only it's name will be loaded, so this will break the "loading chain" (no other referenced objects, are they will also be lazy-loaded, unless explicitely told; nor the name of this dependent objects).
- Updating collections will not cause JDO/DataNucleus to update the version on the Aggregate Root / PersistenceCapable Entity.
- Collections are "disabled" (lazy-loaded) by default, unless explicitely annotated, by the Apache Isis "contract" with the programmers and implemented viewers. If they must be eagerly loaded, the programmer must explicit it by annotating the Collection with @Resolve(Type.EAGERLY), such as in:

public class Order {
    @Resolve(Type.EAGERLY)
    public List<LineItem> getLines() { ... }
    ...
}

- Same happens for direct Entity references:

public class Order {
    @Resolve(Type.EAGERLY)
    private Customer customer;
    ...
}



Cheers,

Oscar







El 19/04/2013, a las 15:37, Dan Haywood <da...@haywood-associates.co.uk> escribió:

> So, one last mail in this thread.  I've not cc'ed Vaughn this time, so we
> won't get a reply (and I don't think he would want to anyway), but anyway...
> 
> The point that Vaughn makes about "allowing your consistency boundaries to
> change per use case" is interesting.  And I remember Udi Dahan make this
> point a long time ago too [1].  According to this viewpoint, then each
> aggregate changes over time, rather than being statically defined across
> all time.   That is, the use case starts with an interaction  with one and
> only one domain object, and the consistency boundary is simply the domain
> objects that are enlisted within the transaction as a result of invoking
> that action.  Isolation level 3 (serializable) takes care of any
> consistency issues across entites.
> 
> So the easy way out of this argument is to say that Isis supports
> aggregates, according to the above definition.  After all, in Isis any
> given interaction results in the invocation of an action on a single domain
> object.  However, I'm pretty sure that this dynamic morphing of aggregate
> boundaries isn't what Evans intended when he wrote the pattern.    Hmm,
> perhaps I should ask him.
> 
> Enough already.  Have to get on with some work, here....
> 
> Dan
> 
> [1] http://tech.groups.yahoo.com/group/domaindrivendesign/message/11202
> 
> 
> 
> 
> On 19 April 2013 13:29, Vaughn Vernon <vv...@shiftmethod.com> wrote:
> 
>> Your bias may be mostly due to not actually using the Aggregate pattern.
>> If you were truly using Aggregates to define transactional consistency
>> boundaries then reference by id would not be a problem. (Maybe you allow
>> your consistency boundaries to change per use case.) You don't have to use
>> Aggregates to benefit from DDD, but it's good to understand when you are
>> and are not using them. This is true whether or not you are using
>> relational databases or kv stores. There is no difference in applying
>> Aggregate in either case.
>> 
>> I am sure I will not have more to add.
>> 
>> Vaughn
>> On Apr 19, 2013 1:56 PM, "Dan Haywood" <da...@haywood-associates.co.uk>
>> wrote:
>> 
>>> Thanks for commenting on this, Vaughn.
>>> 
>>> You are right it is the consensus view, because the consensus seems for
>>> some reason to focus on NoSQL and non-transactional databases.  I remain
>>> confused by this; the vast majority of enterprise systems are built against
>>> RDBMS, and that will the case.
>>> 
>>> I still haven't heard any good reason to follow your "disconnected domain
>>> model" if using an RDBMS.
>>> 
>>> Actually, that's not quite right.  Over in Ireland on the big Naked
>>> Objects system based on .NET and Entity Framework, we *do* use the pattern
>>> when entities in different EF DbContexts refer to each other.  We have one
>>> DbContext for each module (namespace); eg Customer, Document, Security,
>>> Appointment, Task, RecordedAction, GenericScheme, Payment and so on.  The
>>> modules form a DAG, preventing the domain model becoming a big ball of mud.
>>>   EF cannot manage relationships between entities in different modules,
>>> and so we do it ourselves using a pattern that is basically equivalent to
>>> the "disconnected domain model".
>>> 
>>> We also do this because we want polymorphic relationships between
>>> entities in different modules.  For example, there are many objects in
>>> different modules that can act as a DocumentHolder.  The Document module
>>> defines this as an interface, and each Document references its
>>> DocumentHolder, but the actual class that implements this interface could
>>> be in any of several modules.  Even if we weren't using modules, we would
>>> need to do this because (at the moment) EF does not support polymorphic
>>> relationships.
>>> 
>>> As I see it, if using an RDBMS, the notion of module is a much more
>>> important organizing concept than aggregate.  But I find there's virtually
>>> no discussion of the module pattern by those that hold the "consensus view".
>>> 
>>> Hope the above doesn't come over as a rant; but I do think that that
>>> article doesn't sufficiently explain why the disconnected domain model
>>> pattern should be "preferred" in all cases; bottom line: I don't think it
>>> should.
>>> 
>>> Dan
>>> 
>>> 
>>> 


Re: A heavier or smaller root aggregate

Posted by Dan Haywood <da...@haywood-associates.co.uk>.
On 13 May 2013 14:44, GESCONSULTOR - Óscar Bou <o....@gesconsultor.com>wrote:

>
> There seems to be a "little" debate about "referencing ids vs lazy loading
> (with or without "direct" reference)" and more on the DDD Yahoo User
> group...
>
> http://tech.groups.yahoo.com/group/domaindrivendesign/message/24048
>
>
You know, after 5 years on that list I've now unsubscribed.  To my mind
most conversations get bogged down in technical implementation details
(this thread is a good example).




> The main point is that sometimes this "Domain Id." does not correspond to
> any Domain concept, so it shouldn't be introduced on the Domain model.
>
>
Indeed.  Except you have to do that if using (what the blog post you
reference below calls) the "aggregate documents" pattern.



>
> Also, there's an interesting blog post about this 2 ways of implementing
> DDD:
>
> http://rogeralsing.com/2009/11/08/two-flavors-of-ddd/
>
> I remember reading this blog post a while back; yes, it's a good one.
 Though the main reason to not use "aggregate graph" (ie ORMs) is: they are
hard to use.

You know: I think that's right in the general case.  The way that Isis uses
an ORM is more naturally constrained by the framework; because the
interactions are generic, if we fix an N+1 issue in one place, we tend to
fix it anywhere.

All this does though is move the argument: ORMs aren't necessarily tricky
if using an NO-style framework.  "Ah yes, but NO can't possible work" is
usually the rebuttal.



>
> But I simply would notice that both approaches can be mixed (specially on
> different Bounded Contexts). If one BC is implemented over a framework that
> supports by default "lazy loading" a direct reference will be exactly the
> same in size as a "referencing id" and none of the problems noticed on
> Vaughn's "Implementing DDD" would occurred.
>
> Agreed.  IDs are needed for wiring different BCs together.  And tend not
to be needed (unless they are part of the UL) within a BC, if an ORM is in
use.


 ~~~~~~~~~~

>
> During my evaluation, I think the following assumptions can be made about
> the Apache Isis default programming model (please, correct me if any of
> them is incorrect or if there are any additional points to consider):
>


> - By default all referenced objects are lazy-loaded.
>

Yes, because that is JDO/DN's default.  However, you can influence this
using fetch groups.[1].  At the moment Isis only ever uses the default
fetch group.  I could imagine in the future that we might define a set of
named fetch groups for certain interactions, and thus allow the domain
programmer to influence what's going on.  But right now, it's just the
default fetch group that is used.



> - Wicket viewer only implicitly loads a referenced object for showing it's
> name. For the referenced object only it's name will be loaded, so this will
> break the "loading chain" (no other referenced objects, are they will also
> be lazy-loaded, unless explicitely told; nor the name of this dependent
> objects).
>

More precisely, its title.

As you know, the title is computed via the title() method or using the
@Title annotation, so Isis will load (or cause to load) as much of the
object as is necessary.

One trick you can do, if the title is expensive to compute, is to have a
@Hidden property which holds the title, and update it whenever underlying
information changes.  You could do this in the updating() callback, for
example.  We've done this once or twice.



> - Updating collections will not cause JDO/DataNucleus to update the
> version on the Aggregate Root / PersistenceCapable Entity.
>

That is true.  I don't know of any way to change that.



> - Collections are "disabled" (lazy-loaded) by default, unless explicitely
> annotated, by the Apache Isis "contract" with the programmers and
> implemented viewers.


Yes, though again you can use JDO/DN fetch group may override this.



> If they must be eagerly loaded, the programmer must explicit it by
> annotating the Collection with @Resolve(Type.EAGERLY), such as in:
>
> public class Order {
>     @Resolve(Type.EAGERLY)
>     public List<LineItem> getLines() { ... }
>     ...
> }
>
>
This is a hint to Isis rather than JDO.  If you haven't used a fetch group
then underneath you will most likely see two queries: one for the Order
object, and another for the LineItems.  It shouldn't be an N+1 query,
though.




> - Same happens for direct Entity references:
>
> public class Order {
>     @Resolve(Type.EAGERLY)
>     private Customer customer;
>     ...
> }
>
>
This is redundant; we always render the title of 1:1 referenced objects, so
this does nothing.  Again, under the covers there will likely be an
additional query to fetch that referenced (customer) object in order to
render its title.

HTH
Dan


>
>
> Cheers,
>
> Oscar
>
>

[1] http://www.datanucleus.org/products/datanucleus/jdo/fetchgroup.html