我目前正在尝试在电子商务应用程序上实现 DDD。这是一个使用 ntier 架构的现有应用程序。我正在一步一步地尝试为产品生成域对象和域逻辑,但我在实现过程中遇到了一些问题。
首先,对于上下文,产品是从现有的表映射而来的,该表具有实体框架 orm 的一对一持久性模型。有问题的表是“产品”、“变体”、“选项”和“实例”。
变体是产品的一系列特征,例如尺寸或材料;
选项属于变体并确定其中的选择,例如尺寸:XL、L 等。对于更昂贵的选项,它们有价格修正。
实例是每个变体中一个选项的独特组合,进而生成特定的价格/SKU 和其他值。 `
public class Product
{
public Guid Id { get; private set; }
public string Title { get; private set; }
public List<Variant> Variants { get; private set; }
}
public class Variant
{
public Guid Id { get; private set; }
public Guid ProductId { get; private set; }
public string Title { get; private set; }
public List<Option> Options { get; private set; }
}
public class Option
{
public Guid Id { get; private set; }
public Guid VariantId { get; private set; }
public string Name { get; private set; }
public decimal PriceModifier { get; private set; }
// ... constructor, methods, etc.
}
public class Instance
{
public string Sku{ get; private set; }
public decimal Price{ get; private set; }
公共列表<
其次,实际问题:
持久化在基础设施层处理自己的模型。这是通过每个数据库集的存储库来完成的。在某些情况下,会在存储库中启动事务以确保不会完成部分更新。这是在更新产品详细信息(标题等)和修改选项价格时完成的,因为它必须使用新价格重新生成实例。
在产品类中,我有一个私有变体列表,我只能通过调用公共函数来添加、删除或更新某些属性来修改它。 变体也是如此,所有属性都不能直接设置。
当我从前端获得更新以更新变体时,到目前为止我会收到变体列表,并覆盖数据库中的所有内容。 对于 DDD,这有点棘手,因为我首先必须获取产品,在其上调用 crud 函数,而这又会在 Variants 上调用 crud 函数,依此类推。虽然这确保我的产品处于有效状态并且所有更改都正确执行,但我无法理解如何将该逻辑映射到存储库更改。产品是否应该有权访问自身的存储库并向基础设施层发送命令?
我是否应该验证我的更新模型并调用存储库而不通过产品域类中的 CRUD 函数?
我有点困惑 DDD 如何与存储库模式交互,尤其是它如何处理更复杂的类上的多个更新。
我想你需要重新考虑你的设计。
Product
可以视为 AggregateRoot
。据我理解你的问题, Variants
和 Options
可以被视为值对象。因此,对 Variants
或 Options
的任何更新都应通过 Product(AggregateRoot)
进行,以确保您的产品处于有效状态。因为现在它是你的一致性边界。
您可以将
repository
替换为 Product
。如果您将 Product
视为 AggregateRoot
,那么您必须将(根实体及其所有子实体)作为一个整体进行持久化。因为 Aggregate
是一致性边界。