Dr. Jekyll and Mr. Hyde: The True Faces of App Architectures

Teddy Georgieva
Dev Labs
Published in
11 min readApr 25, 2018

--

Starting out as a young iOS developer almost exclusively requires using MVC. All the Apple tutorials, all the books, all the beginner courses… Each and every one accents the importance of architecture and lists MVC as the bedrock.

Negativism is abundant, however, and if you’re subscribed to any iOS newsletters, you’ll notice the plethora of ‘Why architecture A is better than MVC’ articles that seem to get written every week.

Personally, I liked MVC. Still do, to be honest. It’s clean and simple, understandably a perfect choice for a novice. I’ve been using it for the last three years, stubbornly set in my ways. Factual evidence supported me, proving that any app can use MVC with little effort to support and test.

Well, facts changed and kicked my obstinate ass.

The latest app I worked on was probably the biggest project I’ve ever been in. And as it’s content and functionality grew, so did its complexity. Exponentially, so did the testing time. One of the view controllers had over three thousand lines of code in it with a multitude of information, and suddenly the mere thought of making changes in that class was worse than having the Grim Reaper knocking at my front door.

In the end it worked out but it was a child of labor and it’s an experience I rue having to go through again.

So, to be able to make direct comparison between different architectures I decided to implement the same use case with all of them.

In other words, even the odds and put different approaches through a crucible. A real life app architecture Survivor starring crowd favourites like MVVM, MVP and VIP.

The app itself is straightforward and hits all of the most common requirements with basic UI and networking.

Summarily, it allows a user to browse through a list of books (a simple collection view on the main screen). The user can navigate to a book’s detailed page, to a list of reviews screen for a selected book and access a search from the main list.

Networking is very basic, its most complex functionality being pagination on the browsing list since that’s a standard often employed when dealing with lengthy amounts of data.

The goal of this project is to evaluate the complexity, learning curve, separation of concerns and testability provided by different structures.

This article aims to give you an insight into how different architectures handle some of the most basic tasks you need to perform in an app. It doesn’t assume or make decisions for you.

The choice of architecture is entirely up to you. I’m just sharing the final results of a fun experiment.

MVC with child plug-ins

For starters, I decided to try a variation of the MVC architecture to see how much variety it can take and whether a smarter, more isolated, approach wouldn’t improve this Apple staple.

I came across Swift By Sundell’s article called “Using child view controllers as plugin”.

Keeping the original architecture while isolating some basic functionality seemed like a smart approach to me, minimising the learning curve and, hopefully, proving that an old dog can, indeed, learn new tricks.

So, what are the pros and cons of using the above mentioned approach when building your app?

Pros:

  • Smaller view controllers

Massive View Controllers is an often met word play on the MVC initialism, showcasing its most distinct con. Using child view controllers as plugins to “insert”new functionality into an existing view controller can make them considerably smaller since the child view controller handles all of it’s own functionality without the parent knowing about it.

In short, each class is responsible for handling it’s own logic.

  • No base view controller

It’s also convenient when your app has a list of repeated behaviour which you can easily separate in a single view controller and using it as and wherever it’s necessary thus avoiding lengthy base classes that keep tons of functionality and have a difficult time separating concerns.

  • Subclassing

Programmers are used to hearing that repeated code is bad practice. You have to refactor every bit and piece to make sure you don’t have two of the same line of code.

Creating a base view controller and making all other view controllers subclasses of the it is one of the easiest, most basic ways to manufacture a place to insert all of the functionality you need access to app-wide.

It’s not a bad practice. I’ve used it in numerous projects to the point it’s more instinct then conscious thought to implement such a controller.

Subclassing the base view controller, however, means you can’t use build-in UITableViewController or UICollectionViewController. Thus, ease of use is sacrificed to avoid duplicate code.

Using child view controllers is an easy way to avoid this while maintaining a stable and isolated base with little to no undesirable code clones.

Cons:

  • Dynamic layouts

One major setback had to do with dynamic layouts and the difficulty to implement them, especially when the size of the child view controller’s content needs to be calculated at run time. At one point I had to initialise a child view controller twice so I can calculate the right frame when I needed it.

Admittedly, my own approach might have been erroneous and caused me to encounter this issue. But design is often complex, flexible and dynamic. The risk of breaking code or encountering complications when implementing a design outweighs any architectural benefits.

MVP

The natural continuation after the Model-View-Controller architecture is the Model-View-Presenter, which is a derivation of MVC. Often used in Android apps, this pattern revolves heavily around displaying data for the user, introducing a Presenter class which acts as a middle-man and handles all presentation logic.

The pattern aims to get rid of presentation logic from the controller, killing two birds with one stone — eliminating a controller’s awareness of the model and removing all presentation logic from the it, thus making it smaller and more manageable.

Arguably, there is little difference between the MVC and MVP architectures. The presenter does a fine job of letting the controller have access to nothing but necessary information. And if done correctly, handling data refreshing is somewhat easier when using the presenter, lowering the number of additional properties for storing the data and methods to format it in the controller.

Choosing one over the other depends on the project.

I would use MVP in apps dealing with statistical data representation or concentrate on analytics and graphics. If you’re doing heavy duty data manipulations before you present any particulars to the user, getting all of that logic out of the view controller is a blessing.

It’s a clean way to keep the focus on breaking down the data and formatting it rather then simply showing it to the user.

Stick to MVC if your data doesn’t require much work. If all you have to do with an API response is show the user’s name in a label, choosing MVP will do little to enhance your app’s structure.

Pros:

  • Smaller view controller classes

As mentioned above, if your data needs massive amounts of work before it’s properly formatted and ready to be displayed to the user, separating that code in another class will significantly reduce your controller’s code mass.

  • Better separation of business and presentation logic

When you remove the presentation logic from the view controller, it only cares about showing information and navigating between screens, whether programmatically or with segues.

Parsing the backend information falls squarely on the model’s shoulders, relieving the controller of the burden of dealing with networking. The controller doesn’t spend time trying to get the information, the model does that. It then sends it to the controller which knows only how to show it.

  • Flexibility

Letting the presenter handle all information, making it ready for display is a sure way to make your code flexible.

Imagine having some data that needs to be presented in the same way in multiple view controllers. Implementing that data’s presenter in all of them means that whenever some data management is needed, the modifications need to be implemented just once in the presenter and all of the view controllers using this presenter will have the new information readily available.

  • Test driven development

Since the entire logic is in the presenter creating proxy presenters and catering the data to the tests is enough to dig out most errors.

Cons:

  • Extra learning curve

While admittedly easy if you’re already used to the MVC pattern, switching to MVP will take some time to get used to. It may be a single day or an entire week to get all members of a team up to speed, so factor that in when making an estimate.

  • Presenters could become massive as well

While removing the presentation logic from the controller might help to slim the controller down, all of that weight has to go somewhere. Presenters run the risk of becoming just as massive as their controller counterparts in the MVC structure.

  • Test driven development

While testing a presenter is quite straightforward, creating a lot of dummy presenters might take some time and effort. It means creating an additional presenter for every one you already have in order to test it. Another thing to consider when estimating for your project.

MVVM

This initialism stands for Model-View-ViewModel. Similar to Model-View-Presenter, the difference lies in the presence of a ViewModel. In a way, it is an implementation of the Observer Design Pattern, where changes in the model are represented in the view as well by the ViewModel.

For example, if a slider changes, not only is the model updated but the data, i.e. a text that is displayed in the view, is updated as well.

Choosing between MVP and MVVM depends, I think, on how “reactive” your approach is.

MVVM leans heavily on the data binding principle. Since iOS has no native approach for data binding (even with KVO and notifications), the most efficient way to use MVVM and get peak performance for your app with it is to chain MVVM and Rx. MVVM helps to distribute the responsibilities and the reactive approach helps to bind the view model with the view.

I would advise caution when using MVVM. Originally created by Microsoft for XAML application like Silverlight, MVVM is a patten adopted for mobile platforms and modified the best it could be.

So, be weary when attempting to use it and make sure you’ve got all of it’s complexities down pat before using it in more complicated apps. There are some outstanding questions, like where to put the networking code. It’s very open to interpretations and while the amount of flexibility and adaptability is liberating, if it’s your first time and the project is big, it’ll hurt.

My advice is to try it out with a sample project beforehand and calculate in a few weeks for the learning curve.

Pros:

  • Business logic is separated from the view controller

As with the MVP pattern, separation of concerns is well handled. The Model does model-y things, the Controller — controller-y and the new guy, the ViewModel, is the carrier pigeon that connects the two.

The job of the controller is only to handle interactions with the view and send them to the view-model

  • Improves readability

Once you have a basic understanding of how MVVM works making it through the code of a project that uses it is, indeed, a breeze.

  • Easy to update if new logic is needed

Since the ViewModel handles data presentation, introducing changes to the display logic is as effortless as adding an extension to a type in Swift.

  • Module based

Cons:

  • ViewModels can become big

Since the goal of picking the most fitting architecture is to make the life of a programmer easier, which automatically means avoiding the strain of scrolling through thousands of lines of code, be aware of the risk ViewModels carry for over inflating and becoming quite burdensome with functionality.

  • Complexity depends on the application itself

VIP

VIP or Clean Swift architecture was kind of a last minute edition. It’s derived from Uncle Bob’s Clean Architecture.

Whereas MVC is structured around controllers, VIP interprets all screens line scenes. Every scene has a number of components, each with its own task. Each component handles a different task for the controller thus separating concerns and sandboxing functionalities so every component knows no more than it needs.

Every scene has:

  • controller
  • interactor
  • worker
  • presenter
  • configurator
  • router
  • models

Imagine you have to make an API request to get some data when the user selects a table view cell.

The controller handles the selection and instantiates a request, which it then sends to the interactor.

The interactor takes the object and asks the worker to perform some work, in this case a networking request.

After the worker is finished, it sends the response data to the interactor which in turn sends it to the presenter.

The presenter takes the data and formats it, before creating a view model to send to the controller.

The controller’s task is to show the formatted data from the presenter or, alternatively, use the router to invoke a segue and transfer the formatted data to another scene.

No need to lie, it is a lot to wrap your head around. Admittedly, the learning curve is steep but the separation of responsibilities is great.

To shorten the time it takes you to learn VIP, you need to have a solid understanding of how protocols work as they are the main method of communication between the different components.

Also, I would advise you to research and read as many articles and tutorials as you can before attempting to use this one in a more complicated project. Similar to MVVM, VIP is quite liberal. While each component has a concrete role, the communication channels are up for interpretation. I’ve also seen different versions of models and view models interpretation, as well as networking or navigation.

Learning to swim in the shallows first is better then jumping into the deep end without a life jacket.

So, start simple and build from there.

Pros:

  • Better separation of business logic and presentation:

Presenter — handles the parsing of the data from the Interactor to the View controller

Interactor — handles the conversation to the API to the local storage

Router — handles segues and transitions to different controller

Controller — handles presentation of the information and interactions with the views

Worker — handles API calls and local storage information fetch

Models — parse the information from the API or local storage

  • Smaller classes

With each component handling its own set of functionalities, classes don’t get clustered with tons of information and trying to be all, end all. Thus classes are kept clean, simple and adaptable to changes.

  • Improved readability

Just like consistent indentation and good documentation, fewer lines of code make classes easier to read. Less is more, right?

  • Protocol based

Above, I pointed out the protocol base communication as a warning. That doesn’t mean its a bad thing. Protocol oriented programming is always a plus. And if you’re an iOS developer, you should be used to delegation.

Cons:

  • Complexity depends on the application itself

Imagine a complex apps with multiple screens and both phone and tablet support, two storyboards… Now think about the fact that each screen needs up to 7 classes… That’s a lot of files to navigate through. So that’s something to keep in mind when choosing VIP.

  • Retain cycles due to overuse of protocols

Always keep in mind that protocols lead to retain cycles. Make your protocol instances weak and restrict protocol conformity.

  • Sometimes Workers or Presenters can become big

You might have avoided Massive View Controllers but that doesn’t mean you’re safe from big classes. Multiple networking requests or complex presentation logic can cause your Worker or Presenter classes to become clustered and burdensome.

And the winner is… up to you

So there you have it. The usual suspects all lined up against the wall and exposed.

Choosing an appropriate architecture is an important part of your workflow. Do so before you’ve written your first line of code. Refactoring the architecture later will cause you tons of grief.

Choose one that fits your app best, that takes into consideration flexibility and testability, as well as your estimate.

Mix and match, pick one out for one project, learn it inside out, then throw it out and pick another one. Don’t shy away from something because it’s new.

I could do this 10 times faster with MVC.

I can’t tell you how many times I thought that when dealing with MVVM or VIP. Workflow is always slower the first time you pick up something new.

Don’t get discouraged and be like a bloodhound — don’t stop looking for the scent and never let go when you find it.

If your app is a house, then the architecture is its foundation. So, be smart, be insightful and make sure your house doesn’t crash down around you.

--

--

Comic book fan. DIY enthusiast. iOS Developer. Writer. Aspiring designer.