让我们说,我们有一个总的根本实体的类型令,涉及客户和订单行。当我想到了一个实体的更自然的概念化为不被定义没有Id。一个以没有Id似乎是更好的代表作了请求于一个订单。

添加了一个储存库中,我通常看到人们的实例以没有Id然后有储存库完成的对象:

class OrderRepository
{
    void Add(Order order)
    {
        // Insert order into db and populate Id of new order
    }
}

我喜欢这个方法是,添加了一个实例,一个OrderRepository.这使得有很大的意义。然而,为了实例并没有身份证,并在该范围内消费的仓库,它仍然是没有意义我,一个以没有Id。我可以定义OrderRequest是一个实例以及增加,为储存库,但是这感觉就像导出一个苹果从橙色,然后将它添加到名单的橘子。

或者,我们也看到这种方法:

class OrderRepository
{
    Order AddOrder(Customer customer)
        // It might be better to call this CreateOrder
    {
        // Insert record into db and return a new instance of Order
    }
}

我喜欢这个方法是,单是不确定没有身份证件。储存库可以创建数据库记录和收集所有需要的领域之前创建和返回的一个实例。什么味道这是事实,你从来没有真正的实例添加一个秩序的储存库。

无论哪种方式工作,所以我的问题是:我要活的一个的这两种解释,或是否有一个最好的实践模式插入?

我发现这个的答案是相似的,但是对于价值的对象:我应该如何增加对象到一个收集维持的根聚集.当它涉及到一个值的对象是没有的混乱,但是我的问题涉及一个实体与敏感器从外部来源(自动生成的数据库Id)。

有帮助吗?

解决方案

我想到开始执行第二种方法。它不仅似乎是反直觉的,它还违反了几个很好的设计原则,例如 命令查询分离原则上的少惊喜.

剩下的选择取决于该领域的逻辑。如果域从逻辑上讲,一个以没有ID是毫无意义的标识是一个需要不变的顺序,我们必须型的这样:

public class Order
{
    private readonly int id;

    public Order(int id)
    {
        // consider a Guard Clause here if you have constraints on the ID
        this.id = id;
    }
}

注意到,通过标记的 idreadonly 我们已经做了它的一个不变的。有没有办法我们可以改变它对于给定的顺序实例。这完全符合 域驱动的设计's 实体 模式。

你可以进一步执行域中的逻辑通过把保护条款成的构造,以防止ID从消极的或零。

现在你可能不知道这怎么可能会工作的自动生成的Id从一个数据库。好了,它不。

有没有好的方法,以确保所提供的ID是不是已经在使用。

这让你有两个选择:

  • 更改标识到Guid。这使得任何呼叫者提供一个独特的ID为一个新的秩序。然而,这需要你使用Guid作为数据库的钥匙。
  • 改变API,以便创建一个新的秩序不采取为目的,而是一个OrderRequest如你建议的-OrderRequest可能是几乎完全相同的顺序类,减去的身份证。

在许多情况下,创建一个新的秩序是一个商业运作需要的具体建模在任何情况下,这样我看不出有什么问题作出这一区分。虽然顺序和OrderRequest可以是语义上非常相似,他们甚至不需要相关类型的层次结构。

我甚至可能走这么远来说,它们 不应该 是相关的,因为OrderRequest是 值的对象 而便是一个 实体.

如果采取这种办法,AddOrder方法必须返回一个以实例(或至少ID),因为否则我们不可能知道的ID了我们只是创建。这导致我们回到采用情况违反这就是为什么我倾向于 喜欢Guid实体Id.

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top