In the previous blog post, Ivan focused on translating the event model of the “music lesson booking system” to the source code, by using Axon Framework as a programming model and Axon Server as an event store and message broker.
In this part we will zoom out, and visualize how multiple software systems fit together within the bounds of an enterprise.
After the “music lesson booking system” was in production for a while, we realized that there is more than just simply adding a lesson into the system for the students to book. We started thinking about the (sub)domain of “teacher”: Who will register teachers into the system? Who will create, draft and publish lessons so they are available to students? How are students going to pay for the lessons they have booked? Let’s find out!
In the blueprint below we now visualize three systems on the timeline: “booking”, “teacher” and “payment”.
We use the second level of swimlane(s) to visualize which events (and aggregates) belong to which systems. For example, “TeacherRegistered” event belongs to “Teacher” aggregate, which additionally belongs to a Teacher system. Payment system is not in any swimlane because we will be using a third party system for payment processing (we are not going to implement this system).
To make this more clear, we will extract each of these systems into independent blueprints.
The booking system remains the same, it enables students to browse and book the lessons. The only thing that is changed is who is going to add the lessons to this system, so they are available for booking. Creating, drafting and publishing lessons is now the responsibility of a teacher system. The booking system will subscribe to the LessonPublished event (from Teacher system) and publish the AddLesson command (from Booking system).
This new component that translates LessonPublished event to the AddLesson command is essentially an Event Handler in Axon. In Event Modeling this pattern is known as the “Translation” pattern.
It is just a new adapter that we are adding, adopting the event of another system to a command of the booking system. You can still keep the old REST/UI adapter, if you need this web page for some reason (in process of transition, for example).
Teacher management system
Teacher system can now independently evolve to enable managers to add teachers in the system and to allow teachers to create, draft and publish lessons.
We are not going to dive deep into this system. The process of translating the teacher system to the source code is very similar to the booking system, we have described in the previous blog post.
We are focusing more on the strategic and integration patterns in this blog post.
Each of these systems is a subdomain model, and not all of these subdomains are equally important.
We map out our domain as a portfolio of capabilities and anticipate how they may change over time. Special focus is on identifying the core domains, the key areas for business growth.
In our example, we anticipate that the Teacher subdomain will transit to a supporting domain in a three-month period.
The question is, if these systems/subdomain-models are autonomous bounded contexts.
Domain Driven Design divides up a large system/domain-model into Bounded Contexts, each of which can have a unified model - essentially a way of structuring MultipleCanonicalModels. Bounded Contexts have both unrelated concepts (such as an Account aggregate only existing in a Booking context) but also share concepts (such as Lesson aggregate). Different contexts may have completely different models of common concepts with mechanisms to map between these common concepts for integration.
In our case, the common concept of Lesson is modeled as an aggregate in booking context and as an aggregate in teacher context. These are now two different models of the common concept of Lesson, and each of these contexts have a unique understanding of this concept, by using unified vocabulary (ubiquitous language). All we have to do is to map/translate this concept for integration between these two bounded contexts. The Event Handler component we have described earlier is acting as an anti-corruption layer (ACL) component now.
Bounded Context Mapping
Axon takes “location transparency” further than placing services behind a logical URL. In Axon, a component (for example an Event Handler) that sends a message via CommandGateway/QueryGateway does not need to specify a destination for that message. This is giving you options, as now you get to choose in which system/subdomain model to put your Event Handling component that is responsible for translating/integrating two bounded contexts.
Since booking is our Core domain, we would want to put the Event Handler component under the Booking context. This puts the Booking context downstream from the Teacher context. This makes the core domain model dependent on the supporting domain model and not the other way around.
This is crucial because if in the future we decided to transfer the Teacher model to a 3rd party (generic) domain model we want to make sure that nothing is dependent on the core system. Therefore, switching a supporting system to a generic system can easily be achieved.
The Booking context (and the team that produces it) is downstream to Teacher and Payment bounded contexts. The Event Handler component is acting as an anti-corruption layer (ACL) component by not letting events from the Teacher or Payment system leak deep into the Booking domain model.
There is a “customer-supplier” relationship between teams. The Downstream team is considered to be the customer. Downstream requirements factor into upstream planning. Therefore, the Downstream team gains some influence over the priorities and tasks of the Upstream team.
Axon Server (Enterprise) explicitly supports bounded contexts, by allowing different (groups of) applications to connect to different contexts within the Axon Server. Unless specifically indicated otherwise, contexts are strictly separated and information/messages are not shared between them.
We hope that these few blogs have given you the basic architectural ideas and some tools to help you design your systems. Of course, there are many ways of doing this process. But one important thing to keep in mind is why a system should be chosen as core and downstream to other systems. That is where the business problem has to be identified and examined closely. Our model to code example is just one way of showing you how these tools can be useful and hopefully you can benefit from these examples in your own projects.