rss twitter gitlab github linkedin linkedin instagram
Software Architecture in Go: Anti-corruption Layer Pattern
May 06, 2022

Disclaimer: This post includes Amazon affiliate links. If you click on one of them and you make a purchase I’ll earn a commission. Please notice your final price is not affected at all by using those links.

Welcome to another post part of the series covering Hands-On Software Architecture in Go, this time I’m talking about a topic that was originally introduced as part of Domain Driven Design but really it can be useful by itself.



What is the Anti-corruption Layer Pattern?

Eric Evans in his book Domain Driven Design defines it as (emphasis mine):

… an isolating layer to provide clients with functionality in terms of their own domain model. the layer talks to the other system through its existing interface, requiring little or no modification to the other system.

Internally, the layer translates in both directions as necessary between the two models.

This pattern is useful when interacting:

  • with external systems that may have different semantics, or
  • with third party systems or legacy applications.

This layer allows our system to interact with another one without being affected (or corrupted) by their design, keeping our system completely isolated from foreign concepts. The Anti-Corruption Layer is typically implemented using a combination of the Facade and Adapter design patterns.

How does it work?

It may sound a bit complicated but it is not, in Go we can implement this layer in two ways:

  • Using a dedicated service, or
  • Using a package

In both cases the goal is to isolate the interaction to the upstream system by wrapping all the required code and doing the conversion we need to satisfy our own domain model:

Anti-corruption Layer Pattern

  1. Downstream Service makes a request, therefore triggering a call to the Anti-corruption Layer (ACL),
  2. The ACL transforms the received message and creates a new request,
  3. The ACL receives the messages from the upstream service,
  4. The ACL converts the received messaged to the domain model used by our downstream service, and
  5. The converted message is sent back.

How can the Anti-corruption layer by implemented in Go?

The code used for this post is available on Github.

One way to implement this pattern is to create a package local to the service using it, in this example we are hypothetically accessing two legacy APIs, in both cases they return temperature values, specifically Kelvin and Fahrenheit, however our domain model works with Celsius, so we have to create an Anti-corruption Layer to prevent their implementation corrupt ours.

The Anti-corruption Layer Pattern uses a combination of Facade and Adapter design patterns, so a code like the following for the fahrenheit package:

 5func New(country string) Fahrenheit {
 6	return Fahrenheit{}
 7}
 8
 9func (f Fahrenheit) Value() float64 {
10	return 85.5
11}

and for the kelvin package:

3func Calculate(country string) float64 {
4	return 306.15
5}

Could easily be implemented in the anticorruption package as:

 8func Kelvin(country string) float64 {
 9	// C = K − 273.15
10	return kelvin.Calculate(country) - 273.15
11}
12
13func Fahrenheit(country string) float64 {
14	// C = (5.0/9.0) * (F-32)
15	return (5.0 / 9.0) * (fahrenheit.New(country).Value() - 32)
16}

And accessed as simply as:

11func main() {
12	// ...
13
14	fmt.Println("anticorruption", anticorruption.Fahrenheit("COUNTRY1"))
15	fmt.Println("anticorruption", anticorruption.Kelvin("COUNTRY2"))
16}

Therefor hiding the upstream implementation and keeping our model consistent to what we use: Celsius.

Conclusion

The Anti-corruption Layer is a defensive pattern meant to separate two domains, ours and the one we need to have access to, it’s useful when working with legacy systems as well as third party APIs because it isolates their implementation and allows ours to keep our domain model consistent to the requirements we have to satisfy.

If you’re looking to sink your teeth into more Software Architecture, I recommend the following content:


Back to posts