· domain-driven-design

Domain Driven Design: Anti Corruption Layer

I previously wrote about some of the Domain Driven Design patterns we have noticed on my project and I think the pattern which ties all these together is the anti corruption layer.

The reason why you might use an anti corruption layer is to create a little padding between subsystems so that they do not leak into each other too much.

Remember, an ANTICORRUPTION LAYER is a means of linking two BOUNDED CONTEXTS. Ordinarily, we are thinking of a system created by someone else; we have incomplete understanding of the system and little control over it.

Even if the model we are using is being defined by an external subsystem I think it still makes sense to have an anti corruption layer, no matter how thin, to restrict any future changes we need to make in our code as a result of external system changes to that layer.

In our case the anti corruption layer is a variation on the repository pattern although we do have one repository per service rather than one repository per aggregate root so it’s not quite the same as the Domain Driven Design definition of this pattern.

anti-corruption.gif

The mapping code is generally just used to go from our our representation of the domain to a representation of the domain in auto generated from an xsd file.

We also try to ensure that any data which is only important to the service layer doesn’t find its way into the rest of our code.

The code looks a bit similar to this:

public class FooRepository
{
	private readonly FooService fooService;

	public FooRepository(FooService fooService)
	{
		this.fooService = fooService;
	}

	public Foo RetrieveFoo(int fooId)
	{
		var xsdGeneratedFooRequest = new FooIdToXsdFooRequestMapper().MapFrom(fooId);
		var xsdGeneratedFooResponse = fooService.RetrieveFoo(xsdGeneratedFooRequest);
		return new XsdFooResponseToFooMapper().MapFrom(xsdGeneratedFooResponse);
	}
}
public class FooIdToXsdFooRequestMapper
{
	public XsdGeneratedFooRequest MapFrom(int fooId)
	{
		return new XsdGeneratedFooRequest { fooId = fooId };
	}
}
public class XsdFooResponseToFooMapper
{
	public Foo MapFrom(XsdGeneratedFooResponse xsdGeneratedFooResponse)
	{
		var bar = MapToBar(xsdGeneratedFooResponse.Bar);
		// and so on
		return new Foo(bar);
	}
}

Right now we are transitioning our code to a place where it conforms more closely to the model being defined in the service layer so inside some of the mappers there is some code which is complicated in terms of the number of branches it has but doesn’t really add much value.

We are in the process of moving to a stage where the mappers will just be moving data between data structures with minimal logic for working out how to do so.

This will lead to a much simpler anti corruption layer but I think it will still add value since the coupling between the sub systems will be contained mainly to the mapper and repository classes and the rest of our code doesn’t need to care about it.

  • LinkedIn
  • Tumblr
  • Reddit
  • Google+
  • Pinterest
  • Pocket