So, I came upon the code similar to the example below. One thing that bothered me about it was the fact that it's dependent on a Result object being created in the Application Service then passed down into the Domain Entities. This struck me as odd, as it's exposing parts of the domain. It's also receiving a parameter that shouldn't ever have any value other than the default - an empty/default/success Result.
I suggested to make the public methods return Result instead (either instead of void or as an out parameter), while keeping the internal methods the same. The argument against this is that it's more difficult to include all errors in the same result if you're not passing the result down into Save, for example..
It's worth noting that there are two aggregate roots here, and they overlap. When editing Parents or Children, both Parent and Child have an aggregate root of Parent. When copying, all three classes have an aggregate root of Grandparent.
What's the best way to proceed, here? Optional parameters? Redefine the aggregates so everything goes through Grandparent? Have the lower Copy methods return a List of Result that can be collapsed into a single one in Grandparent? Is there something we're missing?
public class Grandparent
{
private IEnumerable<Parent> Parents;
private int Id;
public void Save(Result result)
{
Validate(result);
/*Save*/
}
public void Copy(Result result)
{
Id = 0;
Save(result);
foreach (var parent in Parents) parent.Copy(result, Id);
}
private void Validate(Result result) { /*Update result if there are any errors*/ }
}
public class Parent
{
private IEnumerable<Child> Children;
private int Id;
private int GrandparentId;
public void Save(Result result)
{
Validate(result);
/*Save*/
}
public void SaveChildren(Result result, ICollection<Child> dto)
{
/*Do stuff with dto*/
foreach (var child in Children) child.Save(result);
}
private void Validate(Result result) { /*Update result if there are any errors*/ }
public void Copy(Result result, int grandparentId)
{
Id = 0;
GrandparentId = grandparentId;
Save(result);
foreach (var child in Children) child.Copy(result, Id);
}
}
public class Child
{
private int Id;
private int ParentId;
internal void Save(Result result)
{
Validate(result);
/*Do thing*/
}
private void Validate(Result result) { /*Update result if there are any errors*/ }
public void Copy(Result result, int parentId)
{
Id = 0;
ParentId = parentId;
Save(result);
}
}