Design Patterns – How to Abstract External Service Operations

Architecturedesign-patternsdomain-driven-design

I'm creating a system using some DDD principles and I'm stuck with a problem.

To give a bit more of context on what I'm trying to do, let me first describe what the system is about:

The ideia is to allow an user of an specific kind of service to be able to integrate and test many of these services without integrating his system with all of them.

To do that the user would integrate with my system, which acts as a gateway, integrating with all those services.

Now let me explain the problem:

For every service that is integrated there is an API implementation that is very specific (some use JSON, others XML) and for that reason these implementations are used as separated dependencies (projects).

In the domain layer, there is an entity named ExternalService, this entity represents a service integration that is supported.

Lets say the kind of service we are talking about here is a SMS system that sends messages to a phone number.

So we have an api implementation that integrates with the external service:

class XYZSMSProviderApi {
    public void sendMessage(String phone) {...}
}

And we have the entity ExternalService with the XYZ service data (this data is persisted in a database):

class ExternalService {
    public String name = "XYZ";
}

The problem is, who should be responsible for calling the sendMessage method of the XYZSMSProviderApi class?

Should I inject the API object in the entity and then have a method to do the actual message sending in the entity?

Best Answer

Should I inject the API object in the entity and then have a method to do the actual message sending in the entity?

Probably not. The usual idiom is that the domain model is responsible for the integrity of its own state/data, and nothing else. Integration with external services is an application concern, not a domain concern.

In DDD terms, if ExternalService("XYZ") is an aggregate in the domain, then the code within that entity is primarily about the business invariant that is to be enforced by that piece of the domain. Other concerns - which is to say, what do you do with the data now that you can be sure that it satisfies all of your business rules - live somewhere else.

So the application queries the aggregate to get the state that it needs, and the actual message sending would be in the application itself.