DDD
Domain Services
Modeling
Java
Tactical DDD
Domain services are useful when important domain behavior does not belong naturally to one entity or value object.
DDD encourages rich domain objects, but not every business rule fits neatly inside one entity. Some rules span multiple concepts or need domain logic that is still not just application orchestration. Domain services exist for those cases.
Why This Topic Matters
Why it matters in real Java systems
Fraud scoring, cross-order eligibility checks, or shipment promise calculations may involve multiple domain concepts. Putting that logic in a controller is wrong. Putting it arbitrarily inside one entity may also be wrong. Domain services create a legitimate home for such behavior.
Core Explanation
The main design idea
A domain service expresses domain logic that does not sit naturally on one entity or value object. It should still use domain language and remain focused on business rules, not technical orchestration. That distinction is what separates it from an application service.
If a service mostly coordinates repositories, gateways, transactions, and notifications, it is probably an application service. If it mainly expresses business policy spanning several domain concepts, it may be a domain service.
Concept Breakdown
Key ideas to keep in mind
Concept
Good fit
Business logic spanning multiple domain objects without a natural single owner.
Concept
Bad fit
Workflow coordination and infrastructure access that belong in the application layer.
Concept
Main discipline
Keep the service in domain language, not framework or orchestration language.
Decision hint
Decision hint
Ask this: is the logic mainly about business meaning, or mainly about coordinating a use case? If it is about meaning, a domain service may fit. If it is about coordination, it is likely an application service.
Java Example
Java example in the Order Management domain
Java example: a domain service for shipment promise calculation
package org.javaomnibus.ecommerce.domain;
public final class ShipmentPromiseService {
public ShipmentPromise calculate(Order order, InventorySnapshot inventorySnapshot) {
if (inventorySnapshot.isAvailable(order)) {
return ShipmentPromise.standard();
}
return ShipmentPromise.delayed();
}
}
Code Walkthrough
Step by step
- The logic is business-oriented and expressed in domain terms.
- It spans multiple concepts but does not look like workflow orchestration.
- That makes a domain service a reasonable home.
- The difference from an application service is one of responsibility, not just naming.
Real-World Usage
Where this helps in practice
- Policy calculations spanning multiple aggregates or domain concepts
- Rules that do not belong to controllers or application orchestration
- Keeping rich domain logic out of generic helper classes
Trade-Offs
Trade-offs and when to be careful
- Domain services are useful, but they can become dumping grounds if the team avoids hard modeling decisions.
- Too many domain services may indicate the entities are too weak or the boundaries are unclear.
Common Mistakes
Frequent mistakes to watch for
- Putting application orchestration into a class called a domain service
- Using domain services as a default home for all business logic
- Keeping the service full of infrastructure calls and framework concerns
- Ignoring the possibility that a value object or aggregate should own the rule instead
Related Pages
Related concepts
What To Read Next