From time to time, certain services which I am coding requires the functionality which another service has implemented. For example, in writing a service which returns the products bought by a user of a certain ID after a single transaction, I need the balance of the user's account after he has bought the product, so I invoke another services to fetch the data.
I can see some alternatives:
It's good to do so as you are reusing code.
Services should access their own repo to retrieve data for their operations
Services should be isolated from each other and only pertain to a single domain. In my example, I should have another layer, perhaps a ViewFactory, to invoke the services to fetch the relevant data
What are the commonly accepted norms on this issue?
Domain Services (or just Services in DDD) is used to perform domain operations and business rules. In his DDD book, Eric Evans describes a good Service in three characteristics: The operation relates to a domain concept that is not a natural part of an Entity or Value Object.
Are services part of domain model according to DDD? It is part of the domain layer. Domain services encapsulates domain logic that cannot be naturally modeled as value objects or entities.
Advantages of domain-driven design The most obvious advantage of DDD is that it gets everybody using the same language. When development teams use the same language as domain experts, it leads to software design that makes sense to the end user.
Yes, a domain service can access repositories.
Is your question about Domain Services, not application or infrastructure services? If so, DDD has no specific guidelines about isolating Domain Services from each other. Use your judgement and watch for SOLID violations. Also keep in mind that domain services are often misused and it makes sense to put more logic into Entities:
SERVICES should be used judiciously and not allowed to strip the ENTITIES and VALUE OBJECTS of all their behavior.
You can... if it fits your specific domain context and specially your use cases.
If you have several use cases that may span over several aggregate roots and their services you may want to use an internal application service or Domain EventHandler for keeping DRY principle intact.
But I sense that you don't want to use your UserRepository to load the user within your current service because you feel it should be focus on it's context.
My experience is that service methods granularity vary a lot. If you having your services working only against one (or few) repositories I assume your granularity is fine - which means you have SaveOrder, LoadOrder, DeleteOrder, LoadUser etc...
Large granularity is more use-case oriented and tries to match a use-case to service method (or two). But the OrderService may have methods like GetUserPurchaseHistory()
This method returns products with account balance in a response DTO object. If you don't want to use DTO's you will probably need two service calls two both return products and the User account balance. BUT Remember that Application Service Layer's primary task is to serve application client and their needs. If you do not dare to make your granularity large you may push the domain logic out to code-behind/controller/presenter/webservices. Then you have forced the knowledge of calling application service methods in the right order, to your clients.
I have in some projects successfully used DTO objects in complex dialog that demands data that spans over several aggregates. This will makes it easier for the GUI guys and the service api is more process oriented. And yes... I inject several repositories I need into ctor for my services. I have several services that share repositories (no strict 1-to-1 relationship). For less complex use-case I don't use DTO's. DTO's gives you overhead and cost time qand complexity during application maintenance. Though it can provide an anti-curruption layer but very rarely you get this benefit back.
I hope you understand the different ways you can go and the pros and cons. Just my view of your "cross-road"...
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With