I am currently in the process of creating a Proof of Concept for a product/party administration system, based on the principles of DDD. One of the requirements is that the party data (customer, reseller) will be stored in a CRM on the web and the product specific data will be stored in a SQL database on premise (see below).
CRM System (Web Based)
Customer (contains name, address, email, contact preference etc) Reseller (contains name, address, active status)Product System (On Premise)
BaseProduct (defines a vanilla product) ResellerProduct (defines a customisation of a base product which will be sold by the reseller) CustomerProduct (defines a product which the customer as registered).I have been con开发者_如何学JAVAducting a lot of research into the different approaches of how I could implement the solution, but am struggling to make sense of all the concepts and how they apply to my problem.
I started out by splitting the areas into 2 different bounded contexts, Party and Product. I defined domain models for each of these contexts, and where entities referenced concepts in the other model I left these as simple Guid Ids (i.e. CustomerProduct in the product domain would have a CustomerRef value of the related Guid).
I then implemented a Party infrastructure implementation which used API calls to the web CRM and a Product infrastructure implementation which used NHibernate. For each of these I implemented a UnitOfWork so I could control the transaction process in each context. The application layer would have the two contexts injected at runtime and use them.
For Example:
- ApplicationService.RegisterNewProduct(customerId, ProductId)
- Start the transaction of each unit of work (PartyUnitOfWork.Begin(), ProductUnitOfWork.Begin())
- Use the repositories for each context to find the relevant domain objects (Party.Customer.Find(Id), Product.ResellerProduct.Find(Id))
- Perform logic to determine if customer is eligible, product is valid etc.
- Create a new CustomerProduct and save to the product System
- Commit each contexts UnitOfWork
I then started to explore bounded contexts a bit further and was thinking about refactoring the app so that each context had a limited representation of concepts from the other, but only specific to that context. i.e. In the Product context I would have a customer entity, which had an Id, Name and active status but maybe not contact preferences etc. I would then use DomainEvents to coordinate activities between the different systems to keep their data up to date (i.e. If a new customer was created in the CRM system an event would be raised and handled by the Product system to update its representation of customer). Therefore the above example would change so only the Product context was used.
To confuse matters further, say the ‘RegisterNewProduct’ call also created a new Customer, would I created the customer in the Product system and raise a ‘NewCustomer’ event which would be handled by the Party system?
I would be interested to gather peoples comments on these ideas?
Besides my comment/question, there is fundamental issue with UnitOfWork approach you described. You'll run into a whole class of problems with one of the units committed and one failed. You will end up with a distributed transaction spanning two context.
A better (subjectively) approach to bounded contexts, if you really need to have more than one, is to have asynchronous, message based communication between them. You execute a command against an aggregate in one context and in the same transaction as persisting the changes to the DB, you publish (for example via NServiceBus or MassTransit) a message (an event) that something happened. The other context receives the message/event and reacts.
If you are a purist, you could use this approach to all inter-aggregate communication. By doing this you could remove the requirement of having a Unit of Work at all.
Does it make any sense?
精彩评论