DDD 工厂实体值对象

M A*_*ifi 6 c# domain-driven-design factory onion-architecture

在我当前的项目中,我越来越多地采用 DDD/洋葱架构。我仍然不清楚的许多事情之一是应该有多少封装。用一个具体的例子更容易解释。

例子

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);
    }
}
Run Code Online (Sandbox Code Playgroud)

对于一个实体的工厂,你,

  1. 期望调用者为您构造值对象并使用它来初始化 ComplexEntity?
  2. 是否将 CLR 基本类型传递给工厂,并且您构造了构成实体的每个 ValueObject?

我倾向于选项 2,但我似乎找不到支持它的文献。

编辑 1

说实话我还是不太清楚。聚合根呢?

当我的实体引用其他实体时,例如下面。

  1. 我应该有一个IComplexEntityFactory,ILessComplexEntityFactory吗?或者只是一个IComplexEntityAggregateFactory创建 LessComplexEntity 并实例化 ComplexEntity 的?
  2. 在 AggregateFactory 解决方案的情况下,如果传递给工厂的 LessComplexEntity 属性对应于现有的 LessComplexEntity,我该怎么办?我是否从存储库中检索和重用它?或者我是否向调用者返回错误?
  3. AggregateFactory 的方法签名是什么?是吗(ValueObject a, ValueObject b),或者(ValueObject value, LessCompelxEntity entity)

    公共类 ComplexEntity { 私有只读 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)
    {
    }
    
    Run Code Online (Sandbox Code Playgroud)

    }

    公共类 LessComplexEntity { 私有只读 int _id; public int Id { get {return _id;} } public ValueObject Value {get; set;} public LessComplexEntity(int id, ValuObject value) { } }

gui*_*e31 5

我会选择选项1。

  • 向所有人明确说明您需要 ValueObjectA 来构建 ComplexEntity。当您看到某处使用的方法时,更具可读性,更少头疼。

  • 如果 ValueObjectA 发生变化,您将只需要在一个地方(工厂的调用者)修改代码,而不是更改 Create() 的签名 + 调整工厂内部的值对象创建。

  • 工厂的 Create() 方法的参数越少,就越不冗长且可读性更强。

  • 在单元测试中,它为您提供了更多选项,以便能够注入您想要的 ValueObjectA。如果您将 ValueObjectA 的创建完全隐藏在工厂内部,则在测试方面您无能为力。

[编辑]

目前尚不清楚聚合根和工厂的真正问题是什么,但是您不应该将检索/再水化现有对象的责任与创建对象的责任混为一谈。

我认为工厂的工作是从较小的部分(无论它们是原始类型、值对象、实体......)组装一个新对象作为一般规则。

工厂应提供所有这些部件,工厂没有责任从某处取回或再水化它们。你可以把它留给工厂的调用者。它将使工厂更具凝聚力并耦合到更少的类(存储库等)