The only viable iOS architecture

Deep dive into MVC, MVVM, MVP, VIPER as a result of which we’ll understand that for iOS there is only one possibility among them

Amirzhan Idryshev
Nov 11 · 20 min read

Let me guess what you think about reading this title.

Is it another annoying blog post that chides MVC and offers an alternative “super-duper pattern” that practically only leaves more questions? That is what I think when I see yet another article with iOS architectures. MVC, MVP, VIPER, RIBLET, Clean Swift, etc. There are dozens of posts, radically different opinions and architectures.

Our community doesn’t stop arguing which “pattern” is the best. But the problem is all of them are shit. Any argument in favor of some “pattern” is unconvincing. We try to use some “pattern” and get stuck on a problem that does not have a “normal answer”. In the end, we get some awkward solutions and have more misunderstandings. And all of this looks strange. We are fed to the teeth with this. Honestly, I didn’t want to write this post at the beginning but come on, it is not a solved problem in the iOS community.

Tell me one architecture “pattern”, that we should use. Not even that. Tell me, at least one, that is not so strange. We have a million architectures, but not one really helps us, not one even smells like good code. Why?

To solve this problem we should rethink everything and start from the early beginning. We will have a really deep immersion in these architectures and will find the main mistakes we’ve made.

What if I tell you, that there is only one possible architectural pattern in iOS and it is not even a pattern?

Keep reading and you will understand how strange every variation of MVC looks like, how much misunderstandings in the iOS community we have, and what should we really do designing our app's architecture.


At first sight

MVC

Although developers argue which architecture to use, Apple has already given us instructions on how to structure iOS apps. It is MVC.

View is what the user can see on the screen. Model is “data”. And Controller is a mediator between them. It takes data from Model and shows to the user on View, and handles user actions on View and transfers them to Model.

It seems good. So, why not use MVC, if it is Apple guidelines? Because, at first sight, MVC is really really bad. You probably know, how big your ViewControllers could be and how hard to maintain it. Because there are a lot of different logic besides view and data, which apparently should be done by Controller.

Controllers are responsible for managing the view hierarchy of the view they own. They respond to the view loading, appearing, disappearing, and so on. They also tend to get laden down with the model logic that we kept out of our model and the business logic we kept out of our views. That leads us to our first problem with Massive View Controller.

MVVM

We didn’t like that and started to look for MVC alternatives. And we’ve found them.

MVVM adds a new layer, ViewModel to divide the code with Controller. But in fact, it doesn’t solve all the problems. What should really be in ViewModel? And what should I do, when ViewModel also becomes fat like Controller? The community was divided on those who like MVVM and those who don’t like it.

MVP

Another attempt to solve this problem was MVP. It starts to consider ViewController as View, and all logic goes to the new class Presenter. But it hasn’t become popular, because it looks really strange. In fact, we just shifted all problems from ViewController to Presenter.

VIPER

Then we’d thought that we need a more decomposition and created VIPER. All code now goes into one of the View, Presenter, Router, Interactor or Entity.

In short of time, VIPER had become popular, but then we understood that something wrong with it. This architecture requires a lot of protocols, classes, and the passing of data between layers. But for some reason, all this extra work doesn’t make our design better and more readable.

Any other architecture

Finally, we’ve created an endless loop of new architectures. All of this looks like a bad joke. Each new architecture looks more strange than the previous one. Check this joke by Guilherme Rambo, it describes the absurdity of this situation very well. Whichever architecture you choose — all of them are bad.

But as I said before, this problem has a solution. I will say you which “pattern” we should use. You may be surprised, but it is MVC. What I want to do is to start from the early beginning, read MVC from the original sources and stop running away from it. Maybe it is not so bad if it is still alive?


The original MVC

A lot of iOS developers complain about MVC. But what if I tell you, that all MVC problems I mentioned earlier don’t actually exist? Observations such as “Massive View Controller”, “Model is data”, “ViewController do a lot of business logic” are fictional. All of them were born out of a misunderstanding of what real MVC is.

The main reason why people have problems with it is due to MVC’s oversimplification. Seriously, what do you think about when you hear MVC? “There are 3 classes: Model is data, View is view and Controller is between them”. But come on, MVC is not so simple.

MVC is a result of a very huge work. It was invented by Trygve Reenskaug as a result of his work on the Dynabook project at Xerox PARC in 1979. Dynabook is a personal computer for children of all ages. And it was a really revolutionary project. The Dynabook was intended to make computers easy to use while enabling a user to manage complex applications. That is when the foundations of graphical interfaces and the concepts of “user-friendly interface” were first developed.

This project was going for about 10 years. Reenskaug summarized the main ideas and solutions in GUI application development that were accumulated during these 10 years in MVC.

And it wasn’t like “Hey, we created a universal pattern in 10 years that you should use to solve any problem”. It is a fundamental mistake we made. MVC is not a pattern. It is not a scheme of app’s modules decomposition. No one can give you a silver bullet solution with a certain amount of classes that will work for any problem, because no one knows your problem, the business logic of the app, Domain Model details and your main goal. You should design your app yourself accordingly. This is how Martin Fowler describes the problem of MVC misunderstandings:

It’s often referred to as a pattern, but I don’t find it terribly useful to think of it as a pattern because it contains quite a few different ideas. Different people reading about MVC in different places take different ideas from it and describe these as ‘MVC’. If this doesn’t cause enough confusion you then get the effect of misunderstandings of MVC that develop through a system of Chinese whispers.

MVC is a set of architectural ideas and principles. MVC is one of the first attempts to formalize main ideas working with apps with graphical user interfaces. And these ideas are still relevant and not only for the iOS platform. You can read about MVC from the Trygve Reenskaug in his works. The original MVC reports and The Model-View-Controller. It's Past and Present.

One of the main principles of MVC is to divide all our code to Presentation and Domain Model.

Domain Model is the core of our application. It is the main part of it. It consists of several business objects, for example, entities such as account, product, transaction and so on. And the logic around these objects is called business logic. For example, “if the user has little money on the account, give him a discount”. And Model in MVC means the whole Domain Model, not just one dumb model of some entity. Domain Model can consist of one object as well as a whole system of objects. It depends on how complex business logic is.

Presentation is what users can see and interact with. In MVC the View and Controller are parts of Presentation.

Martin Fowler calls this principle a Separated Presentation.

At the heart of MVC, and the idea that was the most influential to later frameworks, is what I call Separated Presentation. The idea behind Separated Presentation is to make a clear division between domain objects that model our perception of the real world, and presentation objects that are the GUI elements we see on the screen. Domain objects should be completely self contained and work without reference to the presentation, they should also be able to support multiple presentations, possibly simultaneously. This approach was also an important part of the Unix culture, and continues today allowing many applications to be manipulated through both a graphical and command-line interface.

So, if our Presentation is loosely coupled with Domain Model, without any knowledge of Domain Model’s details and Domain Model is completely independent of Presentation, our app’s design will be clear, reusable and maintainable.

This scheme is taken from Reenskaug’s report.

The Editor is how Presentation was called at first. In this scheme, we can see that MVC is not 3 classes. It is more about decomposition by layers, not by classes. The important thing is that the Presentation should be very loosely coupled with the Domain Model. Ideally, it should depend only on the required interface, so that any Domain Model could implement this interface. The Facade pattern on the scheme suggests that there is one class in Domain Model that implements this interface by calling desired objects so that the Presentation doesn’t need to know anything about concrete objects in Domain Model. The interface and facade help us to make the connection between Presentation and Domain Model loosely coupled.

But how Domain Model should communicate with the Presentation? If for example, some data is changed in Domain Model, how should it notify the Presentation? It is another principle of MVC. Domain Model should never depend on Presentation, even by interfaces. All Domain Model can do is send notifications about some event, not knowing who will handle this event. It is can be made by the Observer pattern. It will give us full independence of Domain Model.

Another scheme by Reenskaug’s report describes the third principle of MVC.

It is about separation Presentation on Input and Output. Initially, it was a very good idea to divide the Presentation into the layer, which is responsible for showing the information to the user, and the layer, which is responsible for getting information from the user. You will see later, that this principle does not apply in the context of iOS. But you should know that in the original MVC both Controllers and Views had a graphical representation.

In sum, the original MVC should look just about that:


Is it applicable to iOS?

Of course YES! If we considered MVC like a set of principles, and not just a “pattern with 3 classes” we would never know about the “Massive View Controller” problem. Let’s see how these principles fit on iOS.

As we said before, the heart of MVC is a strong separation between Presentation and Domain Model. In fact, this principle has become one of the main ones in the GUI application design. Other architectures like MVVM or MVP also based on this separation. It doesn’t matter for which platform you code, which architecture you use, you should always do this separation. So, it means that this principle is important for iOS also.

What about dividing the presentation on View and Controller? Generally, it also fits on iOS, we even have these classes in iOS SDK: UIView and UIViewController. But we should know, that this separation is a few differences from the original MVC. And it is not surprising because it has been a while, a lot has changed, the user interfaces have changed. Now, we do not need to divide graphical elements on input and output. Particularly, on iOS, each UIView element is able to show the information and receive user actions. So, UIView is a class, that has a graphical representation and is responsible for working with the user in both directions. And UIViewController is an owner of UIView. It “controls” View and its lifecycle, handles user actions on View and shows the information from Model on View.

This variation of original MVC has a different name and we will see it later, but anyway, we will call it MVC, because the main principles are saved and it is only a variation of MVC. Moreover, Apple itself calls it MVC.

Actually, it doesn’t really matter how we will call it. The important thing is to understand how it is implemented. More precisely, to realize that MVC is already implemented. UIView and UIViewController are classes, that are already implemented in iOS SDK. I mean, some people refuse MVC but still use UIView and UIViewController. Although, it is the main thing, that makes Apple MVC different from other architectures. It is a way, how we work with user interaction, and extra classes like Interactor or Presenter don’t change this way. On the contrary, MVC involves additional entities when it is necessary according to the problem. Although Interactor and Presenter are examples of not good classes, we should remember that MVC is not a pattern and there are can be as many classes as needed to solve the problem. So, if you use UIView and UIViewController in front of the user, never mind which other classes you create, you use Apple MVC.

Can we not use UIView and UIViewController? No! A lot of work is done under the hood, so we can easily handle all communication of users with our app. There are a lot of things besides these two classes: Responder Chain, UIEvent, UIView hierarchy, UIView lifecycle, Hit Testing, UIControls, UIGestureRecognizers, etc. All of this is Apple MVC. That means MVC is not our choice. If you say that you don’t use MVC, you do! We use MVC and we can’t use any alternatives in iOS.

Fighting with iOS SDK is impossible and any attempt to do this complicates the system. But it is not so bad if we understand that. As soon as we stop fighting with iOS SDK, all these staffs becomes useful. The SDK starts to help us and benefit. Each UIViewController holds one root UIView. We can just draw View in interface builder without any code and link all user actions to UIViewController. UIViewController also handles the state of the View via methods like viewDidLoad(), viewWillAppear(), etc. And we should use all of these features.

iOS SDK gives us a lot of features. Many developers complain that UIViewControllers become fat, but only a small part of them says about the UIViewControllers decomposition feature. That’s why for many developers it can be surprised. But we can create multiple UIViewControllers for 1 screen. Yeah, if there are multiple logically independent components on 1 screen, we can divide it into multiple small UIViewControllers.

Do you still think that using MVC leads to the “Massive View Controller” problem? Let’s again repeat the main things that refute it.

  1. UIViewController is a part of the presentation layer. If you write there a business logic, network requests or anything else that doesn’t relate to the user interface, it is not MVC.
  2. Create other classes in the presentation layer if you need it. The existence of UIViewController doesn’t force you to write all your code there. If you have a lot of presentation logic, please, take it out of ViewController. But please, be sure that the new entity is really necessary.
  3. Don’t fight with iOS SDK. It gives us a lot of features and these features provide great benefits if we start using them.

Do we need MVC alternatives?

Well, the answer is obvious. We don’t need any of them. You have already seen what real MVC is and how to use it in iOS. Moreover, it is almost impossible to fight with the iOS platform, using own architecture. But let’s again consider each architecture, that we’ve described at the beginning and you will see how strange and even absurd they are in the context of iOS.

MVP

MVP is the strangest one among them. A bit of history to illustrate it. MVP was introduced in 1996 by Mike Potel as a modification of MVC. In his work on MVP Potel suggested that there is no need to divide widgets into Views and Controllers. Modern Operating System user interfaces already provide most of the Controller functionality in View class and therefore Controller seems a bit redundant. So, Controller was removed and a new class Presenter was created as a glue between View and Model.

Stop. Does it look like Apple MVC? Maybe it is Apple MVC? Does Apple means MVP, saying MVC? I don’t know because there has been so much confusion between these terms. Let’s see how Martin Fowler distinguishes MVC and MVP from each other in his post about GUI architectures.

MVP uses a Supervising Controller to manipulate the model. Widgets hand off user gestures to the Supervising Controller. Widgets aren’t separated into views and controllers. You can think of presenters as being like controllers but without the initial handling of the user gesture. However it’s also important to note that presenters are typically at the form level, rather than the widget level — this is perhaps an even bigger difference.

Now, look at these schemes of MVC and MVP. And compare them with the Apple MVC scheme which we have seen above. Which of them is more similar to Apple MVC? Yes, Apple MVC looks more like MVP, but not original MVC. But again, it doesn’t really matter how we call it. Moreover, Apple MVC differs from both of them anyway.

The most important thing is to understand that we already have UIViewController which acts as a UIView holder. That means we don’t need any additional class with the Presenter or Controller role.

So, the attempt to create a new Presenter class and consider UIViewController as a View is nonsensical. Although I said, that there could be other classes in the Presentation layer beside UIView and UIViewController, the Presenter is a bad example of doing this. It is an example of fighting with iOS SDK. No matter how much we want to see an UIViewController as View, it is still a Controller(or you can call it Presenter). And in iOS the scheme of MVP actually looks like that:

Do we really need this new class? It looks strange because we just create a duplicate of native UIViewController with exact the same role. Why should we transfer all user actions, all view state changing from Controller to Presenter if it doesn’t give us any profit? It only gives us additional code and complexity. It is really hard to delegate each action to the Presenter. Again, don’t fight with iOS SDK, we can’t turn UIViewController into View. Even if we could, there is no need for that.

VIPER

Remember I said that MVP is the strangest one? No, VIPER is. Because, in addition to all problems of MVP (It repeats all mistakes from MVP in the Presentation layer, including duplicating Presenter and unsuccessful attempts to turn UIViewController into View), VIPER tries to divide our Domain Model into Interactor, Service and Entity classes.

How VIPER was created? Does it have own histories like MVC or MVP? Yes, it does, but the history is not so shiny. VIPER was created in 2013 to solve Apple MVC problems.

Since much of the application logic does not belong in a model or view, it usually ends up in the controller. This leads to an issue known as a Massive View Controller, where the view controllers end up doing too much.

The quote above is from the original post about VIPER. And it means that VIPER was created to solve the nonexistent “Massive View Controller” problem. It was created on the mistaken thought that “MVC is a pattern with 3 classes and huge UIViewController”. Trying to solve this “problem”, VIPER made a much more decomposition by 5 classes. But practically, it doesn’t really matter how much letters your “architecture” has. If you consider your app architecture only as a “pattern” with exact classes you will fail anyway. The number of classes is finite, but the logic could be wider each time, and once our Interactor or another class will be as big as Massive View Controller.

Moreover, the logic could be really different. But in VIPER we always create 5 classes, even if the logic is small or very specific. The problems are really different and there is no such scheme that is suitable for all problems. We should do the decomposition individually, according to this specific logic. It is a common task in OOP to understand which entities we should create, how they should relate to each other and how to name them to describe the code most clearly.

There are great thoughts about VIPER problems and decomposition by Chris Eidhof in the «App Architecture» book.

While interface decomposition is a valid approach for managing code size, we feel it should be performed as needed, rather than methodically and per view controller. Decomposition should be performed along with knowledge of the data and tasks involved so that the best abstractions — and hence the best reduction in complexity — can be achieved.

Does Interactor is such a good abstraction? The definition of the Interactor says NO. “Interactor is a class that contains business logic”. Come on, does it helps us to understand the code? Which business logic it contains? What if I have a lot of business logic? We should create and name our entities to be clear and specific, not just general “Interactor”.

Creating the same classes for all problems and everytime just adding the code to these classes is not a good design. It is not OOP even, I see that as procedural programming with 5 files.

In my opinion, VIPER is our shameful mistake. VIPER proves that we haven’t understood MVC. Before reading the original sources, we had started to complain about MVC and thought up such a strange thing. My suggestion is to forget about VIPER and never discuss it.

MVVM

If we don’t write business logic in UIViewController and use decomposition to divide one screen into multiple UIViewControllers, will our UIViewControllers never be massive? Well, it depends on how much presentation logic it has.

Let’s consider 1 example.

// Domain Model Object
struct Person {
let name: String let gender: Gender}class ViewController: UIViewController { override func viewDidLoad() { super.viewDidLoad() // presentation logic if person.gender == .male { nameLabel.text = "Mr." + person.name } else { nameLabel.text = "Mrs. " + person.name } }
}

In the example above we have a presentation logic to format the person’s name title according to his gender. Should this logic be in UIViewController? What if there was a lot of complex presentation logic? Besides complexity, there is a testing problem also. It is not easy to test UIViewController class. It is another reason why developers duplicate their own Presenter and made a dump UIViewController, moving all logic to NSObject subclass. But we have already seen the problems of this approach.

Could we write this logic in Person class? Well, in this case, we would mix presentation and business logic in one class that is not good according to the MVC principle. It would be hard to understand, why this code is there. We would not see for which concrete view this code is written. And finally, it would be hard for reusing this model on different screens. What if on some other screen this information will be shown differently, with emoji for example? 👩‍🦰 👨‍

Now, it is time to repeat again that MVC is not a pattern. Yes, we have some logic in the Presentation layer and MVC doesn’t force you to write this logic in existing classes. We can create a new class and encapsulate concrete logic there. Martin Fowler wrote about this problem. He says that we can create other models in the Presentation layer if it differs from the Domain Model object. And he calls this objects Presentation Model.

struct PersonPresentation {    let name: String    init(person: Person) {        if person.gender == .male {            name = “Mr.” + person.name        } else {            name = “Mrs. “ + person.name        }    }}

Now, in UIViewController we just map the name to the label.

You may say that it is MVVM. But it’s not. Although we call it MVVM, it is not. Because in fact, MVVM was created in 2005 as a modification of MVC and MVP. ViewModel was added instead of Controller and Presenter, it handles View actions. But in iOS, we still don’t rid Controller. UIViewController handles how we work with user interaction. All we do is creating an extra model in the Presentation layer, which is implied in MVC. We just used a Presentation Model.

But again, it is not a really big problem in naming. Of course, we will not rename all our ViewModels to PresentationModels. But we should understand what ViewModel really is (let’s call it PresentationModel for now to not get confused).

PresentationModel is not a class that contains all business logic, how a lot of developers say. PresentationModel is not a facade that combines network requests, database requests, cache and so on. It is just a model in the Presentation layer. And using PresentationModel doesn’t mean we use another architecture. We still use MVC, because we don’t change the way we work with the user.

Generally, PresentationModel is just a pattern. Yes, unlike MVC or original MVVM, Presentation Model is a pattern which we use when it is really necessary. And there is no need to standardize that and create PresentationModel on each module for no reason.


Conclusion

MVC is not as simple as a scheme with 3 classes. MVC is not a pattern but a set of architectural ideas and principles.

The heart of these principles is a strong separation between Presentation and Domain Model. Model in MVC means the whole Domain Model. UIViewController is a part of the Presentation. This means MVC doesn’t let us create one dumb entity and move all business logic into UIViewController.

This separation has become one of the main ones in GUI application design and they are useful for iOS also. But Presentation layer separation is usually platform-specific. iOS SDK has already done a lot of work, so we can easily handle all communication of users with our app. So, MVC is not our choice, we can’t change the way we work with user interaction. We shouldn’t fight with the platform because our design would be complicated. But as soon as we stop fighting with iOS SDK, all these staffs become useful.

As well as we design our Domain Model according to business logic, we can design our Presentation according to the presentation logic. MVC doesn’t force us to write all the code in UIViewController. We can create extra classes in the Presentation layer if we need to. But don’t call it a new architecture if you add ViewModel or Coordinator or something else.

Finally, don’t try to standardize the architecture into a pattern. Do the decomposition individually, according to the specific logic, trying to describe the code clearly.

Don’t blame MVC.



🛑 P.S. Let’s stop it!

The main goal of this post is to show how strange the situation is. We made a big mistake by not sorting out MVC. We thought up unusual, misleading things like “Massive View Controller”, “VIPER Architecture”, “Architectural patterns” and so on.

We came up with it, but now we need to stop it! We should stop thinking that app design is so easy, that can be done using some pattern, we should stop looking for silver bullet solution for all problems, we should stop blaming MVC and stop discussing MVC alternatives, that are so unusual for iOS. Stop anyone who says “MVC is terrible”, “ViewController does a lot of business logic”, “Model is data”. Stop them and explain that they are quite mistaken.

It will be a great benefit to our community if we stop it. We should understand that architecture is not just a template or pattern, it is a complex process. It is a skill that comes with experience. And we will start improving that skill if we don’t just thoughtlessly follow some trendy “pattern”, but solve each problem individually, according to the problem specifics, the features of platform and knowledge of common design principles.


Thanks for reading. Do you agree with me or have some questions? Let me know what do you think on Twitter.

Share the article, so other developers can read it too. Let’s stop misleading each other.

Flawless iOS

🍏 Community around iOS development, mobile design, and marketing

Thanks to Miras Karazhigitov

Amirzhan Idryshev

Written by

iOS developer

Flawless iOS

🍏 Community around iOS development, mobile design, and marketing

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade