At an equipment-rental company, a sales representative tells the customer that an excavator is booked. The warehouse sees only a request that it can still reject. Both situations have the same status in the application. When another request arrives for the same machine, a vocabulary problem has become two conflicting customer promises.
Domain-Driven Design, or DDD, develops a model with people who understand the work and uses that model in the software. Here the domain is equipment rental. The starting point is the difference between an intention, a reservation and a confirmed commitment, not a new set of folder names.
Explore a disputed case before drawing the database
Bring together sales, dispatch, warehouse staff and a developer. Take a specific case: the machine is needed tomorrow, the previous rental has been extended and the new customer has already paid a deposit. Who can promise availability? When is the machine removed from the available pool? What if it comes back damaged?
Check the answers against documents and the actual sequence of work. One expert may describe official procedure; another may explain the workaround their department relies on. The team needs to see both. It should not silently legitimise every workaround, but ignoring them can produce an unusable system.
If people disagree about the rule itself, the architect should not quietly choose company policy. Someone needs authority to make the business decision. Modelling exposes the disagreement; it does not replace responsibility for deciding when a customer commitment becomes binding within the product.
Shared language has to survive an action
Suppose “rental request” does not hold equipment, while “confirmed reservation” holds it for an agreed interval. These concepts should mean the same thing in discussion, interfaces, tests and the relevant code. This practice is described as Ubiquitous Language.
A glossary alone is not enough. Confirming a reservation should check the conditions, not merely update a status label. A new employee needs to understand the difference between requesting and confirming, and who can cancel each. Ambiguity will still generate phone calls even when class names are tidy.
Finance may understand a deposit as an amount received with refund conditions. Dispatch may only need to know whether a prerequisite is satisfied. They need not share one enormous object. A Bounded Context defines where a model has a consistent meaning; cooperation across boundaries needs an explicit agreement.
Turn a business rule into a real constraint
In this example, one machine must not have two confirmed reservations for overlapping periods. A condition that must remain true is called an invariant. Checking it only in a browser form is insufficient: requests can arrive through an integration or concurrently from different users.
A DDD aggregate defines a consistency boundary around related data. Choose that boundary for rules that must be protected together, not for every relationship in the company. The Azure Architecture Center's tactical DDD guide explains entities, value objects and aggregates.
Calling a class Aggregate does not prevent a race. Reservations still need a correct write mechanism: a transaction, version check, database constraint or another design appropriate to the rule. Microsoft's guidance on domain-model validation addresses responsibility for invariants. The actual implementation must be tested under concurrent use.
Boundaries can be wrong in either direction. Too small, and an important rule depends on an unsafe sequence of separate updates. Enclose the entire fleet, and unrelated reservations may contend unnecessarily. Refine the choice against real constraints and workload, not a preference for one impressive model.
The availability list may still lag behind. That is acceptable only with clear behaviour: final confirmation checks current state, and the customer sees a request rather than a promise until then. Model rejection too, so the interface does not present a preliminary estimate as secured equipment.
Spend modelling effort where rules warrant it
Not every part of the product is equally complex. Allocating equipment, extending rentals and arranging replacements after breakdowns may determine service quality. Those areas deserve detailed discussion. Editing a straightforward contact directory may need only ordinary forms and validation.
A particular machine keeps its identity when its name or condition changes. A rental interval or an amount with a currency can often be represented by its values. These distinctions can prevent mistakes without requiring every DDD pattern for every field.
DDD does not require microservices, event sourcing or separate read and write stores. Models can live within an existing application. Microsoft's domain-analysis guidance distinguishes strategic analysis from tactical design techniques. Deployment remains a separate decision.
The model changes when the business changes
Now the company allows selected customers to reserve equipment before paying a deposit. Does this apply to existing requests? Who approves exceptions? How do other systems recognise the changed state? Reinterpreting historical operations using today's rule may give the wrong product behaviour.
Capture the decision with examples and tests: confirmation without a deposit, extension into an occupied interval, a damaged return and cancellation after collection. A domain expert should understand the expected outcome without reading code. A developer should be able to show where the system enforces it.
Start with one rule that repeatedly causes rework or support cases. Clarify its meaning, identify its owner, change a limited part of the program and test the next comparable case. That shows whether the model helps rather than merely adding terminology. For rental, the test is concrete: customer, sales and warehouse agree on which equipment has actually been promised, and for how long.