The Transition to MVVM at TextNow
For years, Model-View-Controller has been the dominant presentation layer architecture for mobile applications, but with evolving technologies it may be time to rethink how we develop mobile software. With the introduction of Reactive frameworks in iOS, such as RxSwift and ReactiveCocoa, Model-View-ViewModel (MVVM) is starting to look like the best choice to develop modern iOS applications.
In previous roles and my current position as the Core Product iOS Engineer at TextNow, I have worked with several applications using MVVM and Reactive frameworks, and have even developed my own iOS application based around them. At TextNow, MVVM has played a big role in delivering consistent and reliable features to our users.
So you’re probably wondering what exactly is MVVM, and why is some guy trying to replace my beloved MVC (aka Massive-View-Controllers) with it? Well luckily for you, all of your questions are about to be answered.
What is MVVM?
MVVM is an architectural pattern for developing the presentation layer of an application. The key concepts used to develop an MVVM style architecture are:
- Using data bindings between the Views’ properties (textfields, buttons, images, etc.) and the ViewModel.
- Abstracting the business logic out of the View Controller and into the ViewModel.
- Abstracting the data layer so that it only lives in the model.
I know I just threw a bunch of tech jargon at you that is absolutely meaningless without context, so let’s dive into each of these concepts.
View: Handles all of the presentation logic and lets the ViewModel know about user behavior and interactions, as well as being responsible for UI updates.
ViewModel: Handles all of the business logic and exposes the data necessary for the View to properly update the UI
Model: Handles all of the data logic and abstracts the underlying data source so the ViewModel does not have to access the data layer directly.
Data Binding: Can be unidirectional or bidirectional. Allows data to flow through the View and ViewModel. Super important because it allows the removal of validation and business logic from the View.
Business Logic: Logic that dictates how data gets manipulated and stored.
Data Layer: Any interactions with persistent storage or network requests.
Why is MVVM important?
The main benefits you get from writing your code in MVVM are:
- Code becomes highly testable.
- Code clarity improves, as each layer now has it’s own job.
- Your Main View Controller is no longer 5000 lines — woo!!!
You are probably wondering why your code becomes so much more testable when making this switch, so let’s run through an example of creating a screen that accepts a user’s email address.
A few things to note here. First, we have set up data bindings so we can keep our View Controller code clean — no need for textfield delegate calls or validation on button press. Second, our business logic has been moved into our ViewModel so the View Controller does not have to directly interact with the model API. This allows us to call our ViewModel with closures for UI updates when it finishes. Lastly, our networking layer is completely on it’s own with just an API for the ViewModel to use. All of the things that we have done here are exactly what we described MVVM to be!
Now let’s do the same example in MVC.
Some of the issues with MVC include:
- Heavily reliant on View Controller state and life cycle, which will require an application test instead of a logic test.
- The View Controller does more than it should, making it very difficult to test a specific layer of the application.
What does this mean for testing in MVVM?
If we wanted to write a test for this it would be much easier than it would be in MVC. Instead of having to instantiate a View Controller and make it go through its’ lifecycle, we would instantiate an EmailViewModel and call email() directly with our own success and failure blocks. Easy right? The only thing that we haven’t figured out is passing in that singleton for our model. That’s where protocol-oriented programming comes in. We make a protocol called SomeModelType, which has the barebones of what we need to mock it up, and then make SomeModel, and our new MockSomeModel conform to it.
Now in our test class we can easily create a mock and pass it in as a parameter when creating the ViewModel. This allows us to test something that was not possible in a logic test before, while only testing the single layer of the application that we are trying to target (we aren’t making any network requests). The granularity of the type of tests that we can create now is super important because each layer can be tested individually and with ease.
Benefits of MVVM for TextNow
In order for TextNow to to scale up to the top of the Messaging App scene, we need a developer-friendly codebase and reliable automated testing. These two things, once set in place, will allow us to move quickly by making code much easier to develop, and will decrease expensive regressions. MVVM has proven to be a very helpful tool for increasing the testability of our codebase, and we are quickly starting to accumulate a strong test suite as we revamp and add features. The switch to MVVM has also given us the opportunity to adopt new technologies like RxSwift or ReactiveCocoa, which gives us a lot of flexibility with how we develop software.
Have you used MVVM? If so, feel free to leave a comment about your experience with it. Also, if mobile software development interests you, check out some of the openings on our careers page.