Object DDD实体构造函数参数

Object DDD实体构造函数参数,object,entity,domain-driven-design,aggregate,Object,Entity,Domain Driven Design,Aggregate,如果您有一个以值对象作为属性的实体 哪个是实体构造函数的参数,值对象?还是值对象的基本类型 首先,我在实体外部构建值对象,并将值对象传递给实体构造函数。。。但后来我意识到,可能是实体本身必须构建价值对象 我这样认为是因为实体和值对象实际上是一个聚合,并且假设您必须通过聚合根(即,通过实体)访问聚合的内部 那么哪条路是正确的呢?是否允许处理实体外部的值对象?或者值对象只能由实体使用 多谢各位 编辑: 例如,我有一个实体“Task”,它是聚合根。此实体有一个值对象“DeliveryDate”(格式为

如果您有一个以值对象作为属性的实体

哪个是实体构造函数的参数,值对象?还是值对象的基本类型

首先,我在实体外部构建值对象,并将值对象传递给实体构造函数。。。但后来我意识到,可能是实体本身必须构建价值对象

我这样认为是因为实体和值对象实际上是一个聚合,并且假设您必须通过聚合根(即,通过实体)访问聚合的内部

那么哪条路是正确的呢?是否允许处理实体外部的值对象?或者值对象只能由实体使用

多谢各位

编辑:

例如,我有一个实体“Task”,它是聚合根。此实体有一个值对象“DeliveryDate”(格式为“dd/mm/yyyy hh:mm”)。实体也有更多的值对象

class DeliveryDate extends ValueObject {

    private String formattedDeliveryDate;

    private DeliveryDate() {
        super();
    }

    DeliveryDate ( String formattedDeliveryDate ) {
        this();
        this.setFormattedDeliveryDate ( formattedDeliveryDate );
    }

    private void setFormattedDeliveryDate ( String formattedDeliveryDate ) {
        << check that the string parameter "formattedDeliveryDate" is a valid date in format "dd/mm/yyyy hh:mm" >>
        this.formattedDeliveryDate = formattedDeliveryDate;
    }

    ........     
我的疑问是:这样行吗?(将DeliveryDate对象传递给构造函数) 还是我应该传绳子?(构造函数创建DeliveryDate对象)

我认为这更像是一个“聚合外部是否应该知道DeliveryDate概念?”

一般来说,我怀疑的是任何实体的任何值对象,而不仅仅是任务和交付日期(这只是一个示例)


我已经问过关于构造函数的问题,但是它对工厂也是有效的(如果创建实例的过程很复杂的话)。。。聚合工厂参数是否应为值对象?或者创建价值对象的原语?

域驱动设计在此不提供任何具体指导

一个常见的情况可能是这样的:我们从数据库中检索了一个DTO,现在想从中创建一个实体

class Entity {
    private Value v;

    Entity (Value v) {
        if (null == v) throw new IllegalArgumentException();

        this.v = f;
    }

    Entity (DTO dto) {
        this(new Value(dto));
    }

    // ...
}
如果调用第二个构造函数而不是第一个构造函数,这真的很重要吗?不多

语言检查:

无法从数据库中检索DTO。从数据库检索的是聚合,而不是DTO

我不得不放弃这个想法——这个定义导致了太多的问题

例如,在事件源设计中,数据库通常存储事件的表示,而不是聚合

即使在传统的设计中,它也不起作用——聚合的边界是由域模型强制执行的约束定义的。一旦获取了数据,剩下的只是状态的表示。换句话说,我们在数据库中保存状态,但不保存行为,也不保存约束——您无法从保存的数据中导出约束,因为您看不到边界

决定哪些数据需要保持内部一致性的是模型,而不是数据库


我倾向于使用术语DTO,因为这是它的角色:——在这个特定的实例中,在数据库和域模型之间。如果您想使用或记录,我不会吹毛求疵。

在您的情况下,这两种解决方案似乎是相似的。无论是在实体的外部还是内部创建值对象,这都无关紧要。但是,请考虑当您的实体将有多个值对象时,实体构造函数将包含太多的逻辑,以确保它正确创建VO,同时强制执行实体的不变量

避免这种不必要的复杂性的一个解决方案是使用工厂。工厂将抽象创建过程,这将使实体代码保持简单

在DDD中,工厂对于创建聚合非常有用。在蓝皮书中有一整章是关于工厂的,这里有一篇关于在DDD中使用工厂的好文章

编辑

我的疑问是:这样行吗?(将DeliveryDate对象传递给构造函数)还是传递字符串?(构造函数创建DeliveryDate对象)

是的,没关系。任务不应该知道如何创建值对象。您不应该传递字符串,因为这会增加任务构造函数的复杂性和责任

我认为这更像是一个“聚合外部是否应该知道DeliveryDate概念?”

是的,聚合外部知道交货日期并不是问题。这与了解字符串和整数是一样的。值对象易于处理和推理,它们是域的一部分,因此我认为在聚合之外处理它们不会有问题

聚合工厂参数是否应为值对象?还是创建值对象的基本体


在这里,我想说工厂应该接收基本类型并封装对象创建。因为如果您将值对象传递给工厂,它只会将相同的参数传递给实体构造函数,这就是一个。

您能举个例子吗?我不明白你需要知道什么嗨,康斯坦丁。请参阅我的编辑。也许我没有很好地表达自己。谢谢,你好,穆罕默德。非常感谢。请参阅我的编辑。事实上,在真实的例子中,我使用了一个工厂。你好,穆罕默德,除了在工厂之外,我在大多数事情上都同意你。这取决于:如果实体有多个值对象,那么工厂将有许多基本类型参数。在这种情况下,我认为工厂收到value对象会更好更清晰。我认为从基本类型构造值对象的工作更多地是应用程序层(作为域的直接客户机)。它从GUI适配器接收基本类型,并构造值对象以将其传递给聚合、工厂、域服务等。Hi Mohamed。我不同意的另一句话是:“任务不应该知道如何创建价值对象”。我认为应该这样做,因为value对象是实体的一个属性,也是aggr的一个元素
class Entity {
    private Value v;

    Entity (Value v) {
        if (null == v) throw new IllegalArgumentException();

        this.v = f;
    }

    Entity (DTO dto) {
        this(new Value(dto));
    }

    // ...
}