I have been doing iOS development using MVVM and dependency injection for a couple of months and I am really happy with the results. The code is so much clear and easier to test. But I have been stragling with a problem which I haven’t found a solution that I felt really confortable with.
In order to understand the problem I want to give you a little bit of context. The last app that I have been working was architectured in the following way / layers:
- View models
- View / View Controllers
- Services: Classes that know how to deal with external services like Twitter, Facebook, etc.
- Repositories: A repository is class that knows how to interact with a resource of the application’s REST API. Lets say that we have a blog application, we could have the users resources and the posts resources. Each of thoses resources have several method. There is a 1-to-1 relation between the resources and the repositories.
When the applications starts we have a Bootstrap class that initializes the app and creates the main view model. We have a restriction that only view models can create other view models. For example in the case of having a view that contains a list of elements (in iOS it will be represented with a UITableView) and the detail view for each of thoses elements that is presented by pushing it to the navigation stack after tapping on the element in the list. What we do is make the view model that is attached to the table view controller create the detail view model. The table view controller listens to the table view model and then presents the detail view model by creating the detail view controller and passing it its view model. So the view controller does not know how to create a view model it only knows how to create a view controller for that view model.
Is the responsability of the parent view model to the pass all the dependecies to the child view model.
The problem comes when a view model that is very deep in the view hierachy needs dependencies that its parent controllers does not require. For example a service to access some external web service. Because its parent does not have that dependency it will have to add it to its dependecy list, thus adding a new parameter to the constructor. Imagine how this goes if the grand parent does not have the dependecy either.
What do you think is a good solution? Possible solutions:
- Singletons: Harder to test and they are basically gloabl state
- A factory class: We could a set of factory that knows how to create certain types of object. For example a ServiceFactory and RepositoryFactory. The service factory could have method to create services like: TwitterService, FacebookService, GithubService. The repository factory could know how to create a repository for each of the API resources. In the case of having a few factories (2 or 3) all the view models could dependent on this factories.
For now we have chosen the factory class solution because we don’t need to use singletons and we can treat the factory as any other dependecy which makes it relatively easy to test. The problem is that it kind of feels like a good object and by having a factory you don’t actually know which is the real dependecy that needs the view model, unless you look inside the constructor’s implementation to check which factory methods are being called.