In the past few years, I have met many projects, developers, and articles that blame the Model-ViewController architecture for many, if not all the troubles that occur in the iOS community.
Today, I offer you some alternative views and approaches, as well as techniques that can help rethink MVC and overall project management. Anyone interested is welcome under cat.
Let's start with what MVC is. We all saw this beautiful chart from the documentation:


')
In theory, everything is quite beautiful, as well as in the diagram, view sends the user action to the controller, he in turn updates the model if necessary, the model notifies the controller after the update is completed, and it also updates the view. It's simple, everything works. Using this approach, tens, if not hundreds of thousands of applications, including large ones, have been written, and I mean not only iOS, MacOS — Web applications, Windows applications, and much more has been using this approach for almost 40 years. Many of them use this approach today without experiencing any problems. The main advantages of MVC - ease of use, especially in iOS. UIViewController and its heirs in the UIKit framework provide a lot of functionality and features “out of the box“. Writing small applications requires almost no programming skills, just a couple of days of YouTube lectures and you can start. Problems begin when you need to work on large projects. There is a lot of evidence that MVC, as a pattern, scales very poorly, and this in turn leads to a problem called Massive View Controller.
Causes of the problemThe reasons for the occurrence of this problem are in my opinion 2 things:
1. MVC does not really give you clear instructions on which entities and classes you need to create and which not. Especially in iOS. UIKit MVC initially only gives you a UIViewController, and that's basically all. View exists, but not initially declared, i.e. without even creating a separate view instance, having only a UIViewController application will perform its functions. Same thing with the model. The structure and architecture of the model, as well as its interaction with the controller, remain completely in the conscience and imagination of the developer (s). This actually leads to the second reason.
2. Poor understanding of the domain domain, the inability of developers to select the necessary entities and, as a consequence, the accumulation of dependencies and functionality within the UIViewController. Those. when the developer adds new functionality, instead of creating new entities and refactoring the existing architecture, a new functionality is added to the ViewController.
Those. I want to say that the problem arises
equally due to the flaws in the architecture and inattention / negligence / laziness / ignorance / inexperience (underline) the developers.
Solutions to the first problemMVVM, MVP, VIP, VIPER, Flux (Facebook), Riblets (Viper by Uber), Clean-Swift and others, quite popular in the last few years, partially or fully solve the first part of the MVC problem. Many of them give the developer (s) clear instructions on which classes and what to create. They also make it much easier to work in a team, especially if the team consists of 10+ developers who work on the same project (for example, Uber has 150, JustEats 20+, Facebook is even afraid to take it, but definitely more than 10;)). The relief is due to the fact that the creation of a large number of isolated objects is meant, only to cover the Controller code, this in turn allows us to distribute the work within the team without much loss.
The second problem still remains. I met a lot of projects that used VIP and MVVM with view-models and presenters classes with more than 1500 lines of code containing multiple operations, ranging from parsing and maping to finishing database queries and http queries. The problem of developer inexperience or lack of understanding of the application architecture in general cannot be solved by simply changing the architectural pattern. From my point of view, there is no “golden bullet”, which will allow you to support / write large and complex projects simply “by default“. In any case, it will require effort, unit tests, good planning and time.
The part where there are tips on how to partially avoid the second problem.1.
Facilitate ViewControllerFirst of all, for good, no object in the application should be responsible for more than 1 function (Single Responsibility). For many developers, this is obvious, but nevertheless their code is far from observing such a simple postulate. For many, it is not obvious that UIViewController is the same object as everyone else, and that it should have only one responsibility - to connect the model and the view. Those. maintain the view in the appropriate model state and notify the model when it needs to change this state. Everything that goes beyond this definition, from my point of view, does not belong to the controller. All the garbage such as animations, layout, view compositions, changes in drawings, parsing, mapping, http requests, requests to databases, various levels of operating system services and much more - this is not all owned by the controller. None of this should be created and invoked inside the controller. One of the individual items should be navigation. If your ViewController has more than one exit point, then you should think about navigation and navigation control. Very often I had to meet ViewControllers that had 5-10 exit points scattered throughout the controller’s code. There are many ways to organize this, from making navigation into separate extensions, managing navigation exclusively through segue, creating a separate Router entity, inheriting a UINavigationController, and so on. but it also needs to be done. And test. The main thing that you need to remember is that the ViewController should do what it should, and not everything under the row. The same can be said about the entities that are used in MVVM, VIPER (the list is longer, a little longer). All they have to do is just what they have to, if this is a View-Model, then only the representation of the data for the View, if this entity is the storage and transformation of data, etc. (examples of responsibilities are arbitrary, the author does not claim to be true). Always before adding a new method or property to an already existing class - think about whether this should really be in this class.
2.
ModelsOne of the errors that can be observed quite often in iOS is the lack of isolation of the model level. From my point of view, and after successful application in practice, it is best to make models in separate frameworks. You can take out by domain affiliation. For example, if you have a food delivery application, then in separate frameworks you can take out for example: restaurants and everything related to them (search for restaurants, menus, location, etc.), dishes, delivery areas, and so on. If you have an application for buying tickets, you can select a dozen farmeworks (ticket search, reservation, purchase, history, etc.). Each framework can be covered by a separate unit test. You can not do this, but nevertheless try to write models completely isolated from any interaction with controllers.
3.
Massive 'UI' ViewControllersI have repeatedly met huge storyboards (we’ll come back to them) and equally huge UIViewControllers. Huge not in terms of the amount of code (although this too), but in terms of the number of UI elements. The question that I think every developer should ask himself when he sees a huge, cluttered ViewController, sounds like this - “Can I somehow break this VC into smaller View or VC”.


This is a screenshot of a blank document in Word, and I very much doubt that this is 1 ViewController, but at the same time, many iOS developers follow the paradigm of 1 screen - 1 ViewController.
Select several elements on the screen that perform a logical operation or feature for the user in a separate ViewController. An example would be this screen.

Where each cell in the table is a separate VC. The title with the author's avatar, author and time is a separate ViewController. Content and Link is also a separate ViewController.
Like - Comment - Share - all of these components are separate ViewController.
4.
Many UI CodeVolumetric UI code can also lead to obesity of different components. The solution may be the default inheritance of the UI components instead of customization within the ViewController. Or you can add extensions to describe the UI.
5.
Massive Storyboard.Many times I have met massive Storyboard files in projects. 20-50 ViewControllers with different levels of detail are added to the Storyboard. At first, everything goes smoothly and conveniently, all the navigation is right there, the settings are also there, but as soon as the requirements change to the project or new developers are connected, it becomes a complete hell. One solution is to not use Xcode UI Builder as such. Create the entire layout from code.
Use different libraries to simplify writing constraints (Parus, Masonry, etc.) or use CGFrame on hardcore and for all orientations and permissions to write everything yourself. If you really want to use Storyboard, then think about how to break your project into several. Ideally, a Storyboard should have one responsibility, or one usecase. Those. for example, if you have an application for Taxi, then the individual Storyboards can be: Taxi Call, Taxi Tracking, Payment, General Information, and so on. Those. less independent features. With storyboard reference, this is very convenient and requires a minimum of writing code. Ideally, a Storyboard should not contain more than 3-4 individual screens. The more a storyboard becomes, the more power is needed to support it, it’s harder to figure it out the first time, it’s corpulently longer loaded and it becomes harder to work in a group of developers.
findingsWhat I wanted to say with this post is that I noticed the tendency of MVC to blame many of the troubles of iOS developers, and very often (as seen in some examples above), these charges do not specifically relate to iOS. More often, this is the fault of the developers themselves, moreover, these developers often experience the same or similar problems when switching to other architectures. Massive VC appears in 90% of cases, not because MVC does not know how to scale, but because developers do not want / do not allow restrictions to scale correctly.
VIPER, MVVM (and others) can help you with this, especially if you work in a team of developers, but they will not be a panacea for all your problems. In the article I just tried to bring some of the situations in which MVC is not to blame, and to act as a devil’s advocate of its kind, even though I use VIPER / MVVM on my projects myself. Write a good code. All beaver.