MVC – MVVM – VIPER
MVC – MVVM – VIPER are three design patterns that can be used for iOS development, I am going to explain you the differences and their benefits. You can be also interested in MVP or VIP, but for me they are respectively one step behind MVVM or VIPER, then I will not describe them.
To illustrate this article, I will take an example of a screen that displays a list of movies, on tap, it will display a movie detail screen. I will not speak about the model which should be simple objects which represents your data.
– MVC –
If you have developed for iOS, you already know MVC (Model View Controller) which separates the data model from the logic of a screen (business logic, user interaction and view lifecycle).
Here, you will only one class:
– MovieListViewController which has no public method (except inherited ones)
MVC pattern assumes that you should have 3 classes, Model, ViewController and View. Last one can be a nib (from Xib or Storyboard), a separate custom view or created by code in the controller. The model should represents data plus contains the logic. But most of the time the controller contains view logic and business logic that leads to decrease the quality of testing and lowering the code coverage. An other drawback is that MVC can become a Massive View Controller. One class is responsible for everything. In worst case you can even see api call in View Controller :O
– MVVM –
Because of That, MVVM (Model – View – View Model) pattern is a bit better, separating business logic from User interaction and view lifecycle.
Here, you have 2 classes:
– MovieListViewController which has no public method (except inherited ones) – View in MVVM
– MovieListViewModel which has 2 public methods (one for getting movies and one to present detail screen) – View Model in MVVM
This is one step ahead than MVC, but it’s mostly moving the whole logic from one file to one other file, it improves testing, but still the View Model has multiple responsibilities.
– VIPER –
With the idea of the SOLID principle, one responsibility VIPER was born, splitting the logic, Routing, fetching data, handling user event and view lifecycle.
Here, you will 6 protocols (5 plus one I like to add):
– MovieListViewInput: updateView(with: [MovieCellViewModel])
– MovieListViewOutput: viewIsReady() and didSelect(viewModel: ViewModel)
– MovieListInteractorInput: fetchMovies()
– MovieListInteractorOutput: didReceive(movies: [Movie])
– MovieListRouterInput: showMovieDetail(movie: Movie)
– MovieListModelsFactory: createMovieViewModels(movies: [Movie]) -> [MovieCellViewModel] (not part of viper pattern but very convenient)
And 7 classes:
– MovieListBuilder with a build method responsible for creating and connecting all objects belows (not part of viper pattern but very convenient)
– MovieListViewController which implements MovieListViewInput responsible for User interaction and view lifecycle
– MovieListPresenter which implements MovieListViewOutput and MovieListInteractorOutput
– MovieListInteractor which implements MovieListInteractorInput responsible for fetching movies
– MovieListRouteur which implements MovieListRouterInput responsible for displaying detail screen
– MovieListModelsFactoryImplementation which implements MovieListModelsFactory responsible for creating cell view models from movies data object (not part of viper pattern but very convenient)
– MovieService which makes api call (not part of viper pattern but used by the interactor which can have multiple services)
To have a better understanding, have a look at the sequential diagrams
When the view is loaded, the viewController tells the presenter that the view is ready which contacts the interactor to fetch the movies. The interactor use the movieService to get movies (in that case makes an api call). Once the movieService got the movies, it gives them to the interactor which gives them to the presenter. The presenter uses the factory to create the cellViewmodels to update the view of the viewController.
Handling user event:
When the user taps on a cell, the view controller gives the presenter the selected view model. The presenter gives the corresponding movie to the router, which creates the next view controller using the builder of the next module (detail screen). Then, the router uses the navigation controller of its viewController to pushed the new viewController on the stack.
Working with input and output protocol, you can mock and test each class easily and independently. You can also replace any one of them by a new implementation without changing everything. One more advantage is splitting theses responsibilities make splitting tasks for developers easier (differents developers can work on different part of the module).
For all theses reasons I really recommend Viper. This article goal is to introduce you others patterns than MVC, for more details please have a look at these links: