Domain Objects and Services

前端 未结 4 1200
鱼传尺愫
鱼传尺愫 2020-12-12 14:20

In this question someone replies \"You never let the domain object implementations call services by themselves!\". Is this statement a hard fast rule of DDD or does it depen

相关标签:
4条回答
  • 2020-12-12 14:30

    This is the Spreadsheet Conundrum: does the phone dial the phone number, or does the phone number dial itself on the phone?

    You might find Double Dispatch to be interesting reading, though overkill in your situation, I reckon.

    The Single Responsibility Principle is often at odds with the OO tenet of Tell, Don't Ask. My feeling on the subject has oscillated, and I have settled on the following conditions when logic should go into a domain object:

    • The logic should be domain logic, i.e. nothing like image.load() or image.save()
    • The logic shouldn't give the object more than "one reason" to change in the domain. This is a re-statement of the SRP.
    • The logic shouldn't be forced into the object. In other words, if you end up doing something like trying to calculate the sum of some property in a list of domain objects without using a getter, think twice.

    In your situation, I'd opt against putting the call to the service inside the entity object, mainly because the service doesn't seem like it is related to your domain, but more related to persistence. Domain objects should be coupled to domain concepts, and I don't think the service you gave qualifies.

    An example where I think calling a service in an entity might be acceptable would be if your application used a third-party workflow server to manage parts of its state. Essentially, this is the State Pattern with the states defined at run-time.

    I think it is acceptable to have domainObject.moveToNextState() (assuming this code "makes sense" in your ubiquitous language) call the service that talks to your server because the workflow server manages a part of the domain model.

    I'll add that DDD is very interested with following the language of the domain. Do you hear domain experts saying "A user image finds if its thumb print matches those in the XYZ vendor service"? Or do they say "The XYZ vendor service, given a thumb print, indicates whether that thumb print exists"? Go with the one that makes the most sense in your domain.

    Some more thoughts (I've thought about this issue a lot because it is central to design):

    • In the Evans DDD book, an Account entity has methods like credit(Amount), debit(Amount), transferTo(Account, Amount) and accrue(), but a FundsTransferService has a transfer(Account, Account, Amount) method. The transferTo method doesn't call any service, but merely handles the logic that involves Accounts, like crediting and debiting the right amounts.

      The FundsTransferService, in addition to co-ordination, has its own rules to check, rules that don't fit into Accounts. The exact amount to credit or debit might involve outside parties. This makes it awkward for transferTo to call the service.

    • For simple objects, like the UserImage, significant domain logic that can fit in the object itself might be scarce because it isn't, as far as I can tell, an Aggregate. Aggregates, I think, present more of an opportunity to house domain logic. The Account example is likely an Aggregate.
    0 讨论(0)
  • 2020-12-12 14:32

    If you allow an Entity Object to call a service it is performing two roles Data Object and Service Object. Generally, each object should have on responsibility, not only in implementation but also in usage.

    In your case, the lowly UserImage seems to be both an Image and a ThumbPrint Recognizer.

    0 讨论(0)
  • 2020-12-12 14:37

    I think it's better not to call repositories or services from entities or value objects, but sometimes it's necessary, for example, if an entity has to return other entity which should be loaded from database but it cannot navigate to it using object graph. Then dependency inversion principle comes to help, which means that entities and value objects depend on interfaces of services and repositories and not on implementations.

    0 讨论(0)
  • 2020-12-12 14:39

    One disadvantage I see is that allowing your domain object to call services may make it harder to serialize, or at least cause some issues after serializing it when someone on the other side calls its service method(s).

    0 讨论(0)
提交回复
热议问题