External call in domain layer? (in technical domain)

1,751 views
Skip to first unread message

Radek Kysely

unread,
Jan 10, 2021, 6:57:14 PM1/10/21
to DDD/CQRS
Hi everyone,

I'm currently learning DDD on my side project. The domain is quite technical, I'd name it “webhook management & delivery”. It's a simple app that does webhook delivery and related stuff (subscription management, queues, retries, reporting, etc).

Generally it's been going fine, however the heart of the webhook delivery is the actual HTTP call made to some remote endpoint.

Now I'm at crossroads on how to approach this. Making the HTTP call sounds like a core domain behavior that belongs to the domain layer (the outcome state of DeliveryAttempt entity depends on the result of the call); however it's an impurity.

I tried abstracting to HttpRequest and HttpResponse value objects that would be used to evaluate the outcome of DeliveryAttempt entity, but that felt unnatural, especially when dealing with such a core behavior.
Now I'm at the solution that makes the entity behavior depend on the HttpRequestService interface in domain layer, while the implementation of making the call resides in infra.

Can you please give me your view on this?

Thanks!
Radek

Tomas P.

unread,
Jan 11, 2021, 1:11:09 PM1/11/21
to ddd...@googlegroups.com
Hi Radek,

If I understand you correctly then my view is that you should have something that you call HttpService, I would maybe call it HttpClient that is injected into the domain object and doing the actual HTTP call. Having it in the infra layer sounds good to me. 
Injecting such a client/service allows you to test the Domain without doing the actual HTTP call.

Best
Tomas

--
You received this message because you are subscribed to the Google Groups "DDD/CQRS" group.
To unsubscribe from this group and stop receiving emails from it, send an email to dddcqrs+u...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/dddcqrs/c62f1230-8a3a-41c3-b4ee-4e49aa7c4d16n%40googlegroups.com.

Steven Harrison

unread,
Jan 11, 2021, 2:42:28 PM1/11/21
to DDD/CQRS
Hi Radek,

To add my two cents (very much a learner myself and so definitely no claims to be an expert) but ultimately I wouldn't get too hung up on it. DDD is about getting your domain's design and UL right, and building strong collaborative partnerships. 

I spent so long trying to get all the tactical patterns "right", until I realised I was missing the forest from the trees. And everyone has a different opinion. (If I use Tomas' answer as an example, for every person who proposes that approach — and it seems perfectly valid to me — there will be someone else saying you should never inject a service into an entity).

My ahah moment came when I dived more deeply into Ports & Adapters. And realised its as simple as just making sure you're using interfaces when it comes to your primary and secondary adapters. How you choose to do that is just implementation. Code can always be refactored. Use as much or as little of the DD tactical patterns as you need. 

If it's helpful, we came up with some general guidance on how we implement interactions with external systems. These are not authoritative in any way, and as I said, everyone will likely have another opinion. They help us with consistency though.

When deciding how to integrate, use the following guidance:

  • Adapter: When the technology or interface with the external or third-party system is relatively stable, and any data translation required is minimal, or automated, use a basic port and adapter. If the service is integral to the domain model, provide an interface in the domain (as a domain service). Otherwise call directly from the Application layer. This is analogous to what is sometimes referred to as the infrastructure layer. Also referred to as a gateway. Examples include Repositories, Payment Gateways etc

  • Anti-corruption Layer: If the translation required is more complex in nature, or there is a high level of impedance between your context, and the third-party service, implement an ACL in your bounded context. This will include Adapter(s), and specialised Translation services for performing the complicated data transpositions needed. The ACL may provide a facade to set of more complex services provided by the external system. All communication with the ACL happens in the language of the bounded context. The ACL should limit itself to data translations.

  • Bounded Contexts: If you are looking to expand on the functionality of the third party service then create your own bounded context that wraps the external system, and adds to the feature set. Communication with this bounded context can still happen via an adapter or ACL. Or integration may now be achieved through messaging — your new bounded context can have its own adapter for publishing and consuming messages to and from other contexts.

Wolfgang Klinger

unread,
Jan 11, 2021, 8:45:10 PM1/11/21
to DDD/CQRS
Hi,

making HTTP calls is imho infrastructure concern. Use interfaces (contract) in your domain layer and put the actual implementation into infrastructure layer.
Then you can inject the necessary service into the domain method, that uses it.


Kind regards,
Wolfgang
Reply all
Reply to author
Forward
0 new messages