Last week I saw a blog post float around called MVVM is Not Very Good, and I specifically avoided reading it because I was having a not-great week and I was afraid I would take the blog post personally. Well, this morning I read the article and here I am writing a response to it.
So let’s break this down. The post levels a few criticisms of MVVM:
I actually agree with all of these.
MVVM is poorly named. Why don’t we rename it? Great idea. MVVM is a pretty big “umbrella term”, and precise language would help beginners get started.
When articles introduce MVVM, their focus generally is to get developers to move as much code as possible out of view controllers. Since view controllers do everything in MVC apps, there has to be a place to move all that stuff in MVVM. Introductory articles on MVVM instruct newcomers to just cut-and-paste it to the view model.
That’s a great start, but it’s just a start. Here are a few definitions aimed at MVVM newcomers:
A view controller only binds user interaction and data display.
A view model is everything that your view controller used to do, except for anything that directly touches the views.
We could definitely strive for more precise definitions, but the reason these ones persist is to make MVVM approachable for beginners.
Ok, so MVVM is poorly named and uses loose definitions, and that leads to some confusion. But that’s fixable! Everything is fixable.
Next, does MVVM encourage objects that have many responsibilities? Sure, I guess it does. But again, the alternative that most iOS developers are familiar with is a massive view controller. So compared to MVC, MVVM is just telling you to use objects with one fewer responsibilities, which is a step in the right direction!
I’ll tackle this question later on, but Soroush links to his article discussing ways to reduce view controller complexity, which I really enjoyed. His main principle seems to be to separate distinct responsibilities into distinct objects, which is an awesome idea.
There’s nothing inherent to MVVM that precludes one from following his advice. In addition to view models, I also have network models that help keep view models to a minimum. But that breaks my above definition of view models, shoot! Looks like that question of definitions is bigger than I thought… I’ll get to that in a future post.
So finally, the last claim is that MVVM doesn’t change your structure. As evidence, Soroush links to an article I wrote. My intention is to help readers understand that MVVM isn’t unfamiliar, that it’s a cousin of MVC. It’s aimed at readers who need help taking the first step away from massive view controllers; the article’s point was that MVC and MVVM essentially are the same.
Despite this, I argue that moving to MVVM (keeping the existing app structure, plus view models) is still a great idea. Separating as much code from the view layer as possible makes it way easier to further factor those components into smaller-yet objects.
Separating out view models and view controllers isn’t just to make future work easier – it also provides you with an extremely important, immediate benefit: better testability. Now that view controllers are thin, you can use stubbed view models and test your view controllers visually. Similarly, the logic in your view models is now far easier to test because it’s not touching the views at all.
A statement like “MVVM is not very good” implies that “MVVM is worse than what we already have.” But what we have are view controllers that are hundreds of lines long and do everything in our apps. And MVC tightly binds all our app logic to UIKit and the
UIView lifecycle, which makes them incredibly difficult to test. As a result, they don’t get tested. I don’t blame us – even the Ruby community struggles with this.
Learning to program is a journey with no end. I believe that for the iOS community, MVVM is one stop along that journey, a layover to even better places. But these are all just stops along a journey; we can’t stop at MVVM, we have to keep moving.
However, the iOS community is so stationary that it’s very difficult to get everyone excited about this journey. So I’ve been trying to just get people excited about the first stop.
View controllers, ugh.
So untestable and bad.
—Ancient MVVM Haiku
When I read Soroush’s post this morning, to be honest I felt a bit attacked. But after reflecting, it’s pretty clear that we both want the same thing. I can’t speak for him, but I suspect that we’re both frustrated by the slow pace of the community.
I hope that no one misinterprets my emphasis on MVVM as a belief that MVVM is the final destination. Far from it. I hope that by using MVVM, people are freed from the belief that they must write software like Apple writes sample code, and we can keep the momentum up.
(Side note: I think one of the most beneficial decisions that Apple’s made recently, from a developer community perspective, is to not release a large amount of Swift sample code. Instead, they’ve left it up to us. This has really helped the community realize that we are in control of our own destiny.)
Is MVVM perfect? No of course not. Is it an improvement? I think so. And it makes other improvements a lot easier.
I’d rather have a 50-line view controller and a 400-line view model than just a 450-line view controller. A view model that long is doing way too much, but it’s a step in the right direction. And it makes following Soroush’s great advice on reducing view controller complexity way easier.