When using multiple models, everybody can work\u00a0freely on their own piece. We all know the limits of our model,\u00a0and stay inside the borders. We just have to make sure we keep\u00a0the model pure, consistent and unified. Each model can support\u00a0refactoring much easier, without repercussions on other models.<\/div>\n<\/li>\n
\nThere is a price to pay for having multiple models. We need to\u00a0define the borders and the relationships between different\u00a0models. This requires extra work and design effort, and there\u00a0will be perhaps some translation between different models. We\u00a0won\u2019t be able to transfer any objects between different models,\u00a0and we cannot invoke behavior freely as if there was no\u00a0boundary. But this is not a very difficult task, and the benefits\u00a0are worth taking the trouble.<\/div>\n<\/li>\n
\nThe recommended approach is to create a separate model for\u00a0each of the domains. They can both evolve freely without much concern\u00a0about each other, and even become separate applications.<\/div>\n<\/li>\n<\/ul>\n
Continuous Integration<\/strong><\/div>\n\n- \n
If\u00a0one does not understand the relationships between objects, they\u00a0may modify the code in such a way that comes in contradiction\u00a0with the original intent. It is easy to make such a mistake when\u00a0we do not keep 100% focus on the purity of the model.<\/div>\n<\/li>\n
- \n
We need a process of integration to make sure that all\u00a0the new elements which are added fit harmoniously into the rest\u00a0of the model, and are implemented correctly in code.<\/div>\n<\/li>\n
- \n
Continuous Integration applies to a Bounded Context, it is not used to deal with relationships between neighbouring Contexts.<\/div>\n<\/li>\n<\/ul>\n
Context Map<\/strong><\/div>\n\n- \n
A Context Map is a document which outlines the\u00a0different Bounded Contexts and the relationships between them.<\/div>\n<\/li>\n
- \n
A Context Map can be a diagram like the one below, or it can be\u00a0any written document. The level of detail may vary.<\/div>\n<\/li>\n
- \n
What it is\u00a0important is that everyone working on the project shares and\u00a0understands it.<\/div>\n<\/li>\n
- \n
If the relationships between contexts are not outlined,\u00a0there is a chance they won\u2019t work when the system is integrated.<\/div>\n<\/li>\n
- \n
Each Bounded Context should have a name which should be part\u00a0of the Ubiquitous Language.<\/div>\n<\/li>\n
- \n
The Shared Kernel and\u00a0Customer-Supplier are patterns with a high degree of interaction\u00a0between contexts. Separate Ways is a pattern used when we\u00a0want the contexts to be highly independent and evolve\u00a0separately. There are another two patterns dealing with the\u00a0interaction between a system and a legacy system or an external\u00a0one, and they are Open Host Services and Anticorruption\u00a0Layers.<\/div>\n<\/li>\n<\/ul>\n
Shared Kernel<\/strong><\/div>\n\n- \n
The purpose of the Shared Kernel is to reduce duplication, but\u00a0still keep two separate contexts.<\/div>\n<\/li>\n
- \n
Development on a Shared\u00a0Kernel needs a lot of care. Both teams may modify the kernel\u00a0code, and they have to integrate the changes.<\/div>\n<\/li>\n
- \n
If the teams use\u00a0separate copies of the kernel code, they have to merge the code\u00a0as soon as possible, at least weekly.<\/div>\n<\/li>\n
- \n
A test suite should be in\u00a0place, so every change done to the kernel to be tested right away.<\/div>\n<\/li>\n
- \n
Any change of the kernel should be communicated to another\u00a0team, and the teams should be informed, making them aware of\u00a0the new functionality.<\/div>\n<\/li>\n<\/ul>\n
Customer-Supplier<\/strong><\/div>\n\n- \n
There are times when two subsystems have a special\u00a0relationship: one depends a lot on the other. The contexts in\u00a0which those two subsystems exist are different, and the\u00a0processing result of one system is fed into the other.<\/div>\n<\/li>\n
- \n
There might be some overlapping, but not enough to\u00a0justify a Shared Kernel.<\/div>\n<\/li>\n
- \n
A Customer-Supplier relationship is viable when both teams are\u00a0interested in the relationship. The customer is very dependent on\u00a0the supplier, while the supplier is not.<\/div>\n<\/li>\n
- \n
When two development teams have a Customer-Supplier\u00a0relationship in which the supplier team has no motivation to\u00a0provide for the customer team\u2019s needs, the customer team is\u00a0helpless.\u00a0The most obvious one is to\u00a0separate from the supplier and to be completely on their own.\u00a0We will look at this later in the pattern Separate Ways.<\/div>\n<\/li>\n
- \n
But because the supplier team\u00a0does not help the customer team, the latter has to take some\u00a0measures to protect itself from model changes performed by the\u00a0former team. They will have to implement a translation layer\u00a0which connects the two contexts.<\/div>\n<\/li>\n
- \n
The customer context can still make use of\u00a0it, but it should protect itself by using an Anticorruption Layer\u00a0which we will discuss later.<\/div>\n<\/li>\n
- \n
The customer team cannot make changes\u00a0to the kernel. They can only use it as part of their model, and\u00a0they can build on the existing code provided.<\/div>\n<\/li>\n<\/ul>\n
Anticorruption Layer<\/strong><\/div>\n\n- \n
We can\u2019t ignore the interaction with\u00a0the external model, but we should be careful to isolate our own\u00a0model from it.<\/div>\n<\/li>\n
- \n
But the\u00a0Anticorruption Layer talks to the external model using the\u00a0external language not the client one.<\/div>\n<\/li>\n
- \n
This layer works as a two\u00a0way translator between two domains and languages.<\/div>\n<\/li>\n
- \n
The greatest\u00a0achievement is that the client model remains pure and consistent\u00a0without being contaminated by the external one.<\/div>\n<\/li>\n
- \n
A very\u00a0good solution is to see the layer as a Service from the client\u00a0model. It is very simple to use a Service because it abstracts the\u00a0other system and let us address it in our own terms. The Service\u00a0will do the needed translation, so our model remains insulated.<\/div>\n<\/li>\n
- \n
The Anticorruption Layer may contain more than one Service.<\/div>\n<\/li>\n
- \n
For each Service there is a corresponding Fa\u00e7ade, and for each\u00a0Fa\u00e7ade we add an Adapter. We should not use a single Adapter\u00a0for all Services, because we clutter it with mixed functionality.<\/div>\n<\/li>\n
- \n
The Adapter takes care of wrapping up the behaviour of the external system. We also need object and data conversion. This is done using a translator. This can be a very simple object, with little functionality, serving the basic need of data translation.<\/div>\n<\/li>\n<\/ul>\n
Separate Ways<\/strong><\/div>\n\n- \n
It\u2019s one thing to develop independently, to choose the\u00a0concepts and associations freely, and another thing to make sure\u00a0that your model fits into the framework of another system.<\/div>\n<\/li>\n
- \n
We\u00a0may need to alter the model just to make it work with the other\u00a0subsystem. Or we may need to introduce special layers which\u00a0perform translations between the two subsystems. There are\u00a0times when we have to do that, but there are times when we can\u00a0go a different path.<\/div>\n<\/li>\n
- \n
We should look at the requirements and see if they can be divided in two or more sets which do not have much in common. If that can be done, then we can create separate Bounded Contexts and do the modelling independently.<\/div>\n<\/li>\n
- \n
Before going on Separate Ways we need to make sure that we\u00a0won\u2019t be coming back to an integrated system. Models\u00a0developed independently are very difficult to integrate. They have so little in common that it is just not worth doing it.<\/div>\n<\/li>\n<\/ul>\n