First of all, I would like to share something about the motivation for this article. I am developing Android apps for almost two years now, never felt the need to follow any architectural pattern. One good day I was going through the Google IO 2017 videos on YouTube and came across some of the Architectural patterns. I tried to dig a bit but was confused. Various questions popped out; couldn’t figure out what to do.
I got a project at work, the code was messed up, 4500 lines of code in a single activity. I was afraid to change anything in that junk. At the same time, I started realising the goodness of MVP. I got across that fear and took a leap of faith (I love Assassin’s Creed). It went pretty well. But that’s not when I decided to write about it. I was fixing some issues of a personal project, I saw the code almost after 4 months and guess what, it seemed to me crappy. I couldn’t believe, the code I wrote myself in complete consciousness seemed vague in front of the glorious structure MVP presents. Being fascinated by the fame of MVP I decided to write about it.
So without wasting any more time, I will try to answer the questions to best of my knowledge which I used to have when I started using MVP.
The beauty of the Android platform is that it is unopinionated. Android allows you to design application the way you feel comfortable. This nature of the platform gives significant power to create great apps, but as it is said:
“With great powers comes great responsibility” — Uncle Ben
As the app grows, the code base expands; it becomes tedious to maintain and add new features to it, and the need to use some architecture pattern hits hard.
So what to do when the dark clouds of complexity hover around? MVP to the rescue. MVP was designed to improve the separation of concerns in business logic. OK, I thought this was intended to cover the basics, and you are going all fancy here by stating these technical terms. In most simple words separation of concerns can be explained as, breaking code into meaningful chunks that can and should perform independently.
Implementing MVP also improves testability of code. Huge apps with piles of code cannot be tested manually and efficiently. Writing unit tests can be a pain sometimes, it may seem extra work, but if done they solve multiple problems. Firstly, unit testing makes the app robust. You get to know a lot more about the function of your code and how it may behave on different inputs. Secondly, Unit tests act as a user manual for developers to be joining the project. They give them step by step instructions of what the app does. Unit testing is in itself a huge topic, so I won’t be covering that in here.
Okay, read a lot of your chit chat about MVP, but how to even use it? How can it be implemented? When it comes to implementing MVP in Java programming language for Android apps, I must say there’s no secret mantra except one and that is Interface. The technical details of interface, like it is implemented in classes as Java does not support multiple inheritance, it cannot be instantiated blah blah blah, are all good to know, but what exactly an interface is conceptually?
In Java programming language, an interface is an abstract type, an idea that is used to specify a behaviour that a class must have. It can be said as a set of rules, and any class that agrees to use it must abide by the rules specified. Interface by definition insists on following a thoughtful structure. When we use MVP, we need to clearly define what is the role of any component and interface comes in handy and they always prove good for testing as you don’t always need to provide a complete implementation of everything.
So for implementing MVP, it is required to know what individually Model, View and Presenter are.
The secret being disclosed.
So for starters let’s take View into consideration. What exactly a View is? Is it related to View class of Android? Let me make it very clear that View of MVP has nothing to do with View class of Android platform. View is simply a java class that is responsible for making changes in the User Interface (UI). For example, change in the text of a TextView, change in text size of an EditText, change in colour of a Button or any other User Interface related change. In Android, an Activity, Fragment or any other component that can change the visual presentation is referred as View. Phew! That was a secret.
Since we are talking about implementation, I must say, to follow MVP’s principle of maintainability and testability a View interface must be defined. This interface contains method declarations associated with changes in visual representation. Activity or Fragment should implement this interface to define the complete functionality. Using this approach allows to pass the just an abstract implementation wherever required and can easily be mocked.
It’s commonly stated that dumber the View, better the implementation, i.e. the View should have as less logic as possible. Every logical processing should be done in the Presenter. Though it can contain logic for visual display.
It’s good to keep in mind that whenever a someone’s referring a view, they are trying to point to the activity or fragment that is implementing the View interface.
So what’s a Model? As the name suggests, has it anything to do with some structure? Again, Model is the component which is responsible for getting data in the app. The methods are declared in a separate interface which is defined keeping in mind the maintainability and testability of MVP’s principles. Yes! That’s it.
Model is responsible for data management
For making a concrete concept of what a Model is, it’s necessary to know the common data access patterns of app development. If we see on a broader level, an app fetches data from some REST API and stores in the persistent storage for easy access in the absence of network connection. An app must provide a coherent experience in the presence as well as in the absence of a network. So for providing a consistent experience, a Model must include methods for fetching, inserting, modifying or deleting data which should remain common for both network scenarios, i.e. no matter what the network state is using Model’s method the app can get relevant data.
The model is divided into different parts. The parts may vary as per the required implementation but basically these consists of local database handling, network APIs handling (for getting data from web service) and preferences management. These individual parts manage the logic for getting data and giving back to the presenter.
The API Manager, the Database Manager and the Preference Manager contains logic for providing data to the presenter and taking data from the presenter and storing it. Separate interfaces are defined for each of these and are implemented. These interfaces are created to avoid passing the concrete implementation of these classes hence making the testing area wide.
Now let’s shift our focus to the most important of the three i.e. The Presenter. It’s the one that connects all the other components together. It’s a class having the working logic of the complete application. An activity or fragment which is the View should pass data to the Presenter and it’s a responsibility of Presenter to handle it. The View interacts with Presenter by calling its functions. The functions are declared in a separate interface and the same is implemented in the Presenter. The presenter has basically three important functions:
The Presenter should not contain any Android specific component like Context, Activity, Fragments etc. They make testing hard.
This is how the MVP is implemented but the implementation styles vary based on coding style and requirements.
“Some of this makes sense. But how these MVPs are created?” An abstract idea of MVP is presented till now, thinking of the creation of these will add more juice to it. Naturally, any of these components are not pre-existing in the Android framework. If we put some thought, View is the component which is closely related to Activity and Fragments, and these are the core components of Android.
An activity creates Presenter. Presenter takes in View and Model as arguments for getting the job done.
OK, it makes some sense, but how many Models, Views or Presenters I need? I would rather say that’s functionality dependant. You’ll get to grasp more about these things when you’ll dive deeper.
If I would have to present a vague idea of this I would say, for every dissimilar Activity, you should make one set of Views and Presenters and Model remains the same for all.
These were answers to the major questions I had when I started. I would like to convey that MVP is an architecture pattern and its implementation varies depending on requirement. I hope this adds something to your understanding about MVP. Here are some references that helped me getting to know MVP better.