Shane van Wyk
Shane van Wyk

Reputation: 1900

DDD dealing with 2 domains performing same actions

Not quite sure how to approach this problem regarding DDD.

Say you have 2 domains:

A Product can exist without belonging to a Store. A Store can exist without having any Products in it whatsoever (doesn't make sense I know, but this is just a simple example of a complex solution I'm working on atm.)

So when a Person comes along into the system, they can start at either end. They can start by creating new Products or they can start by adding a new Store.

Here is where it gets complicated, when they create a new Store, they are given the option to add existing Products or they can create a new Product and add it to the Store.

How do you deal with this use case. is the does the Store have a behavior to CreateNewProduct where it's responsible to setting up the new Product and then adding it to the Store. Or do you simply create a new Product outside the Store Domain as part of the Product domain, and tell the Store to AddProduct / AddExistingProduct?

UPDATE: Would something like this be appropriate as a 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;
    }
}

Upvotes: 1

Views: 950

Answers (2)

Louis
Louis

Reputation: 1241

You need the two domains to communicate with each other. You can communicate using various methods but one common way is to use a REST API. In your Store domain, you need something that communicates or knows how to communicate with the API. I have generally implemented these as a service that wraps api calls. The service will be able to understand your domain Ubiquitous language and will translate that into API commands. You can use domain events to possibly listen for when the product has been created and then you can associate the store with the product or you can implement some kind of polling mechanism.

An example was requested, so here goes:

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
       }

The main points to take from here:

  1. Create your aggregate entity using a factory (at this state it has not being persisted).
  2. You need a repo to serialize and persist your new store to your data store.
  3. productApiClient will translate between your domain model and a request to the productApi. It knows how to generate an Api request (if REST for example) given domain entities.
  4. ProductApiClient will return a domain entity from the Api Response.
  5. You add a new product to a store using the store entity.
  6. You persist your store using the repo
  7. You may choose to pick a more asynchronous approach if the call to the api is time consuming.

This example illustrates the power of DDD and the separation of concerns. Depending on the size of your project and your requirements, this might be overly tedious so fit it to your needs, skills and requirements.

Upvotes: 2

Alexey Zimarev
Alexey Zimarev

Reputation: 19600

This business problem is very common. You surely can find some of examples about eCommerce systems with DDD.

Typical situation is that you have not finished developing your UL. If you discuss the Store (I won't mark it as code since I am talking about UL terms, not classes) with your domain experts, you can find out that Store only cares about Product Availability, not the Product itself.

Typically, your Product that belongs to a Product Catalogue, has little to do with the availability. It might have general description, manufacturer details, country of origin, picture, package size and weight and so on.

Product Availability, however, has, well, the availability, i.e. count of available product items. It might have some extra details, for example a count of reserved items, expected to arrive items and so on.

The fact is that often both of these concepts, despite they are rather different, are referred by domain experts as "Product". This is a typical example of two separate Bounded Contexts.

As soon as you have two different things that are called Product in two different Bounded Contexts (and physical places), you will need to keep them in sync. This is usually done by publishing domain events outside of the Bounded Contexts and updating the other side by subscribing to these events there and doing internal domain command handling inside the Bounded Context.

Upvotes: 2

Related Questions