The evolution of software design from Monolithic to Event-Driven Architecture
Software design has come a long way, evolving from monolithic architectures to more sophisticated event-driven architectures. Have you experienced a monolithic app before? These applications are designed as a single indivisible unit. While this approach can simplify development at first, it often leads to challenges like limited scalability and difficulties when making changes. The components are tightly coupled so that when you need to make a change in one part, you need knowledge and experience with all the parts.
As organizations began to encounter these types of constraints, event-driven architectures emerged. This progressive shift recognizes that software systems function better when various components interact asynchronously rather than being tightly bound together. In event-driven applications, systems are designed to respond to events, which are changes in state triggered by user actions or external factors. This architectural pattern not only enhances scalability but also improves resilience, making it easier for teams to deliver new features quickly.
What are the fundamentals of Event Modeling?
Event Modeling is a structured approach aimed at visualizing and representing how applications react to events across a system’s life cycle. At its core, this technique allows teams to identify key events within a system, creating a roadmap for how these events shape the user experience and system behavior. By focusing on events, developers can better understand the impact of user actions and external processes on the application's state.
In Event Modeling, modeling events becomes a collaborative, iterative process. Teams gather to map out significant events, decisions, and responses that occur throughout a system's life cycle. Acting as a visual guide, this model highlights how different components interact and aids the development team in properly modeling the system's behavior in collaboration with the business and management teams, which are the domain experts.
Now let's consider a banking scenario. In this type of business domain, when a customer initiates a fund transfer, several critical events occur, such as:
-
The transfer request is received
-
The account balance is checked to see if funds are available
-
If there are sufficient funds, then the transaction is executed
Each of these actions can be captured as events in the model, providing a clear representation of how the system behaves. This visibility ensures that the application can efficiently handle real-time changes and maintain consistency across various processes.
As we examine things further within this domain, we can identify several other events that map to behaviors within the system, such as "Account Opened," "Funds Deposited," "Funds Withdrawn," and "Account Closed." In an Event Sourced application, each event represents a state change in the system and should be persisted with pertinent details like the timestamp, involved entities, and any correlating data.
The strength of Event Modeling lies in its ability to create a visual representation of these events in a timeline, detailing the causality and sequence. This visualization becomes a powerful tool in communicating the system's design and expectations to both technical and non-technical stakeholders, ensuring alignment before a single line of code is written.
Now let's compare Event Modeling to Event Storming
Event Modeling and Event Storming are often mentioned in similar contexts, but they serve distinct purposes and methodologies. Event Storming is an exploratory workshop-driven approach that focuses on the collaborative discovery of domain events among team members. It's typically facilitated with sticky notes and whiteboards, encouraging spontaneous idea generation and discussion.
Additionally, Event Storming can be seen as a brainstorming technique primarily used for exploring complex domains and mapping out workflows, utilizing collaborative discussions. It aims to uncover business processes and identify key events through open dialogue, making it effective for initial discovery phases.
For example, during Event Storming for a banking application, participants might brainstorm events such as "Loan Application Submitted" and "Loan Approved." The process could reveal hidden complexities and new requirements. Event Modeling would then take these discovered events and place them into a coherent structure, detailing how each event leads to the state transitions needed to approve a loan.
In contrast, Event Modeling provides a more structured, comprehensive blueprint for the entire system's lifecycle of events. It involves methodical steps like specifying event types, defining projections, and modeling user interactions. Where Event Storming helps uncover and brainstorm events, Event Modeling places a higher emphasis on UI elements, with the "storyboard" outlining human actors and the actual screens they use to trigger and observe state changes
Event Modeling takes the findings from an Event Storming session and translates them into structured visual representations of events and user interactions. While Event Storming emphasizes collaborative exploration, Event Modeling benefits from a more formalized approach, focusing on laying out how each event transpires within the system's architecture. The end goal of both methodologies is to enhance understanding, but the approaches differ fundamentally.
Using our banking application example, during an Event Storming session, the team may uncover various processes such as account creation, fund transfers, and loan applications—all crucial events worth exploring. Event Modeling then takes these insights and creates a detailed representation of how each event impacts the system. This structural model will highlight the transition states, necessary commands, and corresponding outcomes of user interactions, ensuring a clear path to follow during development.
Why separate commands from queries?
The separation of commands from queries is central to many modern software design patterns, including Event Modeling. By isolating commands—operations that modify a system's state—from queries—requests for data without any changes—developers can enhance the efficiency and organization of their applications. This separation allows for a more structured approach to handling user interactions and improves scalability.
The Event Modeling process
During the Event Modeling process, you should identify your events, determine your commands, and design your projections. If you’re unfamiliar with these terms, let’s explore them further.
Identifying and modeling Events
The first step in the Event Modeling process involves identifying significant events that occur within a system. This requires the participation of domain experts who have an in-depth understanding of business operations. Events in this context are not only acts or occurrences but are also triggers that result from user actions or system processes. It’s essential to define these events accurately to ensure they capture the essence of user interactions.
When modeling events for a banking application, consider a scenario where a customer applies for a mortgage. The important events could range from "Application Submitted," "Credit Check Completed," and "Application Approved." By breaking down the application process into key business events, teams can create a clear sequence that shows how the process unfolds and highlights critical user interactions (if any) along the way.
Commands and User interactions
After identifying and modeling events, the next step is to define the commands and user interactions that yield these events. Commands are actions that users or systems invoke to trigger specific events within the application. Understanding the command actions within a system is necessary in order to know what state changes will take place and the flow of events.
Once again, in the banking business domain, consider the command "Initiate Transfer." This command expresses the intent to transfer funds from one account to another and is executed when the end user clicks a button. Therefore, identifying commands allows developers to implement actionable logic and infrastructure needed to handle user requests effectively.
For more information about Commands in an Event Sourced application, read our article on CQRS and Event Sourcing.
Designing Projections and Read Models
Another stage of the Event Modeling process involves designing projections and read models. While other parts of the event modeling process focus on how events impact the state of the application, projections are read-only views that reflect the system’s current state, as it’s continuously updated by these modeled events. Projections are designed to facilitate queries by exposing important data in a format accessible to users.
A projection is specifically tailored to meet particular query requirements or to provide insights into the system's current state. Projections are derived from events and represent the accumulated state of those events over time. They are continuously updated as new events occur, ensuring that the data they present is always current.
For instance, imagine a banking system where numerous transactions like deposits, withdrawals, and interest accruals affect a customer's account balance. A projection might sum up these events to present an up-to-date balance view. The key here is that projections translate raw event data into meaningful and actionable representations without necessarily adhering to the structures of the original event data. For obvious reasons, it doesn’t make sense for bank customers to read a historical list of all bank transaction events in order to know their current balance. The projection simply derives and provides that information for them.
A read model has a custom projection of events, and the resulting data is offered through push and/or pull semantics. While a projection provides a general view of data, a read model structures this data specifically for efficient querying and retrieval purposes. Read models are designed to facilitate particular use cases, often incorporating indexed data structures and other optimizations tailored to the application's query patterns.
Consider the same banking scenario: a read model could be designed to quickly retrieve a customer's transaction histories. It would index transactions by date and type to allow swift queries, enabling users to pull up comprehensive transaction logs in an instant. This is crucial for functionalities that require robust data retrieval, such as generating monthly statements or performing audits.
Read models are also useful when you need to present data in various formats across diverse platforms, like mobile apps, web dashboards, or reporting tools. Each platform might have its own read model optimized for its specific needs and user interaction patterns.
So what’s next?
Event Modeling represents a significant advancement in software architecture, enabling developers to capture and visualize system events clearly and effectively. Through the structured approach of modeling events, defining commands, and designing projections, teams can create responsive and resilient applications. The shift from monolithic architectures to event-driven designs empowers organizations to adapt to changing demands efficiently and maintain high-performance standards.
As businesses embrace digital transformation, Event Modeling's relevance becomes increasingly prominent. By employing this practice, teams can ensure their software systems are not only robust but also positioned to respond to user needs appropriately. Is your organization ready to implement Event Modeling and explore the full potential of your software architecture? The journey promises to yield immense benefits.
Read our Playbook to learn how to model the events within your first application.
Learn how to create your first Event-Driven application in Java with this tutorial.
Read this article about creating a Query Model in Java.