Usually whenever I want to fetch an aggregate root by ID I just use some type of Repository::findByID(...) function
Whenever I started with DDD I thought factories where just a pattern to build new objects, but after meeting some aggregates needing one or two extra queries to load, I realized that Factory::objectWithID(...) were useful to also create instances of objects already existing in the database.
Now I have a tree relationship of entities, like Project->Task. The number of relations is huge and I have no framework providing lazy loading.
Since Tasks can be nested, have complexity of their own, and should not be fully retrieved in one query, I made Project and Task different aggregate roots
How should I retrieve and persist Tasks?. It seems that a ProjectFactory is not the solution this time because a Project does not contain the whole Task tree.
I still want some aggregate root like features for my Project, and since I am avoiding queries inside my entities, I decided to write the relationships inside a Project-Service-Aggregate. Now I can retrieve a single Project with a Repo::findByID() function, but fetching a Task looks like
ProjectAggregationService *service = ProjectAggregationService.new(SomeProject)
Task task_1 = service.findTask(...)
Task task_1_child_2 = service.findTaskChild(task_1,2)
I am puzzled at this point because:
- I have a service to represent entity relationships.
- I am declaring many instances of a service, whereas before, services tended to be quite unique objects.
- Not having a clear object tree like Project.tasks[1].subtask[3] make the code above look like more complex than necessary.
Basically I could summarize my question to: Did I take the right approach?
I would greatly appreciate any comment on my reasoning. I am mostly concerned about degenerating my code with overblown complexity, but I still think that keeping references to queries and repos outside my entities implementation is a good goal.
-
If you don't have a framework for lazy loading, why don't you add that (framework or lazy loading), as it seems to be just what you want?Frank– Frank07/19/2013 11:13:02Commented Jul 19, 2013 at 11:13
-
1I believe that there are common DDD solutions to this problem without lazy loading. Looking back at my own code in previous projects, I realize that lazy loading was most of the time a comfortable way to ignore architecture problems. I do not wan to give up so soonSystematicFrank– SystematicFrank07/19/2013 12:01:52Commented Jul 19, 2013 at 12:01
1 Answer 1
I think logic like this is supposed to go into repository of specific aggregate. I would question if Project and Task need to be different aggregate roots. Aggregate roots should be decided based on business needs, not on (perceived) complexity. Either way I would create either ProjectRepository::getTasks(project)
or TaskRepository::getTask(project, taskId)
. This way, you will keep number of services to minimum while still keeping logic where it is logical to look for it.
-
I would love to manage Task objects through an aggregate with Project as root. However it's my understanding that aggregates should be pulled all at once. Whenever I see danger of an Entity pulling out too many associations, I split the aggregate. Still I want a class that given one single Project, it takes care of fetching/adding and cascading the deletions. Sounds like a repo, but ProjectRepo and TaskRepo serve other type of queries. Sounds like an aggregate, but then, aggregates should be repo agnostic. Right? Hence I try to cheat the golden rules with a Service emulating an AggregateSystematicFrank– SystematicFrank07/19/2013 20:06:46Commented Jul 19, 2013 at 20:06
-
mmm... just reading my previous comment I realized that ProjectRepository::getTasks(project) is not so bad. I refused the idea of a plain query like that because I was thinking in a "tree like" access ... however now I am thinking about an enhanced query object that provides such tree like access abstraction with the persistance layer. Never saw a tree result Query class, but that might fit the bill. Time to research again. Thanks for the inspirationSystematicFrank– SystematicFrank07/19/2013 20:16:34Commented Jul 19, 2013 at 20:16
Explore related questions
See similar questions with these tags.