As a developer I’ve always enjoyed reading various architecture related articles. What I liked the most about them is how they pointed out at possible downsides and upsides of using one type of architecture above the other. Furthermore, architecture is one of my favourite subjects regarding iOS development due to its controversial nature originating from the MVC pattern. Due to that architecture-related articles are usually strictly opinionated, because I believe it’s difficult or even impossible to write such article without sharing your personal opinion. It’s almost like writing a review - it’s always gonna be subjective, but that’s the whole beauty of it. You can agree or disagree with someone else’s opinion, but you shouldn't disagree with the facts.
That’s the first time I’m writing such article but please, bear with me. It is based upon my 3 years of experience developing iOS applications professionally and during that time I have worked on various types of projects, from simple apps being just pretty representations of JSON to really advanced projects where we took advantage of framework oriented programming. As mentioned before, I have read many books and articles regarding software architecture, tried many of the approaches, failed multiple times and learned from these failures. And as I still believe there’s a lot for me to learn, having that experience under my belt gives me pretty strong foundation to finally share my opinion.There’s a pretty strong chance you’ve heard about MVC which is a default, standard architectural pattern for developing iOS applications. Among all of the architectural patterns we use on iOS, there’s probably no other one that brings so much controversy. You probably know too that there are multiple alternatives to MVC like MVP, MVVM or VIPER. All of them have their own advantages and disadvantages, can be implemented in many different ways and there’s no happy medium which can be used for all use cases (because if such thing existed, there would be no point in having a choice, right?).
The sentence above is one of the most often used sentences when it comes to any iOS Architecture related subject. I’ve seen it multiple times in various architectured related posts, heard it during meetup or conference talks and overall it is also one of the “undeniable facts” willingly repeated by the community.
But there’s one thing which can be easily forgotten about theory of MVC standing for Massive View Controller. It is a horrible, dreadful lie which can be harmful - especially for junior developers. Furthermore, it originates from a Twitter joke from early 2013 and in my opinion is taken way too seriously even 5 years later.
MVC stands for Model View Controller. It is an architectural pattern introduced in late 1970s which gained its popularity few years later. Furthermore, it can be easily said that this architecture was present during the birth of the software development we know nowadays and is widely used on multiple platforms, not only iOS. It is a crucial element of many popular development frameworks like ASP.NET MVC, Laravel, Spring or Ember.js. It also doesn’t differ much from Android’s implementation of Model View Presenter.Apple chose MVC as the default iOS architecture for a good reason. Firstly, it fits the ecosystem perfectly as macOS development world used exactly same pattern before the introduction of iOS. It allowed a smooth, painless transition for already skilled macOS developers. Secondly, MVC is just a perfect match for beginners - it’s simple, as it requires only three major layers to be implemented. With other iOS development tools provided by Apple like Storyboards or Target-Action and Delegate patterns it’s obvious that iOS Development it’s meant to be simple, at least at the early stage, to allow the developers to prototype rapidly and not to scare them off.
At this moment everything sounds great, so why exactly does MVC receive so much hatred in the community? As it turns out, it’s again the simplicity.
If something is simple, it doesn’t necessary mean it’s supposed to be easy. Actually, it often takes a moment to understand how MVC pattern can be used properly as a software development tool in the world of iOS. I believe that most of the problems with MVC in production environment are usually caused by lack of proper understanding of other essential iOS patterns like the Delegate.
Many software development tutorials or even WWDC videos, teaching us how to take advantage of certain elements of the SDK show us examples where the Controller is a delegate of other element. This other element sends callbacks which are later received and interpreted by the delegate.
Now let’s image a real use case based on this approach - an application displaying certain Points of Interest on the map depending on the user’s location. Here’s a quick list of parts that need to be implemented in its simplest form:
Out of these three, at least CLLocationManager and MKMapView require an external delegate. If they both will be delegating to the controller, the controller will implement at least two additional protocols. Also if the URLSession calls will be executed directly in the controller (let’s say in the viewDidLoad method or via Target-Action, like it’s often shown in educational materials) the controller will quickly start to swell. Now imagine your client wants you to cache these POIs in the Core Data storage to make the application work offline. We’re only adding more code and it’s a quick way for your Controller to become massive.
Now let’s think about the same use case a little bit differently. Controller is still meant to provide an interaction with the user, but it’s not said it’s meant to be delegate for all of your objects. Instead, let’s try an approach where your Controller in fact delegates the tasks to other objects:
This way, entire delegate logic is no longer stored inside the Controller but inside the mentioned third party objects. That also brings us some of the benefits that were not possible to be accomplished in previous approach:
If there’s one architectural pattern you should master except of MVC, Target-Action or Delegate it’s definitely the Composite. The reason for that is that Composite by its nature leads to other great architectural practices. But having just these four in mind is enough to make sure that we can save our Controllers from becoming massive. Untestable, large codebase written with MVC pattern can (and should) be a myth. Bad usage of architectural patterns is always a serious problem.
Does it mean that all tutorials, conference talks or WWDC videos should use the similar approach to the one above just to save us from bad practices? Of course not. These sources often teach us to use the Controller as a delegate for one simple reason - they’re not meant to show us good architectural practices. Instead, they’re meant to show us how to use a certain functionality, like the Core Location Manager in the simplest, most seamless way possible. And it is important to keep it simple, just to make sure that every developer at every stage of his career would be able to benefit from such lesson without unnecessary confusion.
But are MVVM or VIPER really superior to MVC? First of all, they’re more composed by default which initially gives us a better clue on how the code should be structured. Proper understanding of these architectures greatly decreases risks of making a mistake due to their more detailed nature. But still, it shouldn’t make MVC look bad - the architecture is fine as long as it’s implementation is correct. And if you’re not sure which one to choose for your application - stay tuned for second part of this post, where we will discuss the architecture you’ll fall in love with: the MVA pattern.