DDD Factory Object Value Object

In my current project, I am increasingly adopting the DDD / Onion architecture. One of the many things that I still don't understand about is how much encapsulation should be. It is 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 a factory object, you,

  • Expect the caller to construct value objects for you and use it to initialize ComplexEntity?
  • Essentially, the base CLR types are passed to the factory, and you build every ValueObject that makes up Entity?

I am inclined to option 2, but I cannot find support for it.

Change 1

Honestly, I'm still unclear. What about aggregate roots?

When my object refers to other objects, for example. below.

  • Should I have IComplexEntityFactory , ILessComplexEntityFactory ? Or is it just IComplexEntityAggregateFactory that creates LessComplexEntity and instantiates ComplexEntity?
  • In the case of an AggregateFactory solution, what should I do if the LessComplexEntity attributes passed to the factory match the existing LessComplexEntity? Am I retrieving and reusing it from the repository? Or am I returning an error to the caller?
  • What would be the method signature for an AggregateFactory? It will 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) {}}

+4
source share
2 answers

I would choose option 1.

  • Makes it explicit to everyone that you need ValueObjectA to create a ComplexEntity. More readable, less scratching the head when you see the method used.

  • If ValueObjectA changes, you will only need to change the code in one place (calling the factory), as opposed to changing the signature of Create () + the setting for creating the value object inside the factory.

  • Smaller parameters for the factory Create () method are less verbose and more readable.

  • In unit tests, you get much more opportunities to be able to enter the required ValueObjectA. Not much can be done in terms of testing if you fully retain the creation of ValueObjectA inside the factory.

[change]

It's not clear what your real problem is with Aggregate Roots and Factories, but you should not mix responsibility for obtaining / redesigning an existing object with responsibility for creating the object.

I would take as a general rule that the task of the factory is to assemble a new object from smaller parts (be it primitive types, value objects, entities ...)

The factory should be equipped with all these parts, not its duty to retrieve or rehydrate them from somewhere. You can leave this to the caller factory. This will make the factory more connected and tied to smaller classes (repositories, etc.).

+3
source

I prefer option # 1, as this will reduce the number of parameters needed for the factory method. But my advice would be to use only the factory when the creation strategy is required for the population in question.

In one of your comments, you say:

".. but then I don’t understand the advantages of the factory. All it will do is just call the ComplexEntity constructor, and not create all the subcomponents that create it."

The factory's task is to make decisions on how to create an instance of the population by looking at the data passed to it. In my experience, the general scenario where this is required is where inheritance / polymorphism is used. For example, imagine that you have an abstract class Account with two subclasses: SavingsAccount and CurrentAccount. The factory's task is to decide which one should be created, given some data.

Another potential advantage of the factory is how expressive you are. If an aggregate can be created in several ways (i.e., using different arguments), then this can be better expressed with the method name in the factory than an overloaded constructor.

As I said, my advice is not to create a factory for each unit, if for one of the above reasons. Otherwise, as you indicated, this will be only one line, calling the constructor with the same arguments that are passed to it.

+1
source

All Articles