Reputation: 1900
Not quite sure how to approach this problem regarding DDD.
Say you have 2 domains:
Product
domain which is responsible for creating new and managing existing Products
which a person has created. Product Aggregate Root
Store
domain which is responsible for assigning all created Products
to a given Store
to be sold, and other stuff. But the Store
can also create new Products
which will be assigned to themselves but also available for other Stores
so that they can assign the Product
to themselves. Store Aggregate Root
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
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:
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
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