DDD domain services: what should a service class contain?
Asked Answered
F

2

6

In Domain Driven Design, domain services should contain operations that do not naturally belong inside an entity.

I've had the habit to create one service per entity and group some methods inside it (Organization entity and OrganizationService service).

But the more I think about it: OrganizationService doesn't mean anything, "Organization" is not a service, it's a thing.

So right now I have to add a Organization deep copy functionality that will duplicate a whole Organization aggregate, so I want to put it in a service.

Should I do: OrganizationService::copyOrganization(o)?

Or should I do: OrganizationCopyService::copyOrganization(o)?

More generally: is a "service" an abstract concept containing several operations, or is a service a concrete operation?

Edit: more examples given the first one wasn't that good:

  • StrategyService::apply()/cancel() or StrategyApplicationService::apply()/cancel()? ("Application" here is not related to the application layer ;)
  • CarService::wash() or CarWashingService::wash()?

In all these examples the most specific service name seems the most appropriate. After all, in real life, "car washing service" is something that makes sense. But I may end up with a lot of services...

*Note: this is not a question about opinions! This is a precise, answerable question about the Domain Driven Design methodology. I'm always weary of close votes when asking "should I", but there is a DDD way of doing things.*

Funnelform answered 19/7, 2013 at 12:20 Comment(4)
Why is the organization being cloned? The answer to that question might reveal a bit more about what the service is actually providing. I don't actually want to know - I'm just trying to elevate your thought process back into the domain...Posterior
@Posterior I see what you mean. But I'm afraid it's that simple: the user wants to "copy"/"duplicate" an existing organization because he want to create a new one looking a lot like the previous one. I welcome your thoughts on this though :)Funnelform
"the user wants to "copy"/"duplicate an existing..." -- Looks like the user has given you a solution to implement rather than a problem to solve! Could the real problem be that creating new organizations from scratch is too time consuming? In which case you are providing a service which expedites this process?Posterior
@Posterior I added more examples because the one I chose is not very good after all :/Funnelform
C
5

I think it's good if a domain service has only one method. But I don't think it is a rule like you must not have more than one method on a domain service or something. If the interface abstracts only one thing or one behaviour, it's certainly easy to maitain but the granularity of the domain service totally depends on your bounded context. Sometimes we focus on low coupling too much and neglect high cohesive.

Cheke answered 19/7, 2013 at 14:50 Comment(1)
+1 this is what I was trying to hint at in my comments. A good domain service may abstract more than one behaviour - but they should only abstract one problem.Posterior
P
1

This is a bit opinion based I wanted to add it as a comment but ran out space.

I believe that in this case it will make sense to group the methods into one a separate OrganizationFactory-service with different construction method.

   interface OrganizationFactory{
       Organization createOrganization();
       Organization createOrganizationCopy(Organization organization);
   }

I suppose it will be in accordance with information expert pattern and DRY principle - one class has all the information about specific object creation and I don't see any reason to repeat this logic in different places.

Nevertheless, an interesting thing is that in ddd definition of factory pattern

Shift the responsibility for creating instances of complex objects and AGGREGATES to a separate object, which may itself have no responsibility in the domain model but is still part of the domain design. Provide an interface that encapsulates all complex assembly and that does not require the client to reference the concrete classes of the objects being instantiated.

the word "object" is in a generic sense doesn't even have to be a separate class but can also be a factory method(I mean both the method of a class and the pattern factory method) - later Evans gives an example of the factory method of Brokerage Account that creates instances of Trade Order.

The book references to the family of GoF factory patterns and I do not think that there's a special DDD way of factory decomposition - the main points are that the object created is not half-baked and that the factory method should add as few dependecies as possible.

update DDD is not attached to any particular programming paradigm, while the question is about object-oriented decomposition, so again I don't think that DDD can provide any special recommendations on the number of methods per object.

Some folks use strange rules of thumb, but I believe that you can just go with High Cohesion principle and put methods with highly related responsibilities together. As this is a DDD question, so I suppose it's about domain services(i.e. not infrastructure services). I suppose that the services should be divided according to their responsibilities in the domain.

update 2 Anyway CarService can do CarService::wash()/ CarService::repaint() / CarService::diagnoseAirConditioningProblems() but it will be strange that CarWashingService will do CarWashingService::diagnoseAirConditioningProblems() it's like in Chomsky's generative grammar - some statements(sentences) in the language make sense, some don't. But if your sentence contains too much subjects(more than say 5-7) it also will be difficult to understand, even if it is valid sentence in language.

Prejudice answered 19/7, 2013 at 13:45 Comment(4)
I agree with every point you make, and I realize my example wasn't good. My question was more generic: should a service class realize only one operation, or is it OK to have a service class aggregate several operations. New example: StrategyService::apply()/cancel() or StrategyApplicationService::apply()/cancel()? Or CarService::wash() or CarWashingService::wash()?Funnelform
The number of objects is very subtle thing - C. Alexander in pattern Small parking lots cited some other study that showed that objects in a collection of 5-7 items(but no more) can still be grasped as individuals, so you don't have to restrict everything to one method per class. :-)Prejudice
I've updated the title of my question: let alone the number of methods, what is a service? Is it an action, like the word "service" in the real world? Or is it an abstract concept/name that aggregates actions? see my examples in the previous commentFunnelform
Now rereading the post I wonder why I didn't mention the UBIQUITOUS LANGUAGE pattern and that the methods should conform to it. Anyway there some ddd experts on SO who may add something more tangible.Prejudice

© 2022 - 2024 — McMap. All rights reserved.