DDD 处理执行相同操作的 2 个域
DDD dealing with 2 domains performing same actions
不太确定如何解决有关 DDD 的这个问题。
假设您有 2 个域:
- 一个
Product
域,负责创建一个人创建的新域和管理现有的 Products
。 Product Aggregate Root
- 一个
Store
域,负责将所有创建的 Products
分配给要出售的给定 Store
,以及其他内容。但是 Store
也可以创建新的 Products
,它将分配给自己,但也可用于其他 Stores
,以便他们可以将 Product
分配给自己。 Store Aggregate Root
A Product
可以不属于 Store
而存在。 Store
可以在没有任何 Products
的情况下存在(我知道这没有意义,但这只是我正在使用 atm 的复杂解决方案的一个简单示例。)
因此,当 Person
进入系统时,它们可以从任一端开始。他们可以从创建新的 Products
开始,也可以从添加新的 Store
开始。
这就是事情变得复杂的地方,当他们创建一个新的 Store
时,他们可以选择添加现有的 Products
或者他们可以创建一个新的 Product
并添加它到 Store
.
你如何处理这个用例。 Store
是否对 CreateNewProduct
有行为,它负责设置新的 Product
,然后将其添加到 Store
。或者您只是在 Store
域之外创建一个新的 Product
作为 Product
域的一部分,然后告诉 Store
到 AddProduct
/ AddExistingProduct
?
更新: 这样的东西是否适合 Domain Service
public class StoreProductService {
public Store CreateNewStoreProduct (Store store, string sku, string name, etc){
Product newProduct = ProductFactory.CreateNewProduct(sku, name, etc);
store.AddProduct(newProduct);
return store;
}
}
这个业务问题很常见。您肯定可以找到一些有关使用 DDD 的电子商务系统的示例。
典型的情况是您还没有完成 UL 的开发。如果您与您的领域专家讨论商店(我不会将其标记为代码,因为我在谈论 UL 术语,而不是 类),您会发现商店只关心产品可用性,而不关心产品本身.
通常,属于产品目录的产品与可用性关系不大。它可能有一般描述、制造商详细信息、原产国、图片、包装尺寸和重量等。
然而,Product Availability 具有可用性,即可用产品项目的数量。它可能有一些额外的细节,例如保留物品的数量、预计到达的物品等。
事实是,尽管这两个概念相当不同,但通常这两个概念都被领域专家称为 "Product"。这是两个独立限界上下文的典型示例。
一旦在两个不同的限界上下文(和物理位置)中有两个不同的东西被称为 Product,您就需要使它们保持同步。这通常是通过在限界上下文之外发布域事件并通过在那里订阅这些事件并在限界上下文中执行内部域命令处理来更新另一端来完成的。
您需要两个域相互通信。您可以使用各种方法进行通信,但一种常见的方法是使用 REST API。在您的 Store 域中,您需要能够与 API 通信或知道如何通信的东西。我通常将这些实现为包装 api 调用的服务。该服务将能够理解您的域通用语言并将其翻译成 API 命令。您可以使用领域事件来监听产品何时创建,然后您可以将商店与产品相关联,或者您可以实施某种轮询机制。
请求示例,所以这里是:
Call from UI (probably from a controller)
StoreService.CreateStore(storeName: String, newProduct : StoreProduct)
You could pass in primitives to represent the newproduct. This allows you to create a new product without the need for a new class for it. You subsequently don't need a shared infrastructure class or converter between your domain and UI layers.
StoreService
public StoreService
{
public StoreService(ProductApiClient productApiClient...)...
public void CreateStore(string StoreName, StoreProduct prod...)
{
var newStore = StoreFactory.Create(storeName);
//below might be better as an asynch call but for simplicity
//keeping it all synchronous
var newProd = productApiClient.CreateProduct(prod);
//check if product was created successfully, if so
newStore.Add(newProd);
//save
StoreRepo.Create(newStore);
//check if store was created successfully
}
这里的要点:
- 使用工厂创建您的聚合实体(在此状态下它尚未持久化)。
- 您需要一个存储库来序列化您的新存储并将其持久保存到您的数据存储中。
- 产品Api客户端将在您的域模型和对产品的请求之间进行转换Api。它知道如何在给定域实体的情况下生成 Api 请求(例如 REST)。
- 产品Api客户端将从Api响应中return一个域实体。
- 您使用商店实体将新产品添加到商店。
- 您使用存储库保存您的商店
- 如果 api 的调用很耗时,您可以选择更异步的方法。
此示例说明了 DDD 和关注点分离的强大功能。根据项目的大小和要求,这可能过于乏味,因此适合您的需要、技能和要求。
不太确定如何解决有关 DDD 的这个问题。
假设您有 2 个域:
- 一个
Product
域,负责创建一个人创建的新域和管理现有的Products
。Product Aggregate Root
- 一个
Store
域,负责将所有创建的Products
分配给要出售的给定Store
,以及其他内容。但是Store
也可以创建新的Products
,它将分配给自己,但也可用于其他Stores
,以便他们可以将Product
分配给自己。Store Aggregate Root
A Product
可以不属于 Store
而存在。 Store
可以在没有任何 Products
的情况下存在(我知道这没有意义,但这只是我正在使用 atm 的复杂解决方案的一个简单示例。)
因此,当 Person
进入系统时,它们可以从任一端开始。他们可以从创建新的 Products
开始,也可以从添加新的 Store
开始。
这就是事情变得复杂的地方,当他们创建一个新的 Store
时,他们可以选择添加现有的 Products
或者他们可以创建一个新的 Product
并添加它到 Store
.
你如何处理这个用例。 Store
是否对 CreateNewProduct
有行为,它负责设置新的 Product
,然后将其添加到 Store
。或者您只是在 Store
域之外创建一个新的 Product
作为 Product
域的一部分,然后告诉 Store
到 AddProduct
/ AddExistingProduct
?
更新: 这样的东西是否适合 Domain Service
public class StoreProductService {
public Store CreateNewStoreProduct (Store store, string sku, string name, etc){
Product newProduct = ProductFactory.CreateNewProduct(sku, name, etc);
store.AddProduct(newProduct);
return store;
}
}
这个业务问题很常见。您肯定可以找到一些有关使用 DDD 的电子商务系统的示例。
典型的情况是您还没有完成 UL 的开发。如果您与您的领域专家讨论商店(我不会将其标记为代码,因为我在谈论 UL 术语,而不是 类),您会发现商店只关心产品可用性,而不关心产品本身.
通常,属于产品目录的产品与可用性关系不大。它可能有一般描述、制造商详细信息、原产国、图片、包装尺寸和重量等。
然而,Product Availability 具有可用性,即可用产品项目的数量。它可能有一些额外的细节,例如保留物品的数量、预计到达的物品等。
事实是,尽管这两个概念相当不同,但通常这两个概念都被领域专家称为 "Product"。这是两个独立限界上下文的典型示例。
一旦在两个不同的限界上下文(和物理位置)中有两个不同的东西被称为 Product,您就需要使它们保持同步。这通常是通过在限界上下文之外发布域事件并通过在那里订阅这些事件并在限界上下文中执行内部域命令处理来更新另一端来完成的。
您需要两个域相互通信。您可以使用各种方法进行通信,但一种常见的方法是使用 REST API。在您的 Store 域中,您需要能够与 API 通信或知道如何通信的东西。我通常将这些实现为包装 api 调用的服务。该服务将能够理解您的域通用语言并将其翻译成 API 命令。您可以使用领域事件来监听产品何时创建,然后您可以将商店与产品相关联,或者您可以实施某种轮询机制。
请求示例,所以这里是:
Call from UI (probably from a controller)
StoreService.CreateStore(storeName: String, newProduct : StoreProduct)
You could pass in primitives to represent the newproduct. This allows you to create a new product without the need for a new class for it. You subsequently don't need a shared infrastructure class or converter between your domain and UI layers.StoreService
public StoreService { public StoreService(ProductApiClient productApiClient...)... public void CreateStore(string StoreName, StoreProduct prod...) { var newStore = StoreFactory.Create(storeName); //below might be better as an asynch call but for simplicity //keeping it all synchronous var newProd = productApiClient.CreateProduct(prod); //check if product was created successfully, if so newStore.Add(newProd); //save StoreRepo.Create(newStore); //check if store was created successfully }
这里的要点:
- 使用工厂创建您的聚合实体(在此状态下它尚未持久化)。
- 您需要一个存储库来序列化您的新存储并将其持久保存到您的数据存储中。
- 产品Api客户端将在您的域模型和对产品的请求之间进行转换Api。它知道如何在给定域实体的情况下生成 Api 请求(例如 REST)。
- 产品Api客户端将从Api响应中return一个域实体。
- 您使用商店实体将新产品添加到商店。
- 您使用存储库保存您的商店
- 如果 api 的调用很耗时,您可以选择更异步的方法。
此示例说明了 DDD 和关注点分离的强大功能。根据项目的大小和要求,这可能过于乏味,因此适合您的需要、技能和要求。