In previous articles, I’ve hinted at our ESE architecture and how it stands apart from the traditional MVC setup. Now it’s time to dig in and explore what makes ESE both unique and refreshingly simple. It’s a structure inspired by the way our human bodies function.
Let’s take a break from talking about software and think about the human body for a moment.
Now, back to the world of computers. At its core, ESE (Exposition-Service-Effect) is a backend architecture that emphasizes a clean separation of concerns, making it easier to manage, test, and scale the different parts of a system. But what exactly do these layers do?
This structure replaces the traditional MVC controller:
In a typical MVC controller, you’d find both input management and business logic combined. The controller might directly interact with models, handle business logic, and render views. In the ESE example above, the Exposition layer only manages the request and delegates all logic to the Service layer. This leads to a cleaner separation of concerns, making the system more modular and easier to maintain.
Another key feature is that the Exposition layer can handle multiple sources of events and protocols:
From a development perspective, I was never satisfied with having to handle different input sources in different ways. The Exposition layer streamlines this by centralizing all inputs and dispatching to the Service layer, whether it’s an HTTP response, an event, a background job, or a cron task.
In Pulse and Verse, we provide a base Service class (Verse::Service::Base) that handles the authorization context (similar to current_user in Rails) and passes it to the Effect layer, which is in charge of dealing with access rights. But that’s a topic for another article on our approach to authorization management.
You might be wondering how ESE compares to the more traditional MVC (Model-View-Controller) architecture. While both aim to separate concerns, they approach it differently.
In MVC:
In contrast, ESE is more modular:
This separation leads to cleaner, more maintainable code and makes it easier to scale complex systems.
A major pain point in MVC is having models handle both logic and effects, especially with mixed-level teams of developers. For instance, mixing query building with business code is a bad practice because it’s hard to determine query performance, as the query might be built incrementally within the business logic.
Another significant advantage of ESE is testing. You can easily replace the Effect layer with a mock version to test if your logic holds up, resulting in tests that run in microseconds without dependencies on other systems, instead of seconds. This is especially valuable in large applications, where this difference can translate to saving up to 45 minutes a day in productivity. And yes, this is a number I’ve experienced.
We opted for ESE over MVC because it offers a more modern and modular approach to handling complex backend systems. By separating business logic from data concerns and outcomes, ESE allows us to build systems that are easier to manage, test, and scale.
In the next article, we’ll dive into why we chose Redis Stream over NATS, RabbitMQ, or Kafka for maintaining our Event Bus. Stay tuned!
Proudly awarded as an official contributor to the reforestation project in Madagascar
(Bôndy - 2024)