DDD处理执行相同操作的2个域

时间:2016-03-07 21:46:56

标签: domain-driven-design aggregateroot bounded-contexts

不太确定如何解决有关DDD的问题。

假设您有2个域:

  • Product域,负责创建新人并管理某人创建的现有ProductsProduct Aggregate Root
  • Store域,负责将所有已创建的Products分配给要销售的给定Store,以及其他内容。但Store也可以创建新的Products,这些Stores将分配给自己,但也可用于其他Product,以便他们可以将Store Aggregate Root分配给自己。 Product

Store可以存在而不属于StoreProducts可以存在而不会有任何Person(我知道这没有意义,但这只是我正在研究atm的复杂解决方案的一个简单例子。 )

因此当Products进入系统时,它们可以从两端开始。他们可以先创建新的Store,也可以先添加新的Store

这是复杂的地方,当他们创建新的Products时,他们可以选择添加现有的Product,或者他们可以创建新的Store并将其添加到Store

您如何处理此用例。是CreateNewProductProduct有行为,它负责设置新的Store,然后将其添加到Product。或者您只是在Store域之外的Product域外创建新的Store,并告诉AddProduct AddExistingProduct / {{1} }?

更新:此类内容适合作为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;
    }
}

2 个答案:

答案 0 :(得分:1)

这个业务问题很常见。你肯定能找到一些关于DDD的电子商务系统的例子。

典型情况是您尚未完成UL的开发。如果您与领域专家讨论商店(我不会将其标记为代码,因为我在谈论UL条款,而不是类),您可以发现商店只关心产品可用性,而不关心产品本身。

通常,属于产品目录的产品与可用性几乎没有关系。它可能有一般描述,制造商详细信息,原产国,图片,包装尺寸和重量等。

然而,产品可用性具有可用性,即可用产品的数量。它可能有一些额外的细节,例如保留项目的数量,预计到达项目等等。

事实上,这两个概念,尽管它们相当不同,但通常被领域专家称为“产品”。这是两个独立的有界上下文的典型示例。

只要在两个不同的有界上下文(和实际位置)中有两个不同的名为Product的东西,您就需要保持它们同步。这通常通过在有界上下文之外发布域事件并通过在那里订阅这些事件并在有界上下文中执行内部域命令处理来更新另一方来完成。

答案 1 :(得分:1)

您需要两个域相互通信。您可以使用各种方法进行通信,但一种常见方法是使用REST API。在您的商店域中,您需要能够通信或知道如何与API通信的内容。我通常将这些实现为包装api调用的服务。该服务将能够理解您的域无处不在的语言,并将其转换为API命令。您可以使用域事件来监听产品何时创建,然后您可以将商店与产品关联,或者您可以实现某种轮询机制。

请求了一个例子,所以这里是:

  

从UI调用(可能来自控制器)

     

StoreService.CreateStore(storeName: String, newProduct : StoreProduct)   您可以传入基元来表示新产品。这使您可以创建新产品而无需为其创建新类。您随后在域和UI层之间不需要共享的基础结构类或转换器。

     

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
       }

要点的主要内容:

  1. 使用工厂创建聚合实体(在此状态下,它没有被保留)。
  2. 您需要一个repo来序列化并将新商店保存到您的数据存储中。
  3. productApiClient将在您的域模型和对productApi的请求之间进行转换。它知道如何在给定域实体的情况下生成Api请求(例如,如果是REST)。
  4. ProductApiClient将从Api响应中返回域实体。
  5. 使用商店实体将新产品添加到商店。
  6. 您使用repo
  7. 保留商店
  8. 如果对api的调用非常耗时,您可以选择更加异步的方法。
  9. 这个例子说明了DDD的力量和关注点的分离。根据项目的规模和要求,这可能过于繁琐,因此符合您的需求,技能和要求。