Data providers composition in swift
Data providers (or services) are used very often in mobile apps. In this article we will see how it's possible to combine data providers to create complex data receiving rules, but keeping flexibility. It's desired to have a solution which allows to easy update and rules for providing data and be changes-welcomed.
DataProvider is a simple protocol to demonstrate the idea. Type of items is chosen as String just for simplicity, but it can be updated with any other actual data type. Of course, we might use generic types, but let focus on the main idea for now.
Let’s have an example. We have initially API data provider and data was successfully received from API. Typically it has this kind of implementation in our iOS app:
But what if product owner ask us to add additional result checking and if getting data from API is failed, try to get data from database or cache. To implement this requirement the obvious approach is to add this check right into APIDataProvider, but this will break Single Responsibility Principle and make our code less robust and more errors-prone. And besides that, how will we expand that solution what if in future we will be asked to add additional check and one more way of getting data?
Let's imagine that we may combine usage of multiple data sources and give this combination as data source to the module. Conceptually the code should look like this
Data provides should be created in composition root module or fabric module where scene is created. As extra benefit, this flexible solution also will allow us to use strategy pattern, update fallback rules easily use different providers combination depending on external conditions.
First of all, we need to create FallableDataProvider to be able to set fallback.
And after that make every our data provider make compliant to FallableDataProvider protocol. For testing purposes GenericDataProvider was created .
Function setFallback returns value of given fallback for easy chaining.
Inside all our data providers we need to add extra if statement and call fallback service if it's set.
Here is test sample to demonstrate final implementation:
In this particular case data will be received from DB data provider.
Using this approach you may add your own custom rules to combine data providers and easily modify call order.