哪个类应该负责为实体创建ID?

时间:2018-02-12 17:54:27

标签: c# domain-driven-design

我在跟随问题时苦苦挣扎。让我们说我想管理项目中的依赖项,因此我的域名不依赖于任何外部内容 - 在存储库中的这个问题上。在此示例中,我们说我的域位于project.Domain

为此,我在project.Domain中为我的存储库声明了接口,我在project.Infrastructure中实现了该接口。阅读Vernon的DDD Red Book我注意到,他建议为聚合创建新ID的方法应放在以下存储库中:

public class EntityRepository
{
    public EntityId NextIdentity()
    {
        // create new instance of EntityId
    }
 }

这个EntityId对象内部是GUID,但我想明确建模我的ID,这就是为什么我不使用普通GUID。我也知道我可以完全跳过这个问题并在数据库端生成GUID,但是为了这个论点,让我们假设我真的想在我的应用程序中生成它。

现在我只是想 - 这个方法有没有特定的理由放在Vernon建议的存储库中,或者我可以实现身份创建,例如在实体内部,如

public class Entity
{
    public static EntityId NextIdentity()
    {
        // create new instance of EntityId
    }
 }

2 个答案:

答案 0 :(得分:2)

你可以将它放在存储库中,正如Vernon所说,另一个想法是将工厂放置在创建标识符的基础实体的构造函数中。通过这种方式,您甚至可以在与存储库交互之前拥有标识符,并且可以根据ID生成策略定义实现。存储库可能包含与某些内容的连接,例如Web服务或数据库,这些内容可能成本高昂且不可用。

有很好的策略(especially with GUID)可以很好地处理标识符。这也使您的应用程序完全独立于外部世界。

如果需要,您还可以在整个应用程序中使用不同的标识符类型。

例如。

getContext().getContentResolver().notifyChange(uri, null);

答案 1 :(得分:1)

是的,您可以绕过对存储库的调用,只需在实体上生成标识。然而,问题是您已经打破了存储库背后的核心思想:将与实体存储相关的所有内容与实体本身隔离开来。

我想说将NextIdentity方法保存在资源库中,并且仍然使用它,即使你只是生成GUID的客户端。好处是,在某些将来您想要更改身份标识的方式,您可以通过存储库支持。然而,如果您直接在实体上使用该方法,那么您将不得不稍后重构以支持此类更改。

此外,请考虑在测试等情况下使用不同存储库的情况。即。您可能希望生成具有相同ID的两个身份并执行冲突测试或“这样做会失败”。拥有一个存储库来处理这一代,使您有机会以这种方式获得创造性,而无需制作完全独特的测试用例,这些测试用例不会模仿实际的生产调用。

TLDR;将它保存在存储库中,即使您的标识符可以是客户端生成的。