In the previous blog post, Ivan focused on translating the "music lesson booking system" event model to the source code using Axon Framework, 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. So 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 classes 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, the "TeacherRegistered" event belongs to the "Teacher" aggregate, which additionally belongs to a Teacher system. On the other hand, the 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 precise, 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 will 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 the Teacher system) and publish the AddLesson command (from the Booking system).
This new component that translates the 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 the transition process, for example).
Teacher management system
The teacher system can now independently evolve to enable managers to add teachers to the system and allow teachers to create, draft and publish lessons.
We are not going to dive deep into this system. However, 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. A particular focus is on identifying the core domains, the critical areas for business growth.
In our example, we anticipate that the Teacher subdomain will transit to a supporting domain in three months.
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 unrelated concepts (such as an Account aggregate only existing in a Booking context) and share concepts (such as Lesson aggregate). Different contexts may have completely different models of common concepts with mechanisms to map these common concepts for integration.
In our case, the standard concept of Lesson is modeled as an aggregate in the booking context and as an aggregate in the teaching context. These are now two different models of the standard concept of Lesson, and each of these contexts has a unique understanding of this concept by using unified vocabulary (ubiquitous language). We have 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 gives you options, as now you get to choose in which system/subdomain model to put your Event Handling component 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 sets 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 acts 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 other 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 tools to help you design your systems. Of course, there are many ways of doing this process. But one crucial 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 helpful, and hopefully, you can benefit from these examples in your projects.
Sara Torrey is a Developer at AxonIQ. She is a self-taught full-stack developer, who has worked with various programming languages and frameworks, namely Java, Axon, and Spring Boot. She comes from a rather unusual background; she studied Music in university and graduate school.
Solutions architect with significant experience in designing full stack application components and providing guidance to the solutions teams in development and implementation.
Skilled in a wide variety of technology stacks and learning quickly new technologies as needed. Experience covers all facets of design patterns, software architecture, continuous delivery, agile methodologies and best practices in constructing solutions that remain scalable, adaptable and replicable. Strong engineering professional with the Master of Science (MSc) focused on Computer Science from the University of Belgrade, Faculty of Mathematics.