iOS Architecture: MVVM-C, Services (6/6)

Daniel Lozano Valdés
Sudo by Icalia Labs
4 min readOct 4, 2017

Service Layer

The service layer is a design pattern that has been around for decades. It is based on the concept that a system should be separated into different layers, like an onion, with different responsibilities on each of each of those layers. The service layer should be the connection to the outside world, whether that be a database, a remote server, a bluetooth connection, etc.

In that service layer there should be multiple Services and each one of those should have a single responsibility of dealing with a specific kind of service or resource.

That’s basically it, it’s actually a simple concept, and we are probably already using it in one way or another in our app. We usually have an ApiClient class that deals with a REST API on a server for example. But the point I want to make, and the reason this fits in well with the architecture we’ve been building throughout this series, is that we should organize and architect this layer to take the most advantage of it.

Let’s continue working on the ApiClient example. All of us are probably already familiar with the concept of an ApiClient. We build an object that has the responsibility of making HTTP requests, either based on Apple’s URLSession or some other framework. But that should be it, that should be it’s sole responsibility. It should have no knowledge of our models and our business logic.

So if all that business logic can’t be in the ApiClient, and most definitely should also not be in our lower ViewModel/View layers, where should it go? That’s where the Service layer comes in.

A Service implementation

A service will usually wrap around some sort of client, in this case an ApiClient, and add all the the model parsing and business logic on top of it. We might be tempted to create just one ApiService to handle all of the API needs in our application, and in a really simple app it might work.

But what I recommend is that we separate Service’s, even if they are of the same kind like in this example, by logical units. For example, you might have a SessionService which deals with login/signup, and a PostService that deals with posting pictures up to your server.

This way, when a ViewModel get’s injected with the Service it needs it is getting a specific Service that deals only with the needs of that specific part of the application. Again, SRP.

Let’s see some code

This is an abbreviated example of a really simple service. A PlaceService that let’s us search for places on our API.

We start with a protocol that outlines the action’s we will call on this service. Having a protocol here is really useful because we might want to switch out the implementation that does these same action’s but with a different source, like a different API or cache. Or, as always, it makes testing much easier.

Afterwards, we move on to an implementation. In this case its the PlaceApiService. Because it’s going to use an API to fulfill the protocol. But we will be dealing with the protocol type almost everywhere in our app, the implementation will be hidden from us.

There’s two parts to this code:

  • We must take in any clients we will need to perform our actions.
  • Then we must implement our Service protocol. In this case we internally use our ApiClient to fulfill the protocol making requests to our API. Here is where we should know what model’s there are, what endpoints will be used, what parameters, etc.

Don’t worry if you don’t follow my implementation of these methods, it is just meant to give you an idea. You should do whatever it is you need to do to make these requests here.

Usage

Then in your Coordinator you have to set up this service and pass it on to your ViewModels for usage. Since our Coordinator already has an ApiClient that was passed onto it as a dependency, it can use that to create the Service.

In this example whenever we create this ViewModel, we create a concrete implementation of a PlaceService and initialize the ViewModel with it. Remember, the ViewModel should depend on the abstract protocol for the service, only the coordinator which is responsible for setting up dependencies knows about the concrete implementation.

Conclusion

Although these last two parts of the architecture are not the most important parts and they are not part of the architecture name, I think they really round the architecture out and make it very complete.

This architecture implementation was arrived to after learning about many other architecture implementations, and by organic iteration using it in many production apps. Altough it is pretty solid and has been used in major production apps, there is definitely room to improve and add other concepts to it.

Take a look at the diagram again to see if clicks! Let me know.

MVVM-C

--

--