A View of Bounded Context
A View of Bounded Context
Learn what bounded context is and why it's important, and why it's an intrinsic part of successful microservices development.
Join the DZone community and get the full member experience.Join For Free
Learn why microservices are breaking traditional APM tools that were built for monoliths.
In this article, I will share my view about bounded context. What does it mean? Why is it required?
The Connection Between Bounded Context and Microservices
I will try to keep it simple and keep this article targeted to the audience who hears the term "bounded context" while developing microservices but has a hard time understanding the bounded context concept.
Before the deep dive into bounded context in terms of DDD (Domain Driven Design), let's understand the meaning of it in the real world. We know the human is the most intelligent species and created different countries to rule. But the question is, why did they create different countries with logical boundaries? How was the boundary drawn between two countries? Before human civilization on Earth, we only had land, there was no concept of countries.
Compelling answers come to my mind: to separate the administration, culture, laws, and economics, so each country abstracted its people from other countries, unless it is an impossible task to create one unified culture and language, as in ancient times, different tribes had their own languages and culture.
In the same country, there are some predefined rules, language, and style every citizen follows. They understand the common language, laws, currency, and style, so I can say the citizens are in sync with each other in a country, and that country has one unified culture which every citizen follows and understand.
In programming, we apply bounded context in the same manner - to separate different models/subdomains from each other in a domain/problem space. In domain-driven design, the strategic design part, we introduce bounded context, so in a certain context, a model has a certain meaning, like the countries where a certain language and currency have a specific meaning. In a different country, that currency and language are not understandable because they have no meaning or a different meaning. In English, the word "fool" means "stupid," but in Bengali, it means "flower!"
If we consider a country like a bounded context and languages/currencies as a model inside that context, we can easily map the concept of the model in a certain bounded context. The model has meaning for one bounded context, but the same model has no meaning (or a different meaning) for another bounded context. With bounded context, we create a logical boundary where the model and business terms have a certain meaning and the bounded context separates/hides the models from the outer world; all communication should be done via API. It is obvious that under a bounded context, the model and business logic maintain a certain law and maintain their own persistence storage that is not directly accessible to other bounded contexts.
Bounded Context Communication
Any design has two common parts: abstraction of the data model and communication with other parts of the system. With bounded context, we separate the data model, abstracting the commonalities in the business. But how does one bounded context communicate with others?
Here the concept of a context map steps in. Using context maps, we can discover how one context depends on other bounded contexts, like whether two contexts have strong dependencies, or when one domain sends a confirmation message to another domain (conformist) or uses a shared kernel/shared model. I will talk about context maps later in a separate article, but for now, context maps are for communicating clearly between bounded contexts.
At this point, I believe you have an idea of what a bounded context is, but if you still have questions about how it fits into architecture, go to the next paragraph.
Let say we have to design an online student management system where a student can register to the site, choose courses, and pay the course fees, and he will be tagged to a batch; the teacher and student are notified about the batch start date and time slot.
As an architect, you have to identify the bounded context of the different domains related to this business logic. If we divide the business logic based on related functionality, we can find four basic functionalities:
Registration process: takes care of the registration of the student.
Payment System: will process the course fee and publish the online payment status.
Batch Scheduling: Upon confirmation of payment, this function checks the teacher availability and batch availability, and based on that, creates a batch and assign the candidates or updates an existing batch with the candidate.
Notification System: It will notify the teacher and student about the timings and slot information.
So, there are four bounded contexts: Registration, Payments, Scheduler, and Notification.
Now, let's dig into how each module represents the Teacher, Student, and Course models.
It only wants the Student information; it needs it demographic information like name, age, sex, address, and which course the student chooses. There is no meaning of Teacher in this context.
The Payment System treats Students as Candidates in the Payment System. Only the Student/Candidates' financial information is required like an Account number and based on the course fees it deducts from the given account, so the perspective of a student is totally different. The information needed in the payment service is totally different from Registration, although the Payment system may need a few minimal pieces of information like the name and address of the student.
The term "Teacher" is not valid here. In the payment system, a Teacher treated as Faculty and they can be permanent or Contractor, based on the Faculty type the payment system chooses for the payment calculation - either a per hour basis or per anum basis.
In the case of a Batch Scheduling system, it needs a bare minimum of information from a Teacher and Student, like name, address, etc, but it needs detailed information for Courses and Batches under the Courses, etc.
For the Notification System, we just need the Teacher and Students' name and email address or Phone number, and nothing else, and it needs the name of the Student management system and Course details. Here, the Student management site acts as Sender and Teacher, and the Student is denoted as Reciever.
Until now, we have seen the same Domain Objects: Teacher, Student, and Course have different meaning and use cases for different contexts. This is the beauty of Bounded Context; we have multiple canonical models for the same domain Object based on different contexts, so developers, businesses, and users are always on the same page when they are talking about a context. The concept of ubiquitous languages is woven here, using ubiquitous language DDD to create a unified system where every participant understands the language based on the context.
Now, the common question is why the bounded context term is so popular in microservices?
To answer this question, we first have to understand that DDD is applicable for the monolith as well as microservices, but in the case of the monolith, it is vaguer and more of a logical segregation, so only good developers can see it. The main reason is that in a monolith, we have a single giant codebase. We may break it into multimodules based on DDD and create ACL/Translator when one module talks to another, but still, it needs other modules as dependent jars to invoke its method.
Another point: as this is a single code base and multiple coders are working on it, some not-so-skillful coder could pollute the boundary or domain object. The architect can't create a physical boundary based on bounded context, but in microservice architecture, it is inherent, as microservices say that rather than a large code base, we can create small services which have their own code base and services talking to each other through API or messaging. The business domain breaks the business logic in to multiple bounded contexts, and each bounded context will be a separate codebase and communicate through the context map.
To design the context map, you have to design the API carefully; you can use Port and Hub architecture so your code under the bounded context does not communicate with the outside world and is never polluted. Microservices offer this type of strong segregation of bounded context. Bounded context is more visible and understandable in the context of microservices.
Bounded context is a basic need when you are trying to break a large business logic. It helps you to understand how different parts of the system use domain objects in a different manner with different terminology. Bounded context is just a view to properly organize the business logic based on functionality, but to make the business logic work, communication between bounded context is needed, and it uses context map for this. In my next article, I will discuss context map.
Opinions expressed by DZone contributors are their own.