Domain-Driven Design
> >
RepositoriesVsDAOFindersQueryHelpers

Thu Jan 1, 2004 5:54 pm

I have a minor minor domain model implemenetation detail that's been
nagging me a bit. It's really more of a naming issue than any thing
else.

If I understand correctly, a repository lets clients of the domain
model find aggregate roots. Clients can only find aggregate roots,
and only through repositories. Clients traverse explicit
associations from the aggregate root to obtain other objects. An
association method may be internally implemented through a DAO or
somesuch, but clients don't know that. So repositories are explicit
domain objects exposed to clients; DAO's (or whatever) are 'private'
implementation details.

I really like this distinction, because it allows you to control
associations. With public DAO's or finder methods for every entity,
explicit associations don't mean much. Clients can call
parent.getChildren(), or they can bypass the association method and
call ChildDao.findByParentId(parent.getId()) directly. Chaos.
Explicitly exposing the query methods clients are allowed to call via
repositories, and only allowing 'queries' to aggregate roots is a
great idea.

We're using Hibernate (an O/R mapping tool) on my project. With
Hibernate, most associations are implemented in the domain model
literally as instance variables with getters and setters, and
Hibernate takes care of the rest. That's really nice. However, we
have a legacy database, so sometimes we have to write explicit
Hibernate queries to implement associations. The amount of Hibernate
code involved is pretty small, but still it'd be nice to factor it
out. Here's an example. Manager (an aggregate root, perhaps) has an
association to his employees. We need to implement that via a query.
The query text is stored in an XML file, but we still have to write a
bit of code to get the Query object, set the parameters, and run the
query. Something like this:


class Manager {
   Collection getEmployees() {
      Query query = QueryRegistry.getQuery("getEmployeesByManager");
      query.setLong(0this.getId());
      query.setBoolean(1true)// we only want 'active' employees
      return query.execute();
   }
}


So maybe we factor that out into a QueryHelper, like this:


Collection getEmployees() {
   return ManagerQueryHelper.getEmployees();
}


We can stub out the QueryHelper for unit testing.

OK, finally here are my questions:

1. What should we call the 'helper' classes? XxxQueryHelper?
XxxAssociationHelper? XxxFinder? XxxDao? Or should we just call
them repositories, but don't expose them to clients? (I.e., make
them 'package private' in Java.)

I don't like the idea of calling them repositories. Even though the
implementation will be almost identical to a repository, they mean
different things. A repository is an explicit part of the domain
model; these things are just 'helpers'; implementation details. The
Hibernate folks use XxxFinder. But that sounds kind of 'public' to
me; I want to stress the private, implementation detail nature of
these things. Thus XxxQueryHelper. Dao is OK I guess. Other ideas?

2. Should we implement andd name these helper classes from the point
of view of the objects being returned, i.e. EmployeeQueryHelper in
the example, or from the point of view of the object that is use the
helper to implement an association? I.e. ManagerQueryHelper. I'm
kind of leaning towards the latter, even though I did the former in
my example above. Given the rules about associations and aggregate
roots, the Manager.getEmployees method should be the only method that
needs to run the employees query. Calling it ManagerQueryHelper
stresses that it's a private implementation class of Manager.

SteveMolitor


> 1. What should we call the 'helper' classes? XxxQueryHelper?
> XxxAssociationHelper? XxxFinder? XxxDao? Or should we just call
> them repositories, but don't expose them to clients? (I.e., make
> them 'package private' in Java.)

I dislike "Helpers". They're procedural and the more of them I have, the
less easily I see other opportunities to refactor. What if you called
them query factories? This way you can avoid the class-level methods
(bad for object testing), hide the factory methods behind an interface,
then use a mock objects approach when testing the query factory clients.

JBRainsberger




RepositoriesVsDAOFindersQueryHelpers is mentioned on: ThreadView


VeryQuickWiki Version 2.6.3 - HTML Export