Crisp View of Context Map
Crisp View of Context Map
Learn how context mapping helps organize your microservices and why it's an essential concept when designing a solution.
Join the DZone community and get the full member experience.Join For Free
Record growth in microservices is disrupting the operational landscape. Read the Global Microservices Trends report to learn more.
In my previous article, I did a detailed discussion about bounded context and how to tackle the complexity of a domain. It is best to divide the domains into several subdomains and map them with different bounded contexts where each business entity/value object has a certain meaning in that context, so every stakeholder of the business (product owners, developers, architects, and sponsors) understand the context and refer to entities with the proper taxonomy. There should be no confusion about naming when we discuss domain objects basis in context with a ubiquitous, unified language among business stakeholders.
With bounded context, we properly define a business model, create a different context based on the business domains, but always a functionality spans over multiple business entities , and those entities lie in the different Bounded contexts/domains, so it is utmost important to understand the relationship between the Bounded contexts, to architecting the business solution Context Map is a technique by which we can visualize the relationship between different contexts and Integration architect choose the best integration patterns to communicate to other contexts.
Why a Context Map Is So Important When Designing a Solution
With a UML diagram, an architect can understand how different parts will communicate with other parts. It gives the architect a view of the communication between different contexts. That is fine, but context maps stepped in before the UML diagram; this helps to visualize the nature of the relationship and, based on that nature, architects can decide what kind of technical solution should be adopted.
The best part of context map visualization is that it talks about the nature of the relationship. It not only tells us whether a relationship is upstream or downstream, publisher or subscriber, it also tells how different teams are dependent on other teams, their motifs, their politics...everything. Counting all of that, now the architect in a position to decide the optimal solution to minimize risk while integrating with another context.
In the era of microservices, context maps are the key player, because before design, the holistic microservice architecture where every team owns a microservice, it is important to understand how one team is dependent on others, which teams are in a commendable position, and which team only seeks help; then you can architect the solution best possible way.
Think of our Student Online Tutor app. As a full-grown app. say it has more than fifty microservices deployed in production. Here, fifty teams are coming into play, and for developing a functionality — say, student registrations — multiple contexts will be affected. We can say that to implement that feature, multiple teams will be involved, so what would be their relationship? While designing this feature, who is the pivot service whose data is most needed? Obviously, that service is in a commendable position. If that team is not ready, other teams can't do anything, so all teams should align with that team. They have to sync their product backlogs with that team, so here, internal politics come into the picture. If the data of the service comes from an external team not within the organization, then the solution is way more complex, as you can't force them, so the only way is to request it from them and wait for their changes. Based on these different scenarios, the politics context map has different solutions. I will cover most important solutions here.
Shared kernel talks about a partnership relation where two or more teams share a common data model/value object. It reduces code duplication as different context use that common model, but that common model/value object is very sensitive, so any changes major/minor should be agreed upon all the parties unless it would break other parties code, so more communication and synchronization need to happen between those teams. Say one team needs a change in the common model, but another team is not ready; the prior team has to wait for the other partner to be ready, or on the other hand, the partner has to change their code although that is not required for them, but to be in sync with other partners. Different shades of problems are woven while maintaining the partnership relationship, so choose that pattern when your common model remains constant or only changes once in a while.
In our example, say we developed an analytical module which analyzes which courses are most chosen by the students, which students have chosen more than five courses, etc. That module works with the student domain model and course model, so our analytics module can share the registration module's student model, and they agree upon any changes in the student model.
Generally, this is the common relationship between two contexts, where a context consumes or depends on data from another context. The context which produces data is marked as upstream and the context which consumes data is called downstream. When we visualize this relationship in terms of politics, we can visualize the power distribution has many shades, like the following:
Upstream as the Leader
In this type of relationship, the upstream team is in a commendable position; that team does not care about the downstream teams, as they produce the data, and the downstream team is at the mercy of that upstream team — they are always changing their model based on the data structure produced by the upstream team.
In our Student Registration app, the relationship between the Payment app and the Notification app is kind of upstream and downstream, where the Payment app decides what information in which structure they provide and the Notification module consumes that data structure.
Downstream as the Leader
In some cases, the relationship is reversed. Although upstream produces data, it must follow the rules/data structure for downstream. In this scenario, downstream is in a commendable position.
Say that in our Studen registration system, we need to submit Form 16 to the government as a tax payee, so our payment module has to submit Form 16 data to a Government-exposed API. But, the government API has certain rules and a data structure for submitting form 16 data, so although the government API is downstream, it has total control. Our Payment module should communicate with downsteam in such a way so it can fulfill downstream's rules.
The customer-supplier relation works best when both the parties upstream and downstream are aligned with the work; both parties have agreed upon the interfaces and change in the structure, and in case of any changes in the contract, both parties will have a discussion to synchronize their priority backlogs and agree upon the changes. If one party does not care about the other party, then every time the contract will be broken and it is tough to maintain a customer-supplier relationship.
Sometimes, there is a relation between two parties in such a way that the downstream team always dependent on an upstream team and they can't have a mutual agreement with upstream about the requirements. The upstream team is not aligned with downstream and does not care; they are free to change their published endpoint or contract any time and don't take any requests from downstream. It happens when the upstream team is an external system or under a different management hierarchy, and many downstream systems are registered with it so it can't give a priority to any downstream, rather than all downstream systems being aligned with the upstream contact and data structures; if the upstream contracts or data structures changes, then it is downstream's responsibility to change accordingly.
Say, in our online Student registration app, we have a free tutorial module where all students or other applications can consume our free tutorials and embed them in their application. Here, our free tutorial module acts as upstream and independent of any other third-party app who consumes our free tutorials; we can't give any priority to them and we don't have any contract with them. If we change the contracts or data structures, it is other third parties' duty to change their application accordingly to consume our free tutorials. Other parties are acting as a conformist.
Anti Corruption Layer
When two systems interact, if we consume the data directly from upstream, we pollute our downstream system as upstream data structure leaks through the downstream. If the upstream becomes polluted, our downstream does, too, as it imitates the upstream data while consuming.
It is a good idea while consuming data from a third party or from a legacy application to always use a translation layer where the upstream data translates to the downstream data structure before being fed into downstream. That way, we can resist the data leakage from upstream. If the upstream contract changes, it does not pollute the downstream internal system; only the translation layer has to be changed in order to adopt a new data structure from upstream and convert it into the downstream data structure. This technique is called an anti-corruption layer. Anti-corruption layers save the downstream system from upstream changes.
In our application, the Notification module can implement an ACL (anti-corrupution layer) while consuming data from the payment module, so if the payment module data structure changes, only ACL layers are affected.
In some cases, your Domain API needs to be accessed by many other services, like our Free Tutorial Publisher module. Many external or internal domains want to consume this service, so as the upstream, it should be hosted as a service and maintain a protocol and service contract like REST and JSON structure so other systems can consume the data.
Often, two or more systems receive and send messages among themselves. In that case, a common language is needed to transform of the data from one system to anotherm like XML and JSON. We call that structure a published language.
The bird view of our Student online registration app in terms of the context map:
Context mapping is a very important exercise to realize how one domain communicates with the others. It gives a proper view of the organization structure, how different domains are distributed, and how domain owners are dependent on each other. What is the relationship between team structure? Can they be aligned with a feature? Based on all the parameters, can an integration engineer can adopt a suitable integration pattern to integrate domains? Prior to designing the integration solution, the architect always has to define a context map to understand the relationship and structure of the teams, and based on that, the architect can choose the best possible solution.
Opinions expressed by DZone contributors are their own.