iOS: Repository pattern in Swift
In a previous post we had the opportunity to define the architecture of our app conceptually. The purpose of this post is to get deep into implementation of key components of this architecture we’re using.
In this post we’ll talk about how we implement:
Repository pattern
Repository pattern is a software design pattern that provides an abstraction of data, so that your application can work with a simple abstraction that has an interface. Using this pattern can help achieve loose coupling and can keep domain objects persistence ignorant.
It also makes code more testable as it allows us to inject as a dependency a mock repository that implements that defined interface.
In Tiendeo iOS app, this pattern allows us to abstract the domain layer from the data layer and also, inside data layer, the data repository from its data sources (web API, Realm, User Defaults, etc.).
Let’s see it in a simple scheme:
In domain layer, we define a RepositoryProtocol
that allows us to abstract domain layer (business logic) from data layer following the dependency rule as it is recommended in clean architecture. (+info)
Let’s see it with a common example:
In the example above, the use case in domain layer just has an instance of an object that implements the FavoriteRepository
protocol. This object is injected as a dependency when use case is created (+info). To use case doesn’t care about who implements this protocol, use case is abstracted from data repository.
Now, let’s see how this example continues in data layer:
In data layer, FavoritesDataRepository
implements FavoriteRepository
protocol defined in domain layer. It also has different data sources, in this case remoteDataSource
and localDataSource
, which implement the same FavoritesDataSource
protocol. That abstracts FavoritesDataRepository
from data sources implementation.
Each data source internally implements the code required for its source, remoteDataSource
makes an Alamofire request and localDataSource
uses Realm to add favorite entity to local data base.
It also interesting the way FavoritesDataRepository
can manage the different data sources. In this example, using RxSwift, we execute remoteDataSource
method and, in case the result is successfully, we execute localDataSource
method.
But there are numerous RxSwift operators that can help you in numerous cases. We talk about RxSwift operators in other post if you interested in.
Hope you found this post interesting and useful for your projects. Any question or comment will be welcome!
Thanks and good luck!!!
Related articles
In the following posts we detail other key components from our architecture: