Saturday, 7 December 2013

Domain Services - representing external dependencies in the Domain

For the most of us who start learning DDD, Domain Services seem to be a strange beast at first. The general definitions says that logic that "falls between" entities should find its place in a Domain Service. Simple as it sounds, in concrete situations it can be difficult to decide where to put a piece of logic. In the entity or create a service? In this post I'd like to show a different, but very frequent use of domain services. This is the manifestation of external dependencies in the domain. Let's see an example for not being so abstract. Imagine we are developing a military application comprising multiple, distributed components. Our task is develop the component that receives an encrypted message from the enemy, decodes it, then sends the decrypted message to the headquarters. Physically there are 3 components in the system, one that processes the decrypted message (headquarters), one that actually does the decrypting, and our component in-between. They are communicating via web-services. Our domain could look like

interface EncryptedMessage  { ... }
interface DecryptedMessage  { ... }
// domain service representing the HeadQuarter component in the system
interface HeadQuarter {
   void send(DecryptedMessage decryptedMessage);
}
// domain service representing the CodeBreaker component in the system
interface CodeBreaker {
  DecryptedMessage breakIt(EncryptedMessage encryptedMessage);   
}
//the heart of our simple domain
class EnemyMessageCatcher {
  private HeadQuarter headQuarter;
  private CodeBreaker codeBreaker;
  void captureDecryptAndForward(EncryptedMessage encryptedMessage) {
    DecryptedMessage decryptedMessage = codeBreaker.breakIt(encryptedMessage);
    headquarter.send(decryptedMessage);
}
//infrastructure layer
class WSBasedHeadQuarter implements HeadQuarter { //calling some webservice }
class WSBasedCodeBreaker implements CodeBreaker { //calling some webservice }
}


Both the HeadQuarter and the CodeBreaker are domain services. Although our domain knows nothing about how these functionalities are implemented (whether they are in other physical components, or just in simple objects), it still knows about the concept, that there is a HeadQuarter who needs to be notified and there is a CodeBreaker that can decrypt the enemy's messages. That's why the interface(=concept) is in the Domain and the implementation(=the details) is in the infrastructure. Using Hexagonal Architecture-terminology, the domain service (interface) is the port, and the implementation is the adapter.
The DDD-savvy reader can notice, that the Repository pattern is actually an ordinary domain service. It represents the concept of storing and retrieving objects in the domain, and hides away how it's done exactly. I suppose the only reason for it being a separate pattern is simply that most application has to deal with persistence.

No comments :

Post a Comment