Ending the debate: MVC vs MVP vs MVVM for iOS application development
Almost each and every talk on iOS application architecture starts with “MVC vs MVP vs MVVM”. There’s a fair share of failures that everyone has gone through to get it right.
Note: If you follow Uncle Bob’s clean architecture with any architectural design pattern you can make anything work when it comes to application quality.
The general challenge of choosing the right architectural design pattern is more about your team size, maintainability, testability to name a few. From bad testability of the app to increased time to market, choosing the wrong architectural design pattern could lead to a lot of problems.
Note: In some scenarios, we have seen developers having to re-write an entire app from scratch again as the architectural design pattern itself was a bottleneck to adding new features and agility.
Recently Flawless, an app builder platform moved from Apple’s MVC to MVVM when they realized it was becoming extremely difficult for them to unit test their code as ViewController became larger and buggy down the road.
They aren’t alone, there are hundreds of such stories on the internet to illustrate the challenges.
With the help of this article, we are hoping to help you avoid some major mistakes when it comes to choosing the best architectural patterns. As you continue to scroll down reading this article, you’ll learn a clean and clear approach on how to select the best design pattern which better suits your development needs.
MVC vs MVP vs MVVM – What difference do they make?
All the architectural patterns do have three components in general:
- Models: The M stands for the model which is a structure that manages the data. It’s not the data itself rather than it is responsible for making new entries in the database, reading the database or deleting entries in the database.
- Views: Views are related to your presentation layer. In a mobile world, you can assume your View as everything which you get to see on your mobile screen i.e UI
- Controller/Presenter/ ViewModel: These are the mediators or glue which handles communication between Model and View.
Now, Let’s understand how do these components interact or behave when it comes to iOS application development.
MVC vs MVP vs MVVM for iOS app development
In case of Apple’s MVC, the things seem to turn around quite in a different manner due to the inclusion of a ViewController. Here ViewController contains the View and updates the Model.
Moreover, ViewController is tightly coupled with UIView here. As a result of which it often becomes difficult to unit test the View as the overall business logic, in this case, needs to be separated from the View layout code.
Though there is still some chance to offload some of the data transformation and business logic to the Model but offloading work to View is more of a pain for most of the developers.
This is the reason many developers find it difficult to deal with MVC in iOS.
Model-View-Presenter in iOS
Apple’s MVP deliver the promises which are previously not delivered by the MVC architectural pattern. The implementation somewhat looks similar to the MVP architecture but it should not be mistaken as the same. Both are way different from each other.
In MVP, View consists of both UIViews and UIViewController. All user interactions from the View gets passed on to the presenter. The presenter interacts with View through an interface which makes m both loosely coupled with each other. The presenter communicates with Model thereby converting the data in a UI friendly format and updating the View.
You can memorize it in this way:
View -> Presenter -> Model -> Presenter -> View
Model-View-ViewModel in iOS
MVVM in IOS is somewhat different from MVC and MVVM in iOS. You can memorize the interaction in this way:
User -> View -> ViewController -> ViewModel -> Model
Let’s understand it with a simple example:
Say, You are developing a temperature converter app.
The user will see the text fields with a button (View). On pressing the button, ViewController will get information from the View (such as the parameters to convert) and pass it to the ViewModel.
The ViewModel will send the data request from the server and will add data to the Model. It will process the overall calculations for conversion and pass back the value to the ViewController which in turn will update the View.
The Key takeaway: In MVVM, you have a new ViewModel class which interacts with Model. This means that Controller is no longer responsible for the same. Therefore, the Controller will only do what is supposed to do i.e working with Views. It does not know about the existence of the Model.
Having ViewModel as the mediator also brings out two biggest benefits in terms of development and testing such as:
- First: ViewModel forms a one-way communication with View due to its binding with View. This way, View will hold the reference to its ViewModel. However, ViewModel is restricted from knowing about its View. Therefore, It can be used by many View objects.
- Second: ViewModel has the ability to observe changes in Model and synchronization with events. Due to the existence of binding between View and ViewModel, Former can be updated accordingly. This brings the most out from the app in the form of responsive experience for users.
Since ViewModel is an independent layer which knows nothing about Model, it is very easy to unit test.
App scenario: Benchmarking MVC vs MVP vs MVVM in iOS when it comes to Objective C vs Swift
Following are the results of an extensive study done on CPU and Memory allocation of an app being made with design patterns such as MVC vs MVP vs MVVM:
CPU and Memory allocation in MVC
CPU Usage: MVC, when implemented with Objective C, possessed 3 % higher CPU usage as compared to swift. To put in a simpler way, we can say that Swift performs better when implemented in MVC.
Memory allocation: As demonstrated by the figure, apps that are implemented in MVC using Swift takes about 6-8 % lesser memory than an app that is implemented in Objective C. The reason being a lesser amount of Data flow in MVC as most of the business logic is implemented directly into the controller.
CPU and Memory allocation in MVVM
CPU Usage: In the case of MVVM, the logic is implemented in ViewModel which requires more classes and interaction between View and Model. As a result of which there is more interaction between the components. Hence, Swift takes more CPU allocation than Objective C as in case of swift, many variables need to declare which allocates more CPU usage.
Memory Allocation: MVVM implemented in Objective C utilizes 5-7% of lesser memory than Swift. The reason being the more data flow between the view components in Swift which is due to communication between View and ViewModel for every element that needs to be updated in View.
MVVM, when implemented in Objective C, performs better as compared to Swift with lesser number of CPU utilization and memory allocation.
CPU and Memory allocation in MVP
CPU Usage: In MVP implemented using Objective C, the data is passed to View with the help of a middleman known as Presenter. Also, there is no strict binding between Model and Presenter. This is why app implemented in MVP using Objective C utilizes 2% lesser CPU usage as opposed to Swift.
Memory allocation: In case of Swift, there is higher complexity between View and Model due to which it takes 5-7 % more memory allocation than Objective C.
The above statistics implies that design patterns such as MVC, MVP, and MVVM, when implemented in Swift, performs better only when there is lesser code complexity and data flow among components.
[Note: The above statistics are based on a specific implementation only. We are, in no way, implying that Swift isn’t better than Objective C when it comes to implementing design architectural patterns.]
MVC vs MVP vs MVVM in iOS app development – A Quick and Dirty Way to decide the best
You don’t need to re-invent the wheels when it comes to mobile app architectural design patterns. We have listed some use cases where you can directly pick-up an architectural design pattern directly from the list. I am sure, you would find 99% of them to be “direct-to-the-point” and helpful.
Use MVC, if you are building a simpler application
Many times, new beginners tend to learn MVVM along with ReactiveCocoa/RxSwift without realizing that it is not the standard way to program for iOS.
MVC is the recommended architectural pattern to learn iOS development. It structures the data flow and interaction in your app. If you are just starting out and want to build simpler applications, It is a good architectural pattern to get your hands dirty.
However, using MVC in applications having complex View will create the problem of Massive View Controller as your ViewController becomes bloated with about 1000+ lines of codes.
Thumb Rule while using MVC as an architecture for building simpler iOS applications
In MVC, developers mostly have a real tendency to put their most of the logic into the ViewController. This leaves them in the end with a giant ViewController which is difficult to manage.
But, lately, all it boils down to understanding the pain points MVC attempts to solve. Because, at the end of the day, you don’t have to follow a pattern like it is a Bible. You will have to learn to make your ViewControllers thin and lean.
Following are some points by following which you can prevent your ViewController from getting bloated in MVC:
- Refrain from handling all the grunt work like UITableView/UICollectionView to your ViewControllers. You can assign these complexities to a different class and your ViewController can just provide model objects to be displayed.
- Break your View controllers into multiple child controllers – this will force the separation of concerns on the project you are working on.
Use MVP, if you are using Xamarin for cross-app development in iOS
Most developers use MVVM while leveraging Xamarin for iOS app development. However, this kind of approach is only limited to apps which have simpler functionalities.
If your app has the relative complex screen with a lot of elements, implementing your code in MVVM will make the framework more prone to bugs which will add a significant risk to your project. Because, in MVVM, you have your business logic contained in the ViewModel layer.
Any change in business logic will require the View layer to immediately reflect on it. MVVM use data binding for this purpose which binds your view states to some of its properties. But, unlike MVP, it usually creates the big problem of invisible outputs.
In MVVM you just have some properties and you are not sure in most cases about what exactly is going to trigger view updates unless you check implementation details. That is unneeded uncertainty about how your view layer behaves when you are using a framework which may have many limitations.
Use MVVM, when you can’t solve out the problems with Massive ViewControllers
If you find your ViewControllers in MVC to be heavily bloated with most of the complex app logic, you can always make them lean by following the thumb rule mentioned above. However, if you are still unable to do so, you can always move to MVVM by refactoring your ViewController into ViewModel.
ViewControllers in MVVM aren’t so massive as compared to MVC. Moreover, your ViewModels in MVVM are often easier to test which will make your code more manageable as a result.
Use MVVM with Swift, if your client project requires you to ship higher quality code with fixed budget and deadline
Most of the time, your client wants you to deliver your app on a fixed deadline and budget. Using MVC and MVP, in this case, is not wiser as they both have their problems to deal with in terms of massive ViewControllers and Presenters.
MVVM along with swift will be a good architecture to follow in this case as it simplifies the problem of massive view controllers by introducing the ViewModel concept. Moreover, Swift is a better coding language than Objective C. It introduces a lot of modern concepts that will help you write more clean code. For example, It supports optional types which often makes you to deal easily with a lot of nulls.
Protocol oriented programming (POP) with Swift
One considerable advantage when adopting the MVVM structure is the isolation of business logic. However, in reality, it is difficult to observe this advantage due to the specific binding between Controller and View Model objects.
By its definition, a View Model is a unit that encapsulates all domain logic needed by a controller. Henceforth, View Model is only reusable in the case where 2 or more controllers share the same package of functionality which is often rare as the app complexity grows.
We have found POP-MVVM to be absolutely beneficial in this case. You can solve this problem by having Viewmodels correspondence to the certain number of different traits.
For instance, you might have two different ViewModels for interacting with animals like dogs and cats. If you are habitual with Object-oriented programming, you would make different methods which will contain specific logic such as feed, play, and train etc. However, this is not efficient considering both animals can be feed or played in the same way. This can be simplified by splitting the interactions into multiple traits such as feeding traits, playing traits etc. which in turn will reduce the number of duplicated implementations in ViewModels since each trait will contain its own logic.
Implementing Routing (Navigation) in MVVM
MVVM does a good job of moving out your business logic out of your VC (ViewControllers) but presentation logic such as routing and navigation are still stuck in your VC. This generally creates a problem of Massive View Controllers.
Henceforth, it is really important for us to move routing and navigation out of the View Controllers.
In an app which consists of a login screen, you will have the following list of routes to implement:
- Login which will be your Home Screen
- Sign Up which will be your user sign up screen
- Forget password
At the first glance, it will look easier to implement all these. However, it’s not that easy as it looks.
You may implement login screen as your home screen. But, in case of user password expiration, you will require implementing the “Forget password” screen as your home screen.
Hence, in this case, your routes will be changed to:
- Login or change password screen as your Home screen
- Sign up
Now, you don’t want to implement this logic in your VC.
Therefore, it is wiser to move away the routing and navigation code out of your View Controller. One way of doing this is by introducing coordinators in the architecture which will make it MVVM-C. The major responsibility of the coordinator will be to handle the navigation and flow of the app.
The entire implementation code of MVVM-C can be viewed on Github here.
Use MVVM, if your project is on Test-Driven-Development
Testability is one of the major prerequisite for any architectural pattern. If your project relies heavily on test-driven development, it is important for you to choose a good architectural pattern. MVC is not a preferable architectural pattern when it comes to unit testing. Hence, it is not recommended to use MVC in the case of Test-driven development.
As long as you know how to thin out your View Controllers, MVVM is the appropriate architectural pattern when you are on test-driven-development. It will make your overall code testable alongside production.
To conclude in short, It turns out that MVVM is way ahead of MVC and MVP when it comes to IOS app development. However, in the end, it all boils down to the requirement of your app.
In general cases, MVC is a good architectural pattern to develop smaller to mid-sized applications. But in more complex app scenario, you need to know how to make your View Controllers thin and lean by moving out your presentation logic out of them.