The User Profile
Image that we want to implement a new super-cool feature called User Profiles 😎. With this feature users of our app will be able to save their names and photos, isn’t that cool! We can start from a data model.
Our UI should look similar to this one.
But before showing a photo or name on the screen we have to get them from somewhere. So we need to implement a functionality of obtaining these data and encapsulate this functionality in some object. We call this object a service.
Why not just implement this functionality in our interactor (if we prefer RIBs or VIPER) or in a view controller (if we more like MVC)? We could do this, but what if we want to get a photo and name not for one MVC/VIPER/RIB module?
Maybe we have one more screen with the photo and name of our user? A chat screen, for instance.
Instead of implementing this functionality twice (in the user profile’s interactor and in the chat’s interactor), we could encapsulate it in some service which then be reused.
This service may have two methods.
We use the protocol instead of a concrete class because we don’t want to limit ourselves to specific implementation leaving the possibility for dependency injection.
Then we simply connect the info service to as many interactors as we want.
But what about the concrete implementation of info service’s methods? In the first one
obtainUserInfo(completionHandler: @escaping (UserInfo?) -> Void)) we can use Core Data stack or Realm to get our data from the persistent storage. Or we can use our networking layer for receiving the data from our backend.
Both of these two core components can be reused by other services.
Thus we have three layers: a presentation layer, a service layer, and a core layer.
A presentation layer consists of MVC/RIB/VIPER/MVVM modules.
A service layer consists of services: objects that encapsulate some business logic and functionality. These objects are reused by modules from a presentation layer.
And core layer consists of core components like Core Data stack, backend API provider, credentials’ provider, etc. These core components are reused by services from a service layer.
But how do we connect all these things? This is where assemblies come into play.
Assemblies are objects that facilitate an assembling of components from our layers as well as connecting these components to each other.
We’ll have one assembly for each layer. A core assembly assembles our API provider, Core Data stack, and other core components. A service assembly assembles our services and connects these services and core components. A presentation assembly assembles our MVC/RIB/VIPER/MVVM modules. Also it connects services to interacators of our modules (if we use RIBs/VIPER) or models of our modules (if we use MVC/MVVM).
And the final assembly is a root assembly. It is responsible for assembling the previous three assemblies.
The example project which demonstrate this approach can be found here.
This is the test project I’ve created to apply for the new job (since it was required as part of the applying process). I don’t use MVC in this project. Instead I use my own design pattern called RIV (it’s very similar to Uber’s RIBs but without builders and viewless modules 😎).