Our current O/RM tool doesn't really permit wealthy domain models, therefore we have to utilize anemic (DTO) organizations everywhere. It has labored fine, however i still have a problem with where you can put fundamental object-based business logic and calculated fields.
Our repository layer has the majority of the fundamental fetch/validate/save logic, even though service layer does many of the more complicated validation &lifier saving (since save procedures also do logging, checking of permissions, etc). The issue is where you can put code such as this:
Decimal CalculateTotal(LineItemEntity li) Cost
Decimal CalculateOrderTotal(OrderEntity order) return orderTotal
Let us return to fundamentals:
Services are available in 3 flavours: Domain Services, Application Services, and Infrastructure Services
- Domain Services : Encapsulates business logic that does not naturally fit inside a domain object. Inside your situation, all of the business logic.
- Application Services : Utilized by exterior customers to speak to the body
- Infrastructure Services : Accustomed to abstract technical concerns (e.g. MSMQ, email provider, etc)
This is when your computer data-access and consistency inspections go. In pure DDD, your Aggregate Roots would result in checking consistency (before persisting any objects). Inside your situation, you would employ inspections out of your Domain Services layer.
Suggested solution: Split your existing services apart
Make use of a new Domain Services layer to encapsulate all logic for the DTOs, as well as your consistency inspections too (using Specifications, maybe?).
Make use of the Application Service to reveal the required fetch techniques (
FetchOpenOrdersWithLines), which forward the demands for your Repository (and employ generics, as Jeremy recommended). You could also think about using Query Specifications to wrap your queries.
Out of your Repository, use Specifications inside your Domain Services layer to check on object consistency etc before persisting your objects.
You'll find supporting info in Evans' book:
- "Services and also the Isolated Domain Layer" (pg 106)
- "Specifications" (pg 224)
- "Query Specifications" (pg 229)
This is just what the service layer is perfect for - I have also seen programs where it's known as the BusinessLogic layer.
Fundamental essentials programs you will want to spend much of your time testing, and when they are in their own individual layer then mocking the repository layer ought to be straightforward.
The repository layer ought to be genericized whenever possible, therefore it is no appropriate spot for business logic that's individual to specific classes.