MVC vs MVP vs MVVM for Android Application Development
In our last post, we deeply evaluated MVC vs MVP vs MVVM architectural patterns for iOS app development. In this post, we will evaluate and benchmark some architectural considerations for the MV(X) patterns for Android. We will understand some specific use cases with which you can easily make a decision while evaluating MVC vs MVP vs MVVM for android application development.
MVC vs MVP vs MVVM – Android Architectural Design Considerations
The following architectural requirements need to be evaluated when it comes to the selection of an appropriate architectural pattern:
- The performance of system after implementation i.e CPU/ GPU utilization, Memory allocation etc
- How testable your application is?
- How easily can you bring modifications and changes in your application?
- Keeping key components of your application like Activity/ Fragment/ View to be business logic free. This decoupling helps you prevent total application failures
App Scenario #1: Benchmarking MVC vs MVP vs MVVM on a Book search application
We will benchmark testability, maintainability, and performance for MVC vs MVP vs MVVM when it comes to a book searching app that has the following functionality:
- User can search any book
- Upon tapping the search results, user can view the description of the book and reviews associated with it on the web
- There are relevant books suggestion on the basis of what user provides in the search input
The Implementation and test setup
The same application logic has been implemented in MVC, MVP, and MVVM respectively. The image below shows how a user is going to navigate through the app.
This app uses RxJava and Retrofit to handle communication with the API. We also used Dagger here for dependency inject between classes.
Following image represent the implementation of the book searching app in MVC, MVP, and MVVM respectively.
Performance evaluation and tools to determine which is the best architectural design pattern fit here
We used Dumpsys here to measure performance. It allows you to measure CPU/Memory utilization in Android apps to evaluate UI performance.
MVP was most reliable with least Jank – Testing UI performance
Dumpsys showed MVP with the highest reliability and smoothness when it comes to rendering frames. When taken from a percentage of total frames rendered and we look at the number of not so smooth frames (Janky frames), we get the following results:
- MVP: 52.10%
- MVVM: 57.57%
- MVC: 58.48%
Data binding in MVVM creates an additional overhead. The differences may seem to be smaller as our test application was a relatively simpler. But, in other complex UI use cases, the differences can significantly elevate.
Evaluating TDD compatibility between MVC vs MVVM vs MVP in our Android test app
For evaluation of testability between these architectural design patterns in case of our app, we used JUnit4. We often follow Test Driven Development(TDD) for building apps, and testability becomes an extremely important part here. Evaluating between these architectural patterns here are our results:
- MVC: Test coverage here includes on 31% of the methods used in our code, and 18% of lines. JUnit can’t work with certain components of MVC(Activity, fragment classes) and hence testability goes extremely down. Clearly, MVC won’t be preferred in case of TDD scenarios.
- MVP: Test coverage was double the amount in this case when you compare it to MVC(~67%).
- MVVM: 100% test coverage was achieved with MVVM as the design pattern. Presence of Data binding had a positive impact on the testability of the application.
Evaluating Modifiability: Which patterns favor changes and easy modifications
App modifications are a common, no matter how sure you are, no matter what research you have in place. Bad architectural design pattern selection prevents you from actually being agile in iterative with features, pushing new go-to-market strategies when it comes to your app.
In this part of the analysis of our Android app, we will evaluate modifiability with each of these architectural design patterns. Our evaluation is based on the following parameters:
- Number of classes that can be modified
- Number of classes that are required to add new features
- How many added lines of code are required to add the new features
[Note: The results mentioned here are based on small size applications. A more thorough analysis needs to be made while evaluating the same for more complex animations]
Based on our criteria, we tried to add and modified a few classes:
MVC vs MVP vs MVVM – Added and Modified Class | |||
CLASS NAME | TOTAL LINES OF CODE | ||
MVC | MVP | MVVM | |
LoadBookDetailsUseCase | +20 | +20 | >+20 |
SearchAdapter | +58 | +58 | +46 |
BookdetailsActivity | +22 | +22 | +25 |
BookdetailsFragment | +112 | +107 | +80 |
BookdetailsPresenter | NA | +61 | +50 |
SearchBookFragment | +16 | +15 | +16 |
BookdetailsView | NA | +14 | NA |
Library | +58 | +58 | +58 |
SearchBookActivity | +11 | +11 | +11 |
SearchBookPresenter | NA | +3 | NA |
SearchBookView | NA | +1 | NA |
BookListAdapter | +15 | +16 | +15 |
TOTAL | 312 | 386 | 321 |
It should not come as a surprise that MVP is one of the most modifiable and maintainable architectures. Although the number of lines is way far more than MVVM and MVC, it lets developers maintain every single class. On the other hand, MVC is least modifiable owing to the number of non-available classes and the increase in lines of codes compared to MVVM.
Now that we have evaluated testability, maintainability, and performance of MVC vs MVP vs MVVM. Now, Let’s evaluate the next criteria – Making activities/fragments/views independent of business logic.
Activity/ Fragment/ View should be business logic free – Rule of thumb
Why separate the business logic from Activities and Fragments?
A rule of thumb while developing android apps is not to put all the code for network requests, database calls and other complex logic implementation in the Android Fragment and Activity classes.
Not following this rule of thumb has two disadvantages:
- First, sooner or later you are going to duplicate your code and,
- For unit tests, you will need to create objects of the component’s classes (Activity and Fragment in this case) to deal with its lifecycle which is a huge pain in testing, as it becomes harder
In the next few sections, we will evaluate if MVC, MVVM, and MVP follow this rule of thumb, as we definitely see it as one of the decision criteria to decide what needs to be done here.
MVC and our rule of Thumb
Activity and Fragment cannot act as a controller
In Android, Activity/ Fragment classes can be either your view or controller. As mentioned above, many developers tend to make their Activities/ Fragments classes as their controller. But this way, the overall file structure becomes complicated most of the time with much of redundant code inside the controller class.
Letting View dependent on Model and Controller can be a problem in complex applications
In Android, thread handling using UI logic can update apps user interface. But in MVC, the model usually updates View in the background. Moreover, there can be many views listening to model so it is difficult sometimes to know which View has been updated by the Model.
Moreover, controller updates model which in turn updates View. This over-dependence of View on Controller and Model doesn’t make it an appropriate architecture for Android.
Now, Let’s check how MVP handles our rule of thumb.
MVP and our rule of Thumb
Independent View from business logic
MVP solves the problem of a dependent View with the help of a middleman which is called as Presenter. Here, presenter holds the reference to the View which makes View independent. This way, you can handle the view dependency in the presenter in multiple ways.
That said, MVP does a great Job of separating business logic and persistence logic out of fragment and Activity.
MVP fits as the appropriate architectural pattern for android which can be used for simpler and complex applications.
MVVM and our rule of Thumb
Let’s check if MVVM separates fragment/activity from the business interaction.
DataBinding makes the separations of business logic from fragment/ activity much easier.
In MVVM, you can bind the ViewModel through the layout with the help of Databinding. This makes it a good event-driven architecture. As a result of which, you can execute the specific moments of fragment/activity interaction through the interface by describing the logic in ViewModel.
Here, the distribution system is more flexible where each element plays a specific role without interfering with others.
If you want to split your app screen into two or more activities, Use MVP
In MVP, an activity’s XML layout can be used in an ample number of ways. For example, a single screen in terms of UX/ UI can be used to showcase two different activities.
For instance, take the following example:
Here, we have two separate interfaces in the form of PaymentPresenter and PaymentScreen which is implemented by using a single activity class PaymentActivity.
Use MVVM with RxJava for developing API driven application
An application which is API driven should respond fastly while doing design changes. Moreover, it should be easier for you to test your Views as they will be the most important part of your application.
The More close are you from Views, the more difficult it would be for you to Unit test.
In MVVM, you can have that feasibility by creating small Views and ViewModels that will have specific responsibilities. Your ViewModels are injected in the Views which means that most of the times you can add the Views in the XML UI without doing other changes.
This way, you can easily replace some Views with new ones whenever there is any change in your requirement.
Moreover, combining RxJava with MVVM is low risk but high gain when you are creating Views and ViewModels for specific tasks.
If you are on test-driven development, Use MVP or MVVM
MVP and MVVM work well when your project relies on test-driven development as they both have well-defined separation of concerns. As a result of which, you can write unit tests in a more easier way.
Use Reactive Programming with MVVM when your application code contains tons of events/ callbacks
When you are developing a complex Android application with multiple network connections, animations, and user interactions, it often makes the application code heavier with the bunch of nested callbacks.
For instance, callback received during any async operation can be followed with another callback from another async operation performed in it and this can be multiplied to N number of times.
In this case, MVVM along with reactive programmings such as RxJava and RxAndroid will simplify the process of writing async code.
Reactive Programming simplifies the process of writing async code.
Reactive programming with MVVM can be also used in following Use cases:
- User interaction (clicks, gestures etc)
- Processing system events (GPS, gyroscope etc)
- Asynchronous data such as server interactions etc.
Use MVVM with data binding, if you are working on an application with complex Views
Until 2015, Android developers have to write tons of fragile, untestable and uninteresting code to work with Views while working with MVVM architecture. This approach is more prone to bug and errors. However, with the launch of data binding library for Android, things became more favorable for developers.
Data binding makes it possible to reduce tones of boilerplate code by making it more readable. It provides the mechanism through which not only your View can receive initial values and updates but your ViewModel can also handle events from the View.
It makes it possible by automatically generating a binding class that will do most of the hard work for you.
MVC vs MVP vs MVVM for Android Development
Model-View-Controller in Android
A common approach to implement MVC in Android is to write about 1000+ lines of code in a single Activity/Fragment.
In this approach, every Activity and Fragment class in the application will act as Controller layer such as text watchers, click listeners and item click listeners etc and Model Layer such as Database calls, Rest API calls, business logic etc.
XML layout is actually a View Layer in Android.
However, the same kind of implementation becomes buggy and it is very difficult to unit test. Moreover, it also decreases the overall code reusability.
An important thing to note is that Fragment and Activity classes support a limited range of transition animations.
MVC in Android is not testable and it is not the best practice to implement.
Model-View-Presenter in Android
A quick and precise description of MVP in Android through the above figure boils down to:
- View Layer is a combination of Activity/Fragment along with the implementation of XML layout and View Interface. The only single thing View does above is to call the right method from Presenter on user interaction.
- Here, DataManager acts as Model. It holds reference to the database API such as SQLite or rest API such as Retrofit
- The presenter is the middleman or mediator between View and Model. It does not know anything about Activity/ Fragment/ View. It holds the reference to the model layer. The major function of the presenter is to retrieve data from the Model and returns it to the View.
The only difference of Presenter in MVP from the Controller in typical MVC is that it also decides what will happen when you interact with the View. That’s why it is easier to unit test it by mocking the View and Model.
To put in a more simpler way, MVP in Android gives the developer the freedom to test different behaviors i.e functionality tests.
MVP in Android is widely used design pattern as it is more testable and readable.
Model-View-ViewModel in Android
The Image above represents a quick and dirty way of understanding MVVM architectural pattern in Android.
In Android MVVM, we have
- View Layer is a combination of Activity/Fragment with XML and binding. Activity requests data from the backend gets data and forwards it to ViewModel Layer. ViewModel Layer updates the UI with the new data.
- DataManager acts as Model Layer. Similar to MVP, it holds a reference to the Rest API and database.
- ViewModel is the middleman between the View Layer and the model. It receives data from Model Layer and updates the View Layer. Also, it manipulates the model state as a result of user interaction from the View Layer.
The difference between MVP and MVVM from the perspective of the Model Layer is that in MVVM architecture DataManager returns the response to Activity/Fragment instead to Presenter. That means that Activity/Fragment is aware of business logic.
Conclusion
When it comes to Android, both MVP and MVVM offer better modular architecture than MVC. Though, they also tend to add more complexity to your app.
In simpler applications which involves two or more screens, MVC can work fine in Android. Whereas in more complex cases where your application needs to be developed considering to add more features in future, MVVM with data binding will make you write lesser code.
So, which architectural design pattern are you going to consider for your mobile application? Feel free to share a comment.