EBI Software Architecture
This article is a kind of POC to find out what is EBI Architecture, how we can use it, etc. so I have tried to read and find good sources about EBI Architecture and share them here with you. so let’s talk about it 🙂
In the history of software architecture, all the mindsets, methodologies, perspectives, and ideas were developed to create a platform or software that is flexible, scalable, and cost-effective to develop. It’s difficult to build everything from scratch again, which is what most companies avoid doing.
By using EBI architecture, the structure becomes cleaner and more flexible. By doing this, each entity is no longer dependent on the other. Let’s go through how it works.
EBI is a modern application architecture. Its goal is to separate business logic from presentation logic. With an EBI architecture, by creating different delivery mechanisms, the same business logic can be used on many platforms.
Marko Malinen has a very good thesis about Using EBI Pattern in Conjunction with Service-Oriented
Architectures and he focused to evaluate the quality of the architecture resulting from the combination of EBI and SOA patterns.
SOA provides constraints and guidelines on how the services should be orchestrated whereas the EBI provides guidelines and constraints on how the system should be split into modules in order to keep it maintainable and testable.
The Clean Architecture
Before talking about EBI, let’s talk about clean architecture which is very important. this term used by Robert C. Martin in his talks and writings concerning software architectures. it refers to an architecture that follows the rule that makes these architectures work: the dependency rule.
The boundaries between the layers should be crossed in a way that the dependency rule is not violated. This means that the inner layers are not allowed to to direct calls into upper layers. That is to say, the source code dependencies should always points inward.
The workflow arrow shows how the controller in the interface adapters layer communicates with the use case interactor of the use cases layer.
Then the use case interactor communicates with the presenter of the interface adapters layer. The use case interactor has no dependencies with the interface adapters. This is achieved by using the dependency inversion principle (DIP)
- High-level modules should not depend on low-level modules. Both should depend on abstractions.
- Abstractions should not depend upon details. Details should depend upon abstractions.
As you can see in the figure above, when the interactor needs to communicate with the presenter, Instead of making direct call to the concrete presenter class, the interactor calls some thing that implements the use case output port interface. The dependency rule is not violated.
The important thing is that the entities are not passed across the boundaries as such. This would violate the dependency rule. Outer circles should pass data in the form that is most convinient for the inner circle.
Principles of EBI
The software that is build according to the EBI patterns consists of three basic elements: entities, boundaries, and interactors. Interactors are objects that are invoked when the user uses the software. In other words they implement use cases. This is called as use case driven design. The whole system is controlled from what the user wish to do with the system. If the functionality of the software system requires changes, that is, the use case changes, the developers see directly which interactor needs to be changed.
The essential parts or building blocks of the EBI pattern are presented in the following list:
- Entity: Entities represent business objects that have application independent business rules. This means that no matter where they exist they always encapsulate the same business rules. All the application-agnostic business rules should be located in the entities.
- Interactor: manipulate entities. Their job is to accept requests through the boundaries and manipulate the application state. Interactors are the business logic layer of the application: interactors act on requests and decide what to do with them. Interactors know of request and response models called DTOs(data transfer objects). Interactors are concrete implementations of boundaries.
- Boundaries: are the link to the outside world. As you see in the above figure, the request boundary is an access point to services that the interactor implements. Whereas the reponse boundary is the interactor’s way to send the possible results of the request that was made. The third boundary is the Entity gateway. It is an access point to the system that stores entities.
In Clean Architecture, these boundaries represent the boundary between the interface adapters layer and the use cases layer. These boundaries enable compliance with the DIP.
A boundary can implement functionality for processing data for a graphical user interface or a web API. Boundaries are functional in nature: they accept data requests and produce responses as result. These abstractions are concretely implemented by interactors.
A delivery mechanism is something that delivers requests to the application and takes response messages from the application. For instance, it can be a web framework or it can be a desktop application or some testing framework.
The interactor should be named according to the use case it implements (Martin). For example, if the use case is called ‘List customers’ the interactor class that implements this use case should be called ListCustomers or equivalent. The use case driven-design makes the architecture more traceable in situations where the architecture requires changes.
By decoupling the application from external agencies, the architect can defer decisions such as what framework or database should be used. In the EBI pattern, all dependencies point inward, meaning the application has no external dependencies. This gives flexibility to the architecture. It will also make the application easier to test.
How does EBI architecture differ from MVC?
- The EBI architecture is that the business logic of the application is designed to be platform-agnostic of its delivery mechanism. The business logic parts, interactions, and entities do not know in which medium they’re being accessed. It could be from a web server, a unit test, or a GUI application.
- In MVC, there is always a dependency on the delivery mechanism. No matter how hard you tried, you cannot tear the Controllers out of the web world.
The same way in the MVC pattern the Model represents the whole back-end, all the entities, services and their relations, the EBI pattern sees the Boundary as one complete connection to the outside world and not just a view, a controller or an interface (the language construct). The Boundary represents the whole presentation layer which in MVC corresponds to the View and the Controller. The Entity in EBI stands for actual Entities who hold data and their associated behaviour, while the Interactor objects make the connection between the presentation layer and the Entities, they are what I would call Application Services and Domain Services.
The EBI pattern is to the back-end what MVC is to the front-end. They are not an alternative to each other, they are complementary. If we would put them together in a single pattern we could call it something like View-Controller-Interactor-Entity.
Implementation of EBI
Marko Malinen in his thesis tried to describe how we can implement the EBI architecture.
The figure shows how the interactors and entities can be hidden behind the boundaries. The delivery mechanism uses a request boundary that is implemented by the interactor.
- The response boundary is implemented by the delivery mechanism. The delivery mechanism has dependencies on boundaries but nothing in the core system depends on the delivery mechanism.
- The interactor uses the entity gateway to access preserved data from some system that implements the entity gateway boundary. (same as response boundary)
- The application itself is completely decoupled from the implementations of the request and gateway boundaries
There are two kinds of messaging boundaries in the EBI pattern: request boundaries and response boundaries.
Request boundary is an interface that hides the actual implementation of the interactor from the delivery mechanism. The request message or model itself can be, for example, some kind of simple data structure. It should not contain any logic and its only purpose is to store necessary data so that interactors can reason the meaning of the message.
A response boundary is an interface through which the interactor can interact with the delivery mechanism. The interactor sends all the response messages through the response boundary.
And now it’s a good time to talk about code-level implementation, for example, I want to create an application for managing my todo-lists and can define all of the parts according to the EBI structure,
The below code-level structure was created by Antoine Kalmbach and he describes it as follows:
it is good practice to separate the EBI architecture itself into five different layers. These layers correspond to namespaces or packages in your language of choice:
- The Host layer implements a physical manifestation of the API, e.g., a web server
- The API layer is the interface to the program itself, which accepts input and translates it into DTOs, passing them to
- The Service layer contains boundaries and response and request models.
The service layer is the common language of the application architecture. When the API and core speak to each other, they do so via an abstract boundary. They use DTOs (data transfer objects), simple structures of data, for communication.
DTOs have no business logic. Think of them as language constructs around simple requests not dependent of any protocol.
- The Core layer contains a concrete implementation of the service layer. The core layer contains actual business logic.
- Interactors that implement boundaries and form the core business logic of the application. Interactors contain rich business logic. They can manipulate entities and they implement boundaries.
- Entities that represent the data models of the program. Entities are completely invisible to the outside layers. Not any thing but the interactors know about them. Entities contain business logic.
Thus, when a program is constructed, the API is built top-down using dependency injection. The Host layer is the one doing the DI of the concrete interactors.
The interactors do not know what protocol their requests come from or are sent to, and the API doesn’t know what sort of interactor implements the service boundary.
According to the Single Responsibility Principle, an interactor should only do one thing, and one thing only. They should operate only one aspect of the business logic.
In the next Article, I’ll implement a simple app based on the EBI architecture.
References & Other sources
- Using EBI Pattern in Conjunction with Service-Oriented Architectures
- EBI Architecture – Herberto Graca
- Screaming Architecture – Robert C Martin
- Structuring Applications – Antoine Kalmbach
- Entity-Boundary-Interactor (EBI) pattern is inspired by Robert C. Martin’s speech. The EBI is based on the ideas of Ivar Jacobson that he presented in his book ‘Object-Oriented Software Engineering: A Use Case Driven Approach’ (Jacobson 1992)