The last couple of years there has been a lot of discussion in the community about one of the most pressing issues when it comes to writing maintainable applications.
And that pressing issue is no other than the size of view controllers. View controllers tend to become a kitchen sink, a mix of responsibilities, that handle networking, deal with navigation or validate user data.
MVC, or at least the flavour of MVC recommended by Apple’s documentation has been partially blamed for it. And MVVM has been suggested as a better practice, designed to avoid finding yourself with a huge view controller that does too many things.
But here is the thing: I don’t think MVVM is intrinsically better than MVC. Nor the other way around. I have the feeling that sometimes MVVM is sold as some kind of silver bullet that, in combination with a more functional style, is going to, magically, make our lives easier.
I love the idea of separating presentation and presentation logic, which is something MVVM advocates for. But, I don’t think that, by itself, is enough. I think it is necessary to do much more than just embracing a different pattern, no matter how good that pattern looks on paper.
I believe this book (highly recommended, non-affiliated link) is the first one where I read about the idea of micro-architectures. Basically, the idea is: when facing a problem, don’t try to think too big, try to build a solution that solves the problem in a clean, extensible and testable way.
I think that micro-architectures pay off at a local scope. But the way micro-architectures really shine is by accumulation. When you start solving small, limited in scope, contained problems by architecting the crap out of them, everything else starts falling into place, and you start noticing how an application-wide architecture starts emerging.
How? A local, isolated, solution usually leads to a better solution at a wider scope, which usually shows the way to a better solution to an even wider scope.
For example, if you remove from a view controller the responsibility of creating and navigating to another view controller by adding a class to the system that takes care of doing that, you might find that if you inject that class into every other view controller you might generalise it to deal with all the navigation logic in your app. So, now, you need to find a way to inject that NavigationManager into all your view controllers, so it might make sense to have another class that takes care only of creating view controllers. It would be great if you could pass your NavigationManager to this new UIManager, so you might need something that creates both and injects one into another. That could be an ApplicationBootstrapper that you create in the App Delegate. See the pattern? Decisions at a local level propagate up, so you can build an application-wide architecture from the bottom up.
The point I am trying to make is: applying the SOLID principles everywhere, all the time, is going, by accumulation, to produce well architected, maintainable and testable applications.
Embracing MVC, MVVM, or whatever goes into fashion next, by itself, is not going to be enough. I think it is better to embrace whatever pattern you understand better, or think is good for you and your application, or you can reason about better, and keep always a vigilant and critical eye on every decision you make. Trust your instincts, and as soon as you notice a bad smell, micro-architect the crap out of whatever you are building.