Anti-Corruption Layer
An anti-corruption layer protects your own model from concepts and structures of a foreign system. It translates in both directions and explicitly treats non-imageable states.
- TranslationForeign codes become shop states.
- Assignment ruleEach code has a fixed rule.
- Amendment bodyProvider changes affect only the ACL.
Context
Why this is important
If the shop takes over the codes of the provider unchecked, they migrate into the specialist logic. An adapter translates technically (protocol, format), the ACL translates meaning. Often it is inserted as an adapter behind a port, which is specified by the specialist model. The direction of technical dependencies deals with dependency inversion.
This building block explains semantic translation at a foreign border. For the direction of technical dependencies, see Dependency Inversion.
At a glance · Translation at the border
This is how ACL translates
The payment provider provides the codes APPROVED, DECLINED and PENDING_REVIEW. The shop uses its own states authorized, rejected and clarification is ongoing.
This is how you read the picture
- Translation APPROVED is authorized to amount and currency to monetary amount()49,90 EUR.
- Assignment rule The highlighted rule shows which provider code goes into which state.
- Amendment body In the case of v2, the field is called state; only the rules change, the result does not.
Payment service provider’s response
{
"status": "APPROVED",
"Quantity": 4990,
"currency": "EUR",
"Refresh": "pay_7Qx2",
"merchant_order": "B-1042"
}ACL · Assignment rules
status APPROVEDzustand: autorisiert(touches)status DECLINEDzustand: abgelehntstatus PENDING_REVIEWzustand: Klärung läuftanderer statustechnischer Klärungsfallamount + currencybetrag: Geldbetrag(49,90 EUR)(touches)refanbieterReferenz(touches)merchant_orderbestellung(touches)
Shop model payment
- Order
- B-1042
- Condition
- Authorised
- Amount
- Amount of money(s)49,90 EUR
- ProviderReference
- pay_7Qx2
Example data illustrative
Where do the codes go?
- CleanPayment providerSend the APPROVED
- UnprotectedACL at the borderis missing, nothing is translated
- Foreign conceptOrderworks with provider code APPROVED
- Foreign conceptInvoiceKnows the provider code
Yes, in order and invoiceProvider codes in the technical model
Benefits & limitations
Helps if:
- Terms or states of a third-party system deviate from their own domain and require a controlled translation.
- Changes to an unstable external contract need to be contained at a clear boundary.
Boundaries
- A translation layer has its own maintenance cost. Check whether external semantics actually threatens the local model and describe the relationship in a Context Map.
- A translation can pass on only what the external contract supplies. Missing information must be resolved in the API Contract.
In practice
- Capture foreign semantics and borderline cases. Collect formats, status values and error responses along with meaning. The result separates stable promises from unknown or ambiguous states.
- Determine your own contract and translation. Define internal terms and assignment from the external model. Connect the integration relationship with the Context map.
- Test the mapping against real variations. Cover known, missing and unknown fields and states. Use the API Contract to validate partner changes against the translation early.
Read the detailed explanation
An integration boundary receives external formats, statuses and errors and converts them into an internal representation. Business rules remain independent of a partner's historical codes or unsuitable terminology. A Context Map shows the relationship between models; API Contracts describes the observable exchange.
Translation must preserve meaning and explicitly handle ambiguous states or states the local model cannot represent. Renaming fields is insufficient when information is missing or several meanings collapse into one. The layer needs tests using representative data and a clear owner for changes to the external contract.
An adapter adjusts protocols and formats; a facade simplifies access to a system. An ACL goes further by translating the meaning of external terms into the local model. It is often implemented as an adapter behind a port defined by the domain model; Dependency Inversion explains the direction of this dependency.
Check your understanding
Test yourself in three stages
ReadingCheck in the picture
The provider sends PENDING_REVIEW. What is the condition of the payment in the shop model, and what happens to the order?
View the solution with justification
The state is clarification is ongoing. The order will not continue; the shop will ask for it again later.
ApplyingTransferred to a new situation
The provider delivers the amount in euros instead of cents in the future ()49.90 instead of 4990). Which rule do you change, and what remains the same?
View the solution with justification
You only change the rule for amount + currency in the ACL: it no longer converts from cents. The amount of money result()49,90 EUR) and all shop conditions remain unchanged.
EvaluateWeighing an alternative
The shop uses only a single code from the provider. Is it worth an ACL?
View the solution with justification
A small ACL costs little care and keeps the provider language out of the specialist model. With an external provider without influence on his contract, it is worthwhile. If the translation is trivial and the contract stable, a simple adapter is sufficient.
Explore further
These building blocks continue the thoughts of this page.
References
- Microsoft Anti-Corruption Layer (opens in new tab)Protects your own specialist model from foreign data models and semantics.
- Martin Fowler · Bounded Context (opens in new tab)Explains model boundaries and relationships between different specialist models.
- Context Mapper · Context Map (opens in new tab)Describes contextual relationships and their concrete modeling.