Friday, April 13, 2012

Getting started with DDD when surrounded by Legacy systems II, by Eric Evans

I got this email a month or so back. Not sure if I should re-post it or not.
It has two parts,
  1. It advertises the up coming DDD courses in NY, Denver and London. 
  2. Then Eric describes how to get started in a legacy environment - (part II).
The parent website is here:






by Eric Evans
  1. Cutting the umbilical
  2. The Synchronizing ACL
  3. Bubble vs. Autonomous Bubble


In a previous newsletter I discussed the "Bubble Context" as a way to get started with DDD when there is not much organizational commitment. The bubble context is completely dependent on the parent context, drawing all its data through an anti-corruption layer (ACL) like an umbilical cord. You can use that strategy when little else might work. However, it has its limits.
Almost all software uses data that comes from other contexts. A lot of interesting domain logic revolves around combining data from different sources and reasoning about it. Even with one source, there may be a significantly new way of thinking about the data that is fundamental to the desired new functionality (a new way of abstracting the domain, i.e. a new domain model). Sometimes this is done in ways that tangle the systems together and prematurely limit design freedom. The bubble context is quite natural way to start with such an undertaking because the team can experiment with models and combinations in isolation from the legacy system, while the Umbilical ACL obtains and translates the data with minimal impact to existing systems.
The Autonomous Bubble is distinguished by the ability to run its software, for a time, cut off from other systems. Information may start to get stale, requests to external service requests start to queue up unfulfilled, but the internal behavior of the software continues to work. Whereas the Bubble Context obtains its data from another context when it is needed, via the umbilical ACL, the Autonomous Bubble typically has some data store of its own. The data store could be in-memory – the storage medium is irrelevant – but the data is in the form native to the context. This is not just a cache of frequently or recently used data. In fact, an umbilical ACL could cache data as a performance enhancement. The point of the local data store is that the overall evolution of the model and design in this context is much more loosely coupled to other contexts. It should be possible to test such a subsystem without mocks of other subsystems.

Main Characteristics of the Autonomous Bubble Strategy

  • Needs organization committed to significant new development with new design approach.
  • Allows new data to be collected and used without involving legacy.
  • Allows decoupled "product" to evolve.
  • May progress from Bubble Context as development is scaled up on a successful pilot project.


An autonomous context has its own data, sufficient to its core functions, organized according to in its own abstractions. To enable this, the ACL takes on the responsibility of synchronization between data stores in two contexts, which do not depend directly on each other. This ACL activity is asynchronous with any activity in either context, with a service level agreement (SLA) regarding the freshness of the translated data.
Synchronizing ACL
Diagram of Synchronizing ACL
Compare this with the Umbilical ACL of the Bubble Context here

The Nightly Batch Script: Low-tech Synchronizing ACL

Asynchronous synchronization with an SLA sounds more daunting than it is. It can be quite low-tech and examples are all around us. A very familiar implementation of the Synchronizing ACL is the “nightly batch”.
Now a typical nightly batch script does all sorts of things, some of which include important business logic. But, in my observation, one thing most of them do is to update one data store based on another. This could involve importing data from a file. It could involve kicking off a SQL script taking data from one table and transforming it and inserting it into another. It takes many forms, but look at a nightly batch script and you’ll probably find a Synchronizing ACL mixed in there.
    Typical nightly batch script has:
  • SLA: Open of business, next business day
  • Unnecessary coupling: Synchronizing ACL mixed in with once-per-day business logic
  • Unnecessary coupling: Multiple ACLs to multiple contexts lumped together.
If you are trying to establish an autonomous bubble, and you think your translation could be handled as part of a nightly batch script, then make sure you isolate the data copying and translation for your particular context into modules (one per context you are drawing on) which can be kicked off by the script. Don't let it get tangled into the spagetti. You need a decoupled synchronized ACL to pull off an autonomous bubble.

Messaging and Domain Events: A Stylish Synchronizing ACL

A more flexible approach to synchronizing uses messages carrying Domain Events. This can be nicely integrated with other event-driven architectural patterns. This approach can support a range of SLAs, and can update a system while it is being used, while batch scripts typically run while systems are off-line.
People discuss the use of messages and events for integration quite often, but usually they don't talk explicitly enough about what happens when a message crosses a context boundary. Just remember, any information crossing a context boundary must be translated. Messages are not somehow neutral. They are always expressed in some language based on some system of abstractions (a model), and we should not let them enter a context that uses a different language and model.
ACL translating Domain Events
Diagram of Synchronizing ACL translating events from one context
            to another.
Many ways of implementing a Synchronizing ACL are in use and more will come in the future, so I won't try to catalog them. Any mechanism that can update a data store in one context based on data in another, translating along the way, and can do this asynchronously, and without introducing any dependency on it from either context, could be used to implement a Synchronizing ACL. You probably have Synchronizing ACLs in your system now, although they may be tangled with other responsibilities


The first two strategies I've described each create a "bubble" context, and in this sense they are very similar, and resemble each other when looking inside the bubble. However, the difference in the relationship to the legacy contexts leads to a significant difference in the options for what you can do within the bubbles.
The "Umbilical ACL" from the first strategy gives us as little architectural overhead as possible, but allows no data to be used that can't be mapped from a context continuously attached. Any new information that does not already exist in the legacy system somewhere must be added to the legacy system somewhere, even though it will not be used there! Then it must be mapped into the bubble context, increasing the dependency between the two systems. Clearly this is not the strategy we want once we are introducing significant new information.
In contrast, the "Synchronizing ACL" gives more autonomy to the newly formed context. This autonomous bubble has its own data, some of which is mapped from another context, but it can also have data of its own. So development in the autonomous bubble is not so tightly bound to the older contexts. The model in this context can be more innovative and grow more freely, and a fresh new product can be created.


Design freedom is the point of a bubble. The bubble context with an umbilical ACL gives a little freedom, while the Autonomous Bubble can give us a lot if properly managed. However, in the actual unfolding of a development project, there are many ways this can go wrong and bog down before the team has reached its goals. In my next article I'll give some guidelines for process and design that help the team retain and even increase their ability to change the model as the project goes along.

No comments:

Post a Comment