Since my last post about why I don’t use a pure repository pattern in Android I received some feedback and I want to explain how I organize my domain layer.
What should be my domain layer
Everything. No, seriously, everything that are decissions that your app makes in order to request data must be in this layer. If your domain layer is rich your controllers/presenters should be so simple like directly calls to your domain. For example, domain logic are form validations, algorithm calculations, etc..
Deconstruction of a domain layer
In an application based on use cases I have the domain separated in Outter domain and Inner domain. This two concepts are pretty simple to understand:
- Outter domain are your interactors, those pieces of code don’t have domain rules, it only coordinates actions and makes your domain logic “Public” to the rest of your layers by using those actions.
- Inner domain is composed of Domain Services and Infrastructure services. Basically an Interactor calls a Domain Service and this Domain Service communicates with your Network, Database, makes calculations, provides rules for your form validations etc… If you need something from your infrastructure (find your current location, send an email…) you can call an Infrastructure service. This doesn’t mean that your inner domain can only contain those 2 figures, your domain can have Objects that help your logic to be organized.
We can define an interactor as the implementation of a use case that makes only one action. It does not contain the domain logic directly because it coordinates various calls in order to make the action. It’s named with a Verb + Noun and it’s Public to the outter layers of your architecture.
Anatomy of inner domain
My Interactor communicates with inner services in order to perform those actions, but it can call various domain services if needed. Here is a sample interactor that modelates the creation of a product in the Selltag app flow:
As you can see it coordinates various actions, first it calls a Login domain service to get the current user status, if it’s logged in, then it calls a Validator that is a simple object with some rules that decides if this product is a valid one, it can be rules like if it has title, the price is greater than zero, etc.. With these 2 preconditions then it decides to call the Product Creator domain service that talks with an infrastructure service in order to get the current user GPS coordinates. When it has all the data to create the product the Product Creator domain service calls some boundaries in order to complete this action.
The way to communicate with the network and data layers is with an interface that defines the boundary between your domain and the outside world. This allows us to keep our domain decoupled from the concrete implementation of the data retrieval objects.
This action makes some complex things in the middle and maybe you want to keep the user informed with exact data to let the user decide what to do in case of a failure in some of the middle actions. You can throw some custom Exceptions and return those exceptions to your controller/presenter to present different messages or customized actions to recover from a problem.
References and further info
- Eric Evans – Domain Driven Design
- Sandro Mancuso (Codurance) – Interaction Driven Design
I’m working on an example that demonstrates this concepts but I wanted to post this to receive feedback, so if you have to tell something you are very welcome!