I have been increasingly adopting DDD / Onion Architecture in my current project. One of the many things I am still unclear about is how much encapsulation should there be. Easier explained with a concrete example.
Example
namespace MyProject.Model
{
public class ComplexEntity
{
private int _id;
public int Id { get {return _id;} }
public ValueObjectA ValueA {get; set;}
public bool IsBool {get; set;}
public ComplexEntity(ValueObjectA a, bool isBool)
{
// Do some validation first
ValueA = a;
ValueB = b;
IsBool = isBool;
}
}
public class ValueObjectA
{
public bool IsBoolA {get; private set;}
public bool IsBoolB {get; private set;}
public ValueObjectA(bool a, bool b)
{
IsBoolA = a;
IsBoolB = b;
}
}
public Interface IComplextEntityFactory
{
// Option 1
ComplexEntity Create(
ValueObjectA a,
bool IsBool);
// Option 2
ComplexEntity Create(
bool valueABool a,
bool valueBBool b,
bool isBool);
}
}
Question
For the factory of an entity, do you,
I am leaning towards option 2 but I can't seem to find supporting literature for it.
Edit 1
To be honest I am still no clearer. What about aggregate roots?
When my entity refers to other entities, e.g. below.
IComplexEntityFactory
, ILessComplexEntityFactory
? Or just an IComplexEntityAggregateFactory
that creates the LessComplexEntity and instantiates ComplexEntity ?What would the method signature be for the AggregateFactory? Would it be (ValueObject a, ValueObject b)
, or (ValueObject value, LessCompelxEntity entity)
public class ComplexEntity { private readonly int _id; public int Id { get { return _id;} }
public ValueObject Value {get; set;}
public LessComplexEntity Entity {get; set;}
public ComplexEntity(int id, ValueObject value, LessComplexEntity entity)
{
}
}
public class LessComplexEntity { private readonly int _id; public int Id { get {return _id;} } public ValueObject Value {get; set;} public LessComplexEntity(int id, ValuObject value) { } }
I'd choose option 1.
Makes explicit to everyone that you need a ValueObjectA to build a ComplexEntity. More readable, less head scratching when you see the method used somewhere.
If ValueObjectA changes, you'll have to modify the code in only one place (the factory's caller) as opposed to changing the signature of Create() + adjusting the value object creation inside the factory.
Less parameters to the factory's Create() method is less verbose and more readable.
In unit tests, it gives you a lot more options to be able to inject the ValueObjectA you want. There's not a lot you can do in terms of testing if you keep ValueObjectA's creation hidden inside the factory entirely.
[Edit]
It's not clear what your real problem is with Aggregate Roots and Factories, but you shouldn't mix up the responsibility to retrieve/rehydrate an existing object with the responsibility to create an object.
I'd take as a general rule that a Factory's job is to assemble a new object from smaller parts (whether they be primitive types, value objects, entities...)
The Factory should be provided with all these parts, it is not its duty to retrieve or rehydrate them from somewhere. You can leave that to the Factory's caller. It will make the Factory more cohesive and coupled to less classes (Repositories, etc.)