Abstract: Architectural Pattern, MVC, Test, Decoupled, Controller, View, Model
The traditional MVC design pattern is a common way to organize your code. There’re three main roles: Model, View and Controller. So, all the entities are decoupled with their role, and they have a way to communicate with each other. However, Apple uses a variation of MVC. By using the Apple’s MVC pattern, you only create a Massive View Controller because the View is totally tied with the Controller.
The View and the Controller are in the same file. The UIViewController is composed from the View and the Controller 😁, and all the view’s life cycle is there: viewDidLoad, viewWillAppear… and all the business/presentation logic. So, we end up creating a Massive View Controllers with many responsibilities: responsibility for the data source, delegates, interaction with our API REST, Core Data, Socket or any other repository.
Where do I put network code? Where do I put datasource code? Where do I put business logic? Where do I put presentation logic?
That’s why I stopped using the basic architectural pattern that Apple uses in their guidelines. I used to using it, until I saw better pattern designs. I’m gonna talk about them during the next weeks. This post only covers the MVC that Apple manages in their guidelines.
With the Apple’s MVC it’s hard to see the Single Responsible Principle, hard to test the code (it’s easier to test it with other architecture patterns such as MVVM or Viper) and hard to reuse the code. We want the Model, the View and the Controller to be decoupled. That means that we don’t one entity to know about the other ones. This way, we can reuse the code (this would be the perfect scenario)
Cocoa MVC
- The View sends interactions to the Controller.
- The Controller is the class, in which the business logic takes place and have the possibility of updating the Model or not (i.e it can send an API Request to see the result in the View)
- The Controller is the mediator between the View and the Model.
- The Model notifies the Controller the new changes, and these changes are updated in the View.
The Controller is the least reusable code, because it provides code to interact with both the View and Model. The View and the Model are decoupled. They don’t know about each other, only about the Controller.
But this is only in theory. In practice, the next figure shows the MVC variation that Apple uses in their guidelines.
Realistic Cocoa MVC
The picture illustrates that the View and the Controller are the same, are tightly coupled (as I mentioned before)
In fact, who many of you have used this code before?
The last snippet shows the knowledge from View towards the Model, so the MVC’s rules explained before are totally broken. The View and the Model must be decoupled, the controller must be the mediator, but Apple uses the View and the Controller in the same class (UIViewController), so, all this logic are smashed.
The Controller is the only one that knows about the View and the Model, so the Controller must configure the Publication Cell and not the View. This increases our code within the ViewController, tending to have a Massive View Controller.
With this bad distribution, creating tests for that massive class and mocks for the view will be tedious. In further blog posts, I’ll explain more about MVVM and how easy it is testing in that kind of architecture pattern. (with Nimble and Quick or Expecta and Specta).
Summary
- Separate de UI from the business logic.
- The View and Controller are totally tied in UIViewController.
- Bad testability.