Tackling Restbucks with Clean Architecture, episode 2
Posted by Sourced Blog on March 4, 2018
2032 words, 11 minute read
In the first part we tackled creating the necessary use cases and the REST interface for the Restbucks application. In this episode we’re going to implement the application layer and the communication with the domain layer. The domain layer is where most of of the logic of your application will reside. It enforces the business rules of your domain and defines the data structures and behavior of that domain. The implementation role of the application layer is to retrieve domain entities and perform the necessary domain operations in order to fulfill the use case.
In this example, we’ll use events to signal the wanted domain behavior, so we’ll end up with an event-driven application. This will allow us to decouple the domain behavior from the implementation details later on. For example, instead of saving an entity through a repository, we’ll send an SomeEntitySaved event, which can then be handled later on in the infrastructure layer handling the persistence. This is one way of doing it, the more direct approach is to have interfaces in the domain layer that are implemented later on in the persistence layer. How you choose to build your application is completely up to you.
The domain in this example is quite simple. You have an order with items and there are a couple of actions that can be performed on the domain object that can change the state of the domain object or invoke some sort of a behavior.
As you can see, this domain object’s behavioral methods don’t only change their state and check the logic, but also send events at appropriate. So from an event perspective, there are 4 events that can happens in the system.
With regards to using some sort of event infrastructure framework, there are a couple of options. Axon for example is a quite good framework for building an event-driven application. I however use a very simple implementation that does most of the heavy lifting.
This way my event publishing can also be nicely decoupled from any of the technical frameworks and once again deferred to an infrastructure layer. To give an example, if you wanted to use the Spring event mechanism, you can use the following classes to implement that support.
However, you can just create a very naive implementation to make sure everything still starts.
The last part of the domain layer is a way to retrieve domain entities in our application layer, the gateway. In this example, the gateway doesn’t need to retrieve much in order to achieve the use case goals (just enough will do).
Now that we have our domain implemented, we can use this to implement the use cases we defined earlier. As most of the behavior is contained inside the domain layer, this implementation is very straightforward. The most elaborate ones are CreateOrder and GetOrders, as they require some mapping between the domain model and the response model.
As you can see, I’m also using Kotlin’s extension method mechanism here. It makes the code a bit nicer to read, in my opinion, but feel free to choose you own style that suits you best. The other use cases merely get the required domain instance and call a method on it, for example.
The only thing that’s missing to get the application to run once again is a mock implementation of the OrderGateway.
So now we have implemented the web layer, the entire application layer and the domain layer. All that’s left is implementing the persistence layer, which I’ll cover in the next episode.