Our team have been debating approaches to integrating external or third party systems when using DDD. The literature is extensive, but sometimes contradictory. Just like a UL helps us better understand and communicate about the domain, we wanted to do a better job of defining the different approaches, and when we might use each? We are not experts, so would be interested in any insights or feedback the community might have, and confirmation we are on the right track.
When integrating with a third-party technology, we identified three different approaches we have used in the past: Adapters (specifically in regards to the Ports & Adapters Pattern), Anti-Corruption Layer and Bounded Contexts.
Acknowledging that there is overlap between each concept, we defined the following team guidelines:
- An external system is always a separate bounded context — by its nature, the solution will use a different language to that of our core domain.
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.
Does anyone have any constructive feedback or critical ideas that they think would help improve our definitions. Or spots something that is incorrect or problematic?