The all new, better than ever MVNCMVCCM Design Pattern
It seems like every week we have a new design pattern pattern for structuring mobile applications, each one better and shinier than the last. In fact, most are not new at all, MVC, the one everyone knows, has been around for over 40 years.
Then there’s MVVM which has been around for over a decade and has gained popularity in the mobile space recently, mainly due to the rise of Functional Reactive Programming which itself is not a new concept. Speaking of which, I’m not quite sure when writing apps became so complex as to require a solution of this magnitude, unless of course you’re working on something the size of Facebook, which you’re probably not. I particularly like Brent Simmons post on how he would approach a typical problem that FRP aims to solve. His approach is tried and battle tested, simple, easy to understand, you don’t have to rely on any huge third party frameworks or to have to sift through mountainous stack traces when something goes wrong.
I do see FRP being useful for binding a view model to a view over using something like KVO, however beyond this it feels to me like overkill.
More recently, three years ago in-fact, Mutable Mobile introduced us to how they architect their iOS Applications, they call it VIPER. The main purpose of VIPER is to enable the clean architecture by breaking down code into smaller modules made up of components which only know about certain other components. I really like the idea, loose coupling and smaller classes can only be a good thing. However there are parts of the execution that keep me up at night whenever I’ve attempted use it in my own projects.
Firstly, the Wirefame (strange name, I like to call it a Router) knows way too much about everything. It’s only responsibility should be navigating from one scene in your app to another, however if you’re being a good citizen and using dependency injection when constructing your View Controllers, it needs to know how to construct View Controllers, for this it needs to have access to it’s dependencies, and then access to their dependencies and so on. Then you need something to set this wireframe up, and before we even get started we end up with something like objc.io’s example:
Secondly, there’s the sheer number of boilerplate files (usually protocols) that need to be created to sit between the View <-> Presenter and the Presenter <-> Interactor so each object doesn’t actually know the real object it’s talking to, most of which you’ll struggle to name in a consistent manor, creating a steep learning curve for newcomers to your codebase.
Finally in larger project’s you’ll inevitably have functionality which doesn’t fit into any of the VIPER camps, or doesn’t even make sense as a VIPER module. At this point, you’ve coded yourself into a corner and will either try hammering a square peg into a round hole, or have part of your project written using one architecture and the rest written using another.
I’m not saying don’t use VIPER in your project, depending on the requirements of your app it may be ideal for you and I’m grateful to Mutable Mobile for going out of their way and sharing it with us, it clearly works well for them. Also, thanks to objc.io for sticking their neck out and actually providing a useful example of how you can use VIPER to architect an iOS application.
Then, this morning I watched Marcus Zarra’s talk on his approach to architecting iOS apps, using what he calls MVC-N (I’m pretty sure he doesn’t call it that, but it obviously sounds better with a familiar looking acronym). I had the pleasure of going to one of Marcus’ talks at iOS Dev UK last year, have read most of his books and always have time to hear what he has to say. The thing that surprised me the most, and one of the main reasons for all of these fancy patterns, is that people are still struggling, after all these years to write smaller View Controllers.
Marcus has likely worked on more codebase’s than most of us have had hot dinners and he says the most common ‘anti-pattern’ he comes across is networking code in View Controllers. Even after the numerous posts on how to address the Massive View Controller, are people really still putting networking code in their view controllers? If so, FRP probably shouldn’t be the first port of call for solving your problems.
As always, I enjoyed Marcus’ talk on MVC-N, networking code should not be tied to a view controllers lifecycle, and I particularly like the point of rolling your own networking over pulling in a mammoth dependency, especially since Apple have made it almost trivial with NSURLSession. If you have networking in your View Controller, following Marcus’ approach is probably the simplest change you can make in order to gain the largest improvement, its the lowest hanging fruit so to speak. That said, I do have one small gripe with this approach…
It’s the NSManagedObjectContext. Maybe it’s just me, but I feel uncomfortable having my networking layer know about my persistance layer. Not only that, the network requests themselves also know about the persistance layer…
You could probably get away with this in smaller applications, but as your application grows, what if you want to fire that same request but not cache the response? Yes you could pass in a parameter but that’s a sign that they probably shouldn’t know about each other.
I’ve worked on a number of apps over the years and I try to structure them in such a way that they are easy to understand for other people working on the codebase, that dependencies are loosely coupled and reusable, and that I’m not trying to be, as Marcus puts it, interesting or clever. This means that my approach, like Brent’s, isn’t particularly exciting, it doesn’t have a fancy acronym, and it isn’t fashionable. In fact it’s so boring I hadn’t even considered sharing it. However all of the above approaches have made me realise that people are still struggling with structuring apps. I started this post with the intention of sharing the approach I used for my largest app Completely. However given how long I’ve already rambled on, I’ll start a new post and come back and update this one with the link when I’m done. Perhaps it will be of use to anyone struggling to architect their own apps, whilst not wanting to use a sledgehammer to crack a nut…