Domain-driven design (DDD) is the concept that the structure and language of software code (class names, class methods, class variables) should match the business domain. For example, if a software processes loan applications, it might have classes such as LoanApplication and Customer, and methods such as AcceptOffer and Withdraw.
As the modelling covers a more extensive area of your business, split the models into very well-delimited contexts in which each model applies. Each of these contexts will have autonomy to evolve the models it owns.
Keeping each model within strict boundaries allows different modelling for business entities that look similar but have slightly different meaning on each of the contexts.
A model within these bounds may need to be shared to interact with external contexts. Use an Anti-Corruption Layer to prevent coupling both contexts.
When building Microservices, each service is a Bounded Context encapsulating an autonomous domain model and its external APIs play the role of an Anti-Corruption Layer.
Business specialists and other members of the team (both technical and non-technical) should collaborate into creating a single, meaningful naming for the use cases, entities, actions and events modelling the business. Using a single, common language will align all parties and improve communication.
The Aggregate is a graph of related domain objects that can only be mutated in an atomic operation. The Aggregate is responsible for keeping the invariants of the model. It decides which mutations are allowed according to its business rules and current state.
It models a central concept in your system having a prominent domain object that gives name to it. We call that prominent domain object the Aggregate Root.
We can take the Shopping Cart application as an example. A Shopping Cart may contain different Items (or Products the user buys). An Item itself is a domain concept, but the Shopping Cart is the root domain concept. The Shopping Cart is the Aggregate Root and gives name to the Aggregate. We can simply talk about the Shopping Cart Aggregate.
All operations must pass through the Shopping Cart, so it can check its validity. You may add or remove an item, or change its quantity, you can checkout the cart. All those operations are atomic and sequential. It should not be allowed to change its content at the same time the cart is being checkout, nor it should be allowed to checkout an empty cart. The Shopping Cart Aggregate will act as the guardian of the model integrity ensuring that only valid mutations are allowed.
Sharing entities across Bounded Context's adds coupling since a change on the entity model affects the code consuming it. An Anti-Corruption Layer is a transformation mapping the external model (controlled by a third party bounded context) into an internal model that’s stable to the actual bounded context consuming the model.
Splitting your business domain model into Bounded Context's will provide some spatial decoupling. Then, you can use asynchronous communication between them to achieve some temporal decoupling. Implement that asynchronous communication using event-driven design.
In parallel, you can use Event Sourcing to model the Stateful Aggregate's on each context.
Both external event-driven modelling and Event Sourcing are a perfect match. You can use an Anti-Corruption Layer and directly publish the Domain events for cross-context consumption.
[book] Domain-Driven Design: Tackling Complexity in the Heart of Software — Eric Evans (Addison-Wesley Professional)
[book] Domain-Driven Design Distilled — Vaughn Vernon ( Addison-Wesley Professional)