The Model View Controller (MVC) pattern in iOS development is easy to understand, but hard to master in practice. This article discusses a modern approach of best practices to use in your apps.
I can understand the approach that you’re recommending and it follows best practices for MVC, but it seems like a LOT of overkill to architect the app this app. It seems less readable, less understandable, and more complex than what is necessary. How do you balance over-architecting with real world timelines and best practices?
It’s an overkill if you don’t take into consideration testing at all, then yes it is. There is also an entire infrastructure created to enable easier expansion of the app. You can always make it easier and more understandable if you put everything (or almost everything) in the ViewController.
I would say the balance relies on the time you have and the duration of the project. You should ask yourself:
Is this just a proof of concept?
Am I going to maintain this?
How likely is this project going to change (new features, edit the already existing ones), or how stable are the requirements?
How about the storyboard or nibs, it seems that all views in the sample is made by code. So it is not recommend to use the storyboard in this approach? And the another question is how can we correct use dependency injection with storyboard.
One thing you mentioned is “…parser [is] domain-specific”
Why do you say that?
Could you not use your model object as the template, and a parser just uses reflection to map fields to the parsed values. This way the only domain specific part is now the model, the parser doesn’t care.
Nice article! But when a VC is designed up by code, where should that code be? I ask because I still can’t draw my UI completely in code but I’d like to learn sometime
Swift reflection doesn’t provide enough information for that to happen. You still need to tell the compiler how the JSON properties map to your object properties.
I find using Storyboards cumbersome when you want to rely in dependency injection… You can still make it work, but you need to expose publicly the dependency in your UIViewController, which I don’t really like.
Often good code seems like an overkill as you describe it but in the future you’ll thnk yourself about doing this job in the beginning of your project.
The benefits of writing a good separation of concerns (which in my opinion is the ultimate goal of architecture) could come in terms of reusable components that you can later reuse in other projects, or even add co workers more easily, as the basis of how to expand an app (adding business logic or new screens) becomes so natural that it tends to speed up development.
@rperes mentions that you should balance some key points about how to decide if the extra work is or not worth the time, but in my experience you would always like to use good architectural patterns for every project you make, so you can refine your knowledge of how to implement architecture patterns.
Most times a project starts from a POC, and for “time saving” (note the ") the same project is going to be used, it will be good to start with a good base.
I think maintanance will always happen, except for project where the objective is too investigate some new features (I recall making some of these for constraints and animations)
Almost every project constantly changes and don’t have stable requirements (sorry, this is the real life)
Adding no. 4
For modern languages, we now have playgrounds for quick POC development n.n
There is a thing to be pointed out: In the beginning there is a phrase “Every new iOS developer is exposed to a huge amount of information” that gives the reader a sense of material for beginners and then in the second part the article turns everything in advanced programming direction with protocols and delegation. Is this article for beginners? Is this article for experienced developers? It’s not clear. For the beginner the second part is almost non understandable. For experienced developers the first part has almost no sense.
Please, in the next time clarify the target audience since the beginner may be catastrophically frustrated by the fact that he/she is not able yet to understand the second part. Please, do not forget that software development is actually hard and beginners may feel bad about themselves because everything in the beginning of the article was simple and then suddenly non of the material is understandable.
I didn’t mean to judge, these were my thoughts. I appreciate the effort that you put on this reading. Thank you for that.
The article audience is quiet broad. A beginner should be able to pick it up and use it as a recipe and also to intermediate devs, that have used MVC before, but felt something was off with Apple’s approach.
Looking at the article from your POV, I can see that for beginners, it might be a challenge. Nevertheless, with the demo, we wanted to show best practises, which sometimes are not “easy” to understand, but make wonders for our project ( easy != simple )
Please let me know, if there is something, in the demo, or the article, that isn’t clear and I will try my best to help you.
Great article, I liked all the practical tips and guidelines. I agree that making the demo section a little clearer for readers of all levels (e.g., no protocol-oriented programming) would make it even better! Thanks for writing this.
Hi, thanks for the wonderful article… i was wondering how would you go about handling image downloads in a situation where the model only has a url to the image to be displayed. For example lets say each of these talble view cells had an imageView showing the profile pics of the users, and the model only stores the URL to some S3 bucket… where would you put the image fetching code?
Good article, small nitpick - calling fetchAttendees() in viewDidLoad() is making the view controller smarter than he needs to be. Would be better to call handler.onViewLoaded() and inside of there you would call fetchAttendees. Also aids in long term maintenance of keeping the view controller small i.e. if additional calls need to be performed on viewDidLoad they get added to handler.onViewLoaded() instead of viewDidLoad().
Some notes that might help in the description of MVC.
Model - The classes in this layer contain the special “business logic” and address the problem domain that the app is all about. One set of classes may contain calculation logic. One set of classes may contain data persistence logic. One set of classes may contain network communication logic. The Model is the layer that makes the application valuable. It should be able to stand alone with out dependencies on the View or Controller layers.
View - The elements in this layer, whether they be classes, story boards, xibs, etc. are the part of the application the user interacts with. They contain the Buttons, Text boxes, WebViews, etc.
Controller - The purpose of the classes in this layer is to decouple the Model from the Views. Users interacting with elements in the view result in requests made to classes(objects) in the Controller layer, which in turn may request changes to information in the Model. Changes that happen in the model are also sent from the Controller to the View.
Here are some great resources to help dive into MVC, Separation of Concerns, Architecture and more!
Cocoa Design Patterns - Erik M. Buck, Donald A. Yacktman
Clean Code - Robert C. Martin
Application Architecture Fundamentals - Bob Tabor - http://learnvisualstudio.net
Hmm this is interesting and I see what you are trying to do but I feel like this way just makes it more confusing to understand, follow and even debug.
I always got the impression Apple likes to combine the view and the controller. You are trying to remove the controller from this but you kept the same naming conventions. I see the idea of removing the logic more for testing but this should be easily done if your models and your logic is done correctly without creating an extra controller.
I feel like you now have 2 controllers. So it’s more like a Model-View-Controller-Controller.
I would also like to mention that in my opinion a model should have almost 0 logic. Maybe some stuff associated with serializing it but generally should be super simple. The networking code should be completely decoupled from a model object entirely and models should just work with systems its handed off to. This can be your viewcontroller (or your viewcontroller controller you have) or it can be your networking code. Maybe you store it in SQL so you can have a SQL class that can accept your model. These would of course use a protocol or delegate to keep it decoupled from a specific model.
Maybe I am wrong but this seems like it provides a ton of extra overhead to deal with when you should already have other classes designed for networking, model updates, storage or whatever you need. The viewController should be able to ask for the data it needs from the right places and then just display it in its views. If it needs to do something a tad different with the data then let it.
Apple docs claim this as well. “You subclass UIViewController (or one of its subclasses) and add the custom code you need to implement your app’s behavior.”
I find this article to be extremely confusing. I am a beginning iOS developer and I am having a hard time following the logical flow of this program. It seems like a mountain of code for such a small task.
The thing that confuses me the most is the author suggests that UIViewControllers do not belong in the family of Controllers and should more properly be considered Views. If this is true, what about UITabBarControllers, UITableViewControllers, and the other ViewControllers? Are they Views also?
I have been taught that:
Models contains the data and logic.
Views are the visible UI such as the components in a storyboard or xib. Views are what you mess with when you are in IB.
Controllers are all the UIxxxControllers that control the view elements.
Is this incorrect?
This article appears to apply an additional level of indirection…I guess. As I say, I am confused.
If I am right that the author considers UIxxxControllers to be part of the view, I’d like to see another simpler article explaining the dangers of making UIxxxControllers part of the Controller in the MVC pattern.
I’d also like to see additional articles on the techniques to use to detect and avoid massive ViewControllers.
Well, I am against what Apple said on that regard, otherwise you end up with a huge UIViewController. Hence the use of a proper controller, that is easily testable and has no dependency with the UI.
UIViewController is part of the the UIxxxControllers family. But this family is tightly coupled with the View and that’s a problem when you want to reuse things. More over, if you want to move to Mac development (where you don’t have access to UIKit) and you have your logic inside members of this family, you will need to extract all that functionality into proper independent classes.
Models shouldn’t contain logic. They are used by a layer above the model.
Well, that level enables testability and makes maintenance a breeze.
The section MVC: Massive View Controller? sums it up.