0

I wonder whether I should model dependent objects as aggregate roots. Let's say I have a TaskList and this list has Tasks. A Task cannot exist without a TaskList but it can be viewed and edited separately. There are no special conditions that the TaskList could check when a Task is modified or added - which would be the main reason for an aggregate root, I think. The only condition is, that the TaskList and its tasks can only be edited by the owner. It would be easy to ensure this condition if the TaskList had an owner and the Tasks could only be edited through the TaskList. Otherwise I would need to detect the owner transetivly or add an owner field to the tasks.

So what is appropriate here?

  • Task and TaskList both as aggregate roots and each with an owner field
  • Only TaskList as aggregate root and Tasks as dependent entities

Am I missing something important?

deamon
  • 89,107
  • 111
  • 320
  • 448

2 Answers2

1
  • If there are no invariants governing both, design them as separate aggregates.
  • The tasklist is the factory of tasks, thus allowing it to tell the task who the owner of the task is. Any subsequent behaviors of the task can now verify that they are performed by the proper owner (i.e. the task should remember what the list told the owner was). However, this seems like poor design from a UX perspective. Why enable the edit button (or show the details as editable) on tasks the user is not owner of? Yes, a man in the middle attack is possible. But how much time/money are you willing to spend on that (how critical is it)?
  • As for authorization, do question how much that's part of your model. Not saying it isn't or is, just something to think about.
  • More on aggregate design can be found here: Effective Aggregate Design & Improving performance and scalability with DDD
Community
  • 1
  • 1
Yves Reynhout
  • 2,982
  • 17
  • 23
0

I would do it like this:

class TaskList{
 User Owner;
 Task[] Tasks;
}

class Task{
 TaskList List; string Description;
 void ChangeDescription(description){
  if(List.Owner!=CurrentUser)
   throw exception or whatever;
  else
   Description=description;
 }
}

// http post
class TaskController{
 ActionResult ChangeDescription(int id, string description){
  _tasks.Find(id).ChangeDescription(description);
 }
}
Arnis Lapsa
  • 45,880
  • 29
  • 115
  • 195