【问题标题】:DDD: should entities contain or reference other entities?DDD:实体是否应该包含或引用其他实体?
【发布时间】:2023-02-23 06:46:26
【问题描述】:

假设我有两个实体:CompanyProduct
它们具有以下属性。

Company Product
Id Id
Name Name
MarketCap Category
Geography Price

以下是一些额外的事实:

  • 一家公司有数百万种产品。
  • 产品离不开公司。

我要支持的核心端点是:

  • 获取特定类别的所有产品(不需要公司信息)
  • 获取所有公司(不需要产品信息)
  • 获取一家公司的所有产品
  • 获取一个产品类别的所有公司

我可以像这样模拟实体的关系:

方法一

// Company
type Company struct {
Id int
Name string
MarketCap int
Geography string
ProductIds []int
}

// Product
type Product struct {
Id int
Name int
Category string
Price int
CompanyId int
}

或者我可以将其建模如下:

方法二

// Company
type Company struct {
Id int
Name string
MarketCap int
Geography string
Products []Product
}

// Product
type Product struct {
Id int
Name int
Category string
Price int
Company Company
}

正如reddit post 中所讨论的那样,方法 2 在某种意义上更多地遵循 DDD 的哲学,即领域模型不应该关心存储实现细节。但是,如果我查看我将如何使用我的 api 端点中的数据,我就会意识到某些端点将变得多么低效。

假设我遵循方法 2 并有一个端点 Get list of all companies。 为了重新创建公司实体,我必须在公司和产品表之间进行连接。每个公司对象将包含数百万种产品。当然,我不会在最终的 API 响应中添加每个公司的所有产品,但我至少需要从数据库中获取所有产品以创建一个有效的公司实体对象。如果我遵循方法 1,我就不必执行连接操作,因为通过单独的连接表(companyID、productID)获取 ProductIds 更便宜。

问题

我什么时候应该只用 id 建模一对多或多对多关系,什么时候应该在域层上用嵌套层次结构建模?

【问题讨论】:

    标签: domain-driven-design


    【解决方案1】:

    这两种方法都不遵循 DDD 概念。

    DDD 是一种设计概念,它指出您应该创建一个代码单元(称为域),其中包含与业务概念建模相关的所有代码,以及与之关联的业务规则/约束。应用程序中此代码的目的是检测并拒绝违反业务约束的操作。域单元仅在状态更改用例中有用:由于只读用例不能更改系统状态,因此它们不能违反业务约束。

    在您的示例中,您只声明只读用例。在这种情况下,您不应该使用域层。当使用经典的表示-域-持久层架构时,只读用例通常采用“中介”模式,类似于存储库,但接口在表示层,实现在持久层。您不需要通过中间模型,因此可以节省大量计算能力。它还允许使用映射库并简化过滤、排序和分页结果的实施。

    此外,领域层预计是持久性不可知.一个常见的错误是尝试像数据库一样对您的业务模型进行建模。特别是你不应该试图规范化一个领域模型,也不应该试图设计一个单一的统一领域模型。领域模型应该分成大小合理、独立的业务规则和用例块,称为上下文:产品管理,公司管理, ... 每个上下文都应该有它的模型,它应该尽可能小和简单。

    在领域层,关系是应该通过 id 还是通过引用建模,取决于您是否对关系有业务规则约束。例如,如果 productscompanies 是您可以不受任何限制地关联的实体,您可能希望使用方法 1,因为它更简单。您甚至可以删除 Company.porductIds。如果您的业务规则在两个实体之间使用数据,例如:product.price <= company.marketCap 的总和,您可能想要编写类似于方法 2 的内容。实际实现会有所不同,具体取决于您是否希望在相同的上下文中使用 productscompanies。否则,该模型将更加复杂,您将需要研究一个更高级的主题,称为语境合作.

    【讨论】:

      猜你喜欢
      • 2020-02-19
      • 2020-01-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-06-10
      相关资源
      最近更新 更多