As iOS developer you start by learning all the tools and components you will need to build the application from the ground up. But then you get introduced to a concept of the app architecture and of course MVC pattern.
Shortly after that you find out during meetups, conferences’ talks or reading architecture-related posts a common thing; they all mocking MVC. Moreover, they call it MassiveViewController. What a bad thing!
Today we will take a closer look at all of this and decide whether MVC is not good as they told you so.
MVC stands for “Model-View-Controller.” MVC is an application design model comprised of three interconnected parts. They include the model (data), the view (user interface), and the controller (processes that handle input).
The MVC model or “pattern” is commonly used for developing modern user interfaces. It provides fundamental pieces for designing programs for desktop or mobile, as well as web applications. It works well with object-oriented programming since the different models, views, and controllers can be treated as objects and reused within an application.
Below is a description of each aspect of MVC:
- Model: is data used by a program.
- View: is the way of displaying objects within an application.
- Controller: is updating both models and views. It accepts input and performs the corresponding update.
The three parts of MVC are interconnected (see diagram). The view displays the model for the user. The controller accepts user input and updates the model and view accordingly.
What MVC promises us?
- Separation of Concerns The advantage of the MVC pattern is a clear separation of concerns. Each layer of the MVC pattern is responsible for a clearly defined aspect of the application.
- Reusability View and model objects are easy to reuse.
- In modern applications what goes into controllers is often less clear. This yield of having a controller that is consistently used for everything that doesn’t clearly belong to the view or model layer.
- Controllers are often not reusable and with unclear logic that goes into controllers this will make the code less reusable.
So I think the main problem here is unclarity. We need more guidelines to tell us where to put keyboard handling, networking calls and so on.
What should we do?
There is no such thing as right and wrong when we talk about approaches to solve a specific problem. An approach, in the end, is a collection of best coding practices of someone. Which may fit in certain problem and may not fit in another. There are no solutions that fits all.
Introducing MVC-N. We are doing Model View Controller (MVC), but we need to take MVC a step further.
So there is another controller, but not a ViewController. I do not like the word “controller”, so let’s call it “manager” or “handler” anything works fine.
But you should understand two things first that it is a controller object because it is not a view and not a model. Second, that is what we should be doing at design time, not 5 hours before shipping your app.
When an application needs data from the network, and you confused about where should implement this, this is where the MVC-N comes in.
Instead of duplicating your networking logic. MVC-N creates a network client to handle the networking logic.
Basically we’ll add a new class that has all the networking calls, input validations, error handling, data sterilization and validation after that we should tell the controller that we finished this request using a callback closure.
Here is a great article to help you build your own network client.
This is a good approach if your app depends heavily on networking requests. But you should know this approach has a drawback, it adds more complexity and time to the designing period.
Introducing MVC-S. Stands for Model View Controller-Services. This is not a design pattern it’s more like a collection of patterns to help avoid Massive view-controller syndrome.
Whenever you group a punch of code under
//MARK: - ... you should consider moving it to a new service.
The delegation pattern enables an object to use another “helper” object to provide data or perform a task rather than the task itself. This pattern has three parts:
- A delegate protocol, which defines the methods a delegate may or should implement.
- A delegate, which is the helper object that implements the delegate protocol.
- An object needing a delegate, also known as the delegating object. It’s the object that has a delegate.
By relying on a delegate protocol instead of a concrete object, the implementation is much more flexible: any object that implements the protocol can be used as the delegate!
Of course, this is increases complexity but it helps a lot with breaking large classes and make reusable components.
Delegates are extremely useful, but they can be overused. Be careful about creating too many delegates for an object.
Coordinator pattern can help you achieve a single responsibility where your classes perform one specific task. So for controllers that’s mean doing one thing only that is controlling your view. And help to remove code that doesn’t belong to it.
We will remove all segues from storyboards and any navigation code from your UIViewController. A view controller shouldn’t be concern about the places it can go to. That’s right there is no
prepare(for segue: UIStoryboardSegue, sender: Any?) anymore.
There are three easy steps to follow the coordinator pattern. First, create a coordinator protocol that defines basic properties and functionality to be a coordinator.
Second, create a concrete implementation of that protocol to be able to actually use it.
Last, when you need to perform navigation you delegate it to your coordinator.
What coordinator really does is removing navigation out the view controller and that gives us a lot of benefits, for example, no duplication when creating the same view controller from different sources, true isolation for your view controller that leads to cleaner, decoupled and reusable code.
However, memory management is a major concern when it comes to coordinators and when to release coordinators and how to detect that. You should be very careful when using this pattern.
Modal-View-Controller with Coordinator plus few other famous design patterns such as Composition and Dependency Injection allow to develop modern complicated applications and avoid Massive view-controller syndrome
This is becoming more complicated than what we started with. But the source code of the project is cleaner, more maintainable, reusable and testable.
Don’t get me wrong, plain MVC is fine and doing the job I think it gives you the liberty to go and add layers and services as much as you need but With freedom comes responsibility and this is the tricky part. You should know what you are doing and choose wisely depending on your timeframe, project scope and teammates’ backgrounds to find that sweet spot.