Loading ...
Sorry, an error occurred while loading the content.
 

Re: Breaking the dependency between entities and DAOs

Expand Messages
  • larry.chu
    Hi Henry, In my experience, I have used various different methods for a Domain Object to obtain a reference to a Repository (or any Service) * Singleton
    Message 1 of 33 , May 6, 2008
      Hi Henry,

      In my experience, I have used various different methods for a Domain
      Object to obtain a reference to a Repository (or any Service)

      * Singleton Repository / new Repository() - as mentioned already by
      Randy Stafford in a previous message in this thread. These are the
      simplest solutions, but I tend to avoid them in favor of loose
      coupling with a Service Locator to at least simplify testing.

      * Service Locator / Registry - This slightly intrusive option works
      well when there are few alternatives available for your development
      platform. Service Locator can decouple the Repository implementation
      from the Domain Object. Since the Service Locator or Registry can be a
      single point of entry, you could easily swap it out with a stub for
      testing.

      * Pass from Factory - Create a DDD factory to pass a Repository
      reference to the Domain object under construction. This would require
      an additional Factory class for every Domain Object that needs a
      reference to a Repository, and should be used in conjunction with
      either Pass from Repository, or a ORM provided Interceptor.

      * Pass from Repository - Within a Repository, pass the reference to
      the Domain Object under construction. This would only work to pass
      Repository references to Domain Objects structurally contained within
      the aggregate.

      * ORM provided Interceptor - Similar to the above. I reiterate, can
      only modify Domain Objects structurally contained within the aggregate.

      * Byte code instrumentation - (such as AspectJ) I have found this to
      be the most powerful of all the methods, and is generally used in
      conjunction with Annotations and Dependency Injection. Any Domain
      Object (Entity or Value Object or any object at all) can be instrumented.

      For Java, I use Spring's @Configurable annotation in conjunction with
      AspectJ and I am very happy with it. I am uncertain whether there are
      any good byte code instrumentation tools for .NET because I haven't
      developed with it for a while, but if there are, they're definitely
      worth the look.

      Larry

      --- In domaindrivendesign@yahoogroups.com, "Hendry Luk"
      <hendrymail@...> wrote:
      >
      > I think the AOP sounds worth to try. I'll look more into it. But
      ideally I
      > think i might lean toward the nHibernate interceptor as you mentioned as
      > well.
      > I'm ok with code-mangling AOP, but I generally steer away from it if
      > there is still 'proper' way to achieve the same behavior. Like u
      > said, reduced automagic factor with interceptor, and I can't see any
      > downside.
      >
      > Thanks for all the suggestions guys.
      >
      >
      > On Tue, May 6, 2008 at 8:01 PM, Alasdair Gilmour <alasdairg@...>
      > wrote:
      >
      > > > Ouf of curiousity, how would you get hold of that repository
      > > instance from domain-model? Especially when the entity is
      constructed by
      > > ORM, is there any common pattern of how
      > > > services are injected from IoC into the domain model? I have
      seen some
      > > people having a factory for each entity, in pair with the
      repository, that
      > > is responsible for injecting all
      > > > services into entity's constructor. But it doesn't really work
      well with
      > > ORM does it?
      > >
      > > The neatest way I've seen this done uses AOP and annotations: Class
      > > bytecode is altered at compile time (actually, at load time is
      possible too)
      > > to intercept constructor calls and call into a framework behind
      the scenes
      > > which injects the dependencies into the annotated members. From
      the domain
      > > layer's perspective its about as non-intrusive as you can get,
      although it
      > > might be a bit too "automagic" for some peoples' tastes ....
      > >
      > > public class Customer {
      > >
      > > private AccountRepository accountRepository;
      > >
      > > @Dependency
      > > public void setAccountRepository(AccountRepository rep) {
      > > accountRepository = rep;
      > > }
      > >
      > > public void doSomething() {
      > > List<Account> list = accountRepository.getAccounts();
      > > ....
      > > }
      > >
      > > ..... etc .....
      > > }
      > >
      > > Customer x = new Customer( ... ); // <----- setAccountRepository() is
      > > automatically called at this point to inject the required dependency
      > > x.doSomething();
      > >
      > > If you are using an ORM like Hibernate, it is also possible to do
      > > something similar but more conventional by writing an Interceptor
      that gets
      > > called by the ORM when an Entity is being loaded from the database
      - you can
      > > then perform injection at that point. This works but is obviously
      a lot more
      > > limited (e.g. only works for non-transient entities etc.)
      > >
      > > Alasdair
      > >
      > >
      > >
      >
    • e_blackbrook
      Just a couple of additions to avoid misunderstanding: When I talk about direct-to-RDBMs operations, I mean (typically) through a Repository object. I don t
      Message 33 of 33 , May 8, 2008
        Just a couple of additions to avoid misunderstanding:

        When I talk about direct-to-RDBMs operations, I mean (typically)
        through a Repository object.

        I don't think such queries or operations should be looked at as an end
        run around the domain model, I think the RDBMs schema should be looked
        at as and embodiment of that domain model, as important and valid as
        the OO one.

        --- In domaindrivendesign@yahoogroups.com, "e_blackbrook" <ericjs@...>
        wrote:
        >
        > Yes, of course any query or operation made possible by the RDBMS is
        > possible by operating on your domain objects, but often at great cost
        > in terms of memory used, execution time, and developer work.
        >
        > I'm basically recommending what Randall says in his post:
        >
        > http://tech.groups.yahoo.com/group/domaindrivendesign/message/7406
        >
        > Use each for what they are good at, and don't let misplaced idealism
        > get in the way of that. I say "misplaced" because ORMs are a
        > workaround for technology flaws which result in the "impedence
        > mismatch", and I look at workaround technologies more as a necessary
        > evil than a matter for idealism.
        >
        > The most common needs for direct RDBMs operations without
        > instantiating all the individual domain objects, could be described as
        > reports. However there are other cases. Bulk changes which would
        > update thousands of records is another. So might a complicated bit of
        > logic which equates to a query joining several tables and with a
        > number of criteria. You *could* call that a report, but it is really a
        > bit of domain logic which would be much more complicated and costly to
        > perform manually with your objects. What is so commonly forgotten or
        > not understood is that an RDBMs is a predicate logic engine, capable
        > of extracting derivative facts from the facts which are represented by
        > the records in the database. It would be a pity to refuse to make use
        > of that power.
        >
        > Of course you don't want to be performing those kinds of RDBMS
        > operations while you have uncommitted changes lying around in your
        > objects. I've never found this to be a problem though, as the
        > operations which most call for direct RDBMs operations are different
        > operations than those where updates through the individual objects are
        > desirable, and happen in different transactions.
        >
        > Eric
        >
        >
        > --- In domaindrivendesign@yahoogroups.com, "Greg Young"
        > <gregoryyoung1@> wrote:
        > >
        > > What exactly does your RDBMS provide you in this area that is not a
        > > "report", when I say report I mean a query that is not required for
        > > consistency ... i.e. not reading a domain object's state so the domain
        > > object can determine whether or not a new change can be added.
        > >
        > > Could this same functionality be exposed in other ways? Perhaps only
        > > using an RDBMS for "reports" and keeping it synchronized with your
        > > transactional model?
        > >
        > >
        > > Has letting the impedance mismatch of the RDBMS leak into your world
        > > caused problems with your model?
        > >
        > > Cheers,
        > >
        > > Greg
        > >
        > >
        > > On Sat, May 3, 2008 at 11:29 AM, e_blackbrook <ericjs@> wrote:
        > > >
        > > >
        > > >
        > > >
        > > >
        > > >
        > > > I think part of the problem here is seeing the database as nothing
        > > > more than a persistence mechanism. A relational database is far
        more
        > > > than that and looking at it as just a persistence mechanism
        naturally
        > > > leads you to want to decouple your domain classes from it as
        much as
        > > > possible. But that makes it difficult to leverage the powerful
        > > > features an rdb has for representing, accessing, and
        manipulating the
        > > > domain model that go beyond what your OO classes can do. I find it
        > > > better to consider the rdb as an integral part of the domain model
        > > > representation and not worry so much about how tightly it is
        > > > integrated with the object version of the domain model. (Which
        is not
        > > > to say the two should be tangled together haphazardly.)
        > > >
        > > > Eric
        > > >
        > > >
        > > >
        > > > --- In domaindrivendesign@yahoogroups.com, "bhatiana" <nbhatia@>
        > wrote:
        > > > >
        > > > > Yes, that's exactly what I was trying to get at: is it a good
        > practice
        > > > > to allow entities to access DAO interfaces? (I understand the
        part
        > > > > about dependency inversion and thus decoupling entities from DAO
        > > > > implementations - so that's not an issue).
        > > > >
        > > > > Thanks.
        > > > > Naresh
        > > > >
        > > > > --- In domaindrivendesign@yahoogroups.com, "Hendry Luk"
        > > > > <hendrymail@> wrote:
        > > > > >
        > > > > > I'm quite new to DDD myself, but in my perspective, I think I
        > > > would use
        > > > > > observer pattern for this scenario. Write a
        TargetPriceNotifier,
        > > > and let
        > > > > > each Security object to subscribe to it. Thus, Security
        > object can
        > > > > update
        > > > > > its prices without tying itself to to any persistence logic.
        > > > > > And as side note, if you need to call DAO from your domain,
        > we can
        > > > > break the
        > > > > > circular dependency using dependency inversion. Domain objects
        > > > > depend only
        > > > > > to DAO interfaces, and I would usually put DAO interfaces in
        > the same
        > > > > > package as the domain objects. The package containing DAO
        > > > implemntations
        > > > > > would thus depend to that domain package.
        > > > > >
        > > > > >
        > > > > > On Thu, May 1, 2008 at 11:14 AM, bhatiana <nbhatia@> wrote:
        > > > > >
        > > > > > > I am implementing an application using DDD principles. I am
        > using
        > > > > > > Hibernate for persistence. I would like to keep the domain
        > model
        > > > > > > independent of my persistence mechanism. So the first
        > thought was to
        > > > > > > retrieve relevant domain objects in the service layer and
        > then start
        > > > > > > calling methods on these objects to implement the
        application's
        > > > > > > functionality. However this is proving to be very tough and
        > I would
        > > > > > > like to get any pointers on how others have tackled this
        issue.
        > > > Here's
        > > > > > > a specific example (it is in the trading domain):
        > > > > > >
        > > > > > > I have an entity called Security. A Security maintains a
        > history of
        > > > > > > TargetPrices. Thus we have a one-to-many relationship between
        > > > Security
        > > > > > > and TargetPrice. There is an external algorithm that runs
        > > > > > > periodically, looks at a whole lot of market parameters and
        > > > determines
        > > > > > > the next target price for each security. It then calls
        > > > > > > Security.setTargetPrice() for each security. The security
        > object
        > > > needs
        > > > > > > to do the following:
        > > > > > >
        > > > > > > find the last target price from the history
        > > > > > > if (new target price != last target price) {
        > > > > > > create a new target price record
        > > > > > > inform traders that the target price has changed
        > > > > > > }
        > > > > > >
        > > > > > > Now how can a security do this? I certainly don't want to
        pull
        > > > in all
        > > > > > > the TargetPrices before calling the method - that's
        > thousands of
        > > > > > > records and is very inefficient. I also do not want to call a
        > > > DAO from
        > > > > > > the Security object because that creates a circular
        > dependency -
        > > > DAOs
        > > > > > > certainly depend on domain objects and now the domain objects
        > > > suddenly
        > > > > > > depend on a DAOs! How have you tackled this issue in your
        > projects?
        > > > > > >
        > > > > > > P.S. Of course, I could rely on Hibernate's lazy loading
        > > > mechanism to
        > > > > > > pull in all TargetPrices automatically, search through them
        > and add
        > > > > > > one if necessary, but that's highly inefficient.
        > > > > > >
        > > > > > >
        > > > > > >
        > > > > >
        > > > >
        > > >
        > > >
        > >
        > >
        > >
        > > --
        > > Studying for the Turing test
        > >
        >
      Your message has been successfully submitted and would be delivered to recipients shortly.