I have a keen interest in finding different solutions to a problem. Currently exploring different architectures for iOS applications.
Problems We Are Dealing With
In almost all user faced applications, we have User Interface, Business Logic, and Data modules. And every application we design, we want it to be easily Scalable, Testable, Maintainable and Reusable.
- Scalable: One of the scalability factors is how much dependency modules have on each other. It is difficult to change the system if the dependency factor between modules is higher.
- Testable: For unit testing, we need to isolate part of modules in order to simulate different behaviors a system can have (also known as Mocking). When operations are not divided into modules or the modules are tightly coupled then testing becomes very hard.
- Maintainable: It shows how much complexity of your program grows with the growth of functionality. If functionality grows to some extreme, managing the code base and its testing should remain easy.
- Reusable: This means make a group of operations called Modules and then use that module where needed rather than writing the same operations again and again.
To elaborate on different designs, let's consider this example. We are building a Profile Viewer application. It will be a single view (means only one screen) application that fetches your profile from the server and displays info on the screen. Users can also update their profile information from the same screen.
The quality of each method we discuss below will be measured by the design parameters discussed above.
If you are new to programming and not using some framework, then you might end up with one class ProfileView which have all the following:
- Profile data model.
- Network operations to get and save the profile.
- View elements e.g. Text, Label, ImageView, etc.
It will look something like this:
Lets gage this method with our design parameters:
- One class (ProfileView) that does all the stuff including UI rendering, loading and saving data, data model, UI updating and network operation.
- If you want to change anything you have to update ProfileView.
- Profile view knows exact data and its source which creates tight coupling.
- Difficult to mock the functionality of ProfileView to perform unit testing.
- We can test and mock some of the functionalities by subclassing ProfileView, if functionality is divided into proper unit functions.
- Class will become huge and complex even with medium functionalities.
- This method does not implement any reusable code as it should be. For example, it can extract network operations into a separate module.
MVC to the Rescue
This design suggests separating god class (described above) into three sections, i.e. Model, View, and Controller. Each section will have the following responsibilities:
- Model: It will contain the data of the application.
- View: It will display everything on the screen that allows the user to interact.
- Controller: It will glue View and Model together. It handles two things: first, it will get data from the Model and fill the UI. Second, it will get inputs from View and update the Model.
There is one exception to MVC, i.e. in the Apple version of MVC Controller and View are tightly coupled and it's difficult to mock view in order to completely test the controller class.
So now if we apply MVC on our ProfileViewer application it will look as follows:
Let's see how this method improves the previous method:
- Both View and Model are now lives and works separately in the application.
- View and Model are not dependent on each other directly.
- Controller knows from where to get data, how to convert it into displayable form and update UI.
- Controller is handling and reflecting all UI actions on model.
- Controller get very big if views are complex.
- We can test the model and services separately.
- We can test the controllers and UI by mocking the model.
- Testing becomes difficult (not impossible) when the controller gets big like lots of view, animations, lists, and actions, etc.
- Difficult to test different states of UI.
- As design has divided code in modules, it's easy to maintain different parts.
- The controller becomes messy when it gets lots of views, animations, lists, and actions, etc.
- We can replace different views with the same model/services.
- As we get Model through services like Api Client which will use Network Client to request server. All these modules can be re-used.
An Overview of What We Did
In this article we have discussed the following:
- Design parameters we are trying to achieve when we build user faced applications.
- How to design parameters affect the quality of the software.
- What is the naive approach and how it's not a good option.
- What is MVC and how it improves the design of the software.
There are other design patterns like MVP, MVVM, Viper, etc that also provides a solution to this problem.
I hope this article helped you in understanding the concept of MVC. Kindly do share your comments in the section below.
© 2019 BAG