How evil is a UIViewController? - ios

This is a somewhat open ended question about the UIViewController class, and their proper role in an iOS app.
I recently read this article, and I partially agree with the author. It's obviously important that every bit of logic related to your views and models doesn't end up getting dumped into the UIViewController, but it seems a bit extreme to build all of your views separately and use delegate methods to access the actions.
I'm curious about which design is most efficient in regards to the memory and performance of the app (clearly an important consideration when dealing with mobile apps)? As the author of the post pointed out, Apple doesn't seem to strongly advocate against putting logic in the UIViewController.
Ultimately, I'd like to know the right way of doing things. So the question is, should the views and any logic associated with it be completely separated out of the VC? Should I really be using delegates to communicate with the UIViewController?

A view controller is not evil by nature, although it's common for them to grow into monolithic messes because they are so convenient to extend.
…it seems a bit extreme to build all of your views separately and use delegate methods to access the actions.
Think of it as breaking up your program into smaller units, whatever that may be. Subclassing UIViews in every case isn't the best solution (as one example).
Each developer's tolerance is a bit different and it varies by program/case, but it's pretty easy to recognize and eliminate duplicate code, and to break your programs down into smaller units.
I think most classes:
should not exceed a few ivars (e.g. 2)
should not require more than 100 lines
should favor composition over inheritance. in many cases where you think you need inheritance, protocols may be used.
Of course, there will be exceptions.
I'm curious about which design is most efficient in regards to the memory and performance of the app (clearly an important consideration when dealing with mobile apps)?
It matters more that you will gain a lot by writing more reusable programs. Invest more time and effort into these reusable designs, reduce duplicate code, and focus on quality. Write performance and memory into your designs where it is a concern. Generally, this will result in a big win when compared to the dreaded freshly written, poorly tested, monolithic VCs.
Ultimately, I'd like to know the right way of doing things. So the question is, should the views and any logic associated with it be completely separated out of the VC? Should I really be using delegates to communicate with the UIViewController?
Oversimplification: No, you don't have to go that far if you eliminate redundant code, focus on reusability where applicable, and ensure your units/classes maintain low complexity. Absolutely, fix those problems before they grow into monolithic classes, regardless of whether they are VCs or another type.

I've also read this article a year ago, when I was looking for better iOS coding practices than what you see everywhere (dumping all kinds of crap in view controllers...). I agree with its points, although unfortunately it doesn't provide any kind of solution to the problem.
After a year of working on a fairly large iOS application, with complicated data model, remote services and highly nonlinear navigation, my experiences come down to these points:
Use view controllers for a single unit of user interaction, like prompting for login credentials etc. Basic validation (e.g. checking for empty fields, number formats etc.) takes place in the view controller, but if validation is part of your business logic, it should be put in your model.
I usually have a so-called controller object which orchestrates the UI flow, and connects it with the domain model. The controller receives user input from the view controllers via delegate mechanisms, so they're loosely coupled.
A single monolithic controller should be avoided; so I usually try to split my controller functionality between simpler, modular parts. For example, I have a controller which manages a registration process with a mostly linear UI flow, and its embedded in the main controller of the application so its

Related

in VIPER architecture should each presenter interact with only one Interactor?

I read about VIPER architecture here http://www.objc.io/issue-13/viper.html (and in a few other sources), but I still can't figure out one thing, should each presenter interacts with at most one Interactor?
Here is a longer discussion about it that might better explain my question: Use Case with 2 ways for the same action
As I get it, the presenter is unique per VC. However, when a presenter needs several interactors, he may use them.
The interactors as for my opinion is a layer of business logic, they can interact with each other and the presenters can interact with many of them.
However, it's important to put the right logic in the right layer. For instance, be careful not to put the business logic in the presenter layer since its very tempting to while having to navigate between several interactors. Keep in mind to put the business logic only in the interactors.
Ideally, NO. One Presenter should know about the existance of only ONE Interactor. But the interactor itself can have many Data Managers. I usually use at least two data maangers: one for API requests and one for Local Data management.
For more advanced tips and helpful good practices on VIPER architecture, I recommend this post: https://www.ckl.io/blog/best-practices-viper-architecture (sample project included)
Ideally no, as Marcelo points out. However I feel like adding the "D" to VIPER for data managers is also not ideal.
A big problem in VIPER is that the presenter already knows which use case to "fire off" upon receiving input from the view, therefore it already has some apriori knowledge of the business use cases. This fact alone calls into question the entire architecture in my view, since if the presenter merely notified the interactor of a use-case-agnostic or purely UI event on the view, it would serve no purpose for existing. The presenter in VIPER has to have a tiny bit of "business logic", no matter what.
So, since the presenter already must orchestrate use cases by talking to the interactor, have one interactor per business use case, and the presenter can connect them if there is more than one business use case per "module". The boundaries in VIPER are often times difficult to maintain in practice without workarounds, but it is a nice architecture for forcing devs to think about separation of concerns.
According to the CheeseCake Best Pratices, the only what to connect multiple VIPER modules should be by using the Router Layer. This way, if you remove any module the only layer that will present errors in other related modules would be the Router. Also, to avoid coupling, Entities may be put in a separate module exclusive for this purpose. Finally, to mitigate the code duplication, similar entities (e.g., user and profile) would be grouped into the same data managers.
My opinion is: try to find out the trade-off between code replication and module decoupling. I'm refactoring just now my code and the code replication saved a lot of time when removing particular modules that were without any dependencies.
A little bit late to the party, but I just Googled this question searching for something else.
It really depends on your implementation of VIPER. There is no single correct one, from what I've seen people implement it in really different ways and it should be adjusted to fit your specific needs.
Some projects have tightly coupled interactor per view, where the view displays data, presenter passes the data between the view and interactor (converting it in the process) and the interactor handles the business logic per view. In this case the presenter would talk to only a single interactor.
Other projects implement interactors per use case, or in other words, "minor" feature. That way you can avoid duplicating business logic between the modules. The presenter can talk to multiple interactors here.
There are also projects that implement large interactor per "big" feature or should we say per area of the app. That way the interactors tend to be pretty large, but also really become the "smart" layer responsible for the business logic decision for the app and they tend to have access to everything they need to make those decisions.
Let's give an example here - let's say you have a log out button in the side menu of your app and also in the settings and that for the log out you need to clear your database, keychain, user defaults and the networking session. A rather common scenario.
In the first case, where you have and interactor per view, you'd obviously have duplicated business logic. I believe that's how the "original" VIPER works, but it's probably not the best approach.
In the second case you'd probably have a "user session interactor" handling just logging in and out the user.
In the third case, you'd have a "user interactor" that would not only handle the session, but also save and manage all the user's data.
My usual approach is the third option, with the big downside of the need to split the interactors over multiple files. Many people use the second option. It may also happen that for your project the first option is the best - for example if there is little overlap between screens in your project and they are tightly aligned with features.

Debating the use of dependency injection in iOS app

I'm working on an iOS app where we need different binaries for each customer based on their needs. A customer may want to change all the colors, icons and texts. We can do that through white labeling process. The problem here, though, is when they ask for different behavior, for instance, removing login screen and making it optional to login.
I thought we can use dependency injections and use different handlers for each customer if needed. For instance, we can have LoginHandler1 and LoginHandler2, both implementing ILoginHandler and inherit from UIViewController.
However, use of dependency injection is costly, it slows down the app because resolving is expensive comparing to normal instantiation.
The other way is to define all these behaviors in the app and enable/disable them in a plist file. like "is login optional? yes/no"
Any suggestions?
Thanks
You should create the entire object graph up-front, in the composition root. Object creation, and constructor injection, should not take much time at all as long as your constructors are not doing any actual work.
That being said, there are times when creating the entire object graph at the start of the application may take longer than is acceptable. In those cases, you can use lazy-loading to defer the costly initialization until later - while still creating the objects in the composition root.
Mark Seemann describes this approach in more detail here: Compose object graphs with confidence.
I thought we can use dependency injections and use different handlers for each customer if needed.
You thought right. Flexibility is one of the main reasons people use DI.
However, use of dependency injection is costly, it slows down the app because resolving is expensive comparing to normal instantiation.
It really doesn't cost that much at all. Have you tried it yourself? Unless the object in question (i.e. the object being injected) is very expensive to instantiate, you have no real reason to stay away from DI and Inversion Of Control. Also, as #Lilshieste noted above, creating the object graph up front (see AppDelegate) will probably make this even less a problem.
A good way of doing that is described here:
http://cocoapatterns.com/passing-data-between-view-controllers/ and here http://cocoapatterns.com/ios-view-controller-transitions-mediator-pattern/
The other way is to define all these behaviors in the app and enable/disable them in a plist file. like "is login optional? yes/no"
While less "elegant", this solution is a pretty useful one, especially if the project is not really big in terms of number of classes and VCs. It is also the easiest one to implement if the app code is already laid out and introducing major design changes would ask for lots of refactoring.
Always take action based on the task at hand, there is rarely if ever a single solution to a software design problem.

MV4 Application with EF5 model first, without ViewModels or Repositories

I'm building a MVC4 app, I've used EF5 model first, and kept it pretty simple. This isn't going to a huge application, there will only ever be 4 or 5 people on it at once and all users will be authenticated before being able to access any part of the application, it's very simply a place order - dispatcher sees order - dispatcher compeletes order sort of application.
Basically my question is do I need to be worrying about repositories and ViewModels if the size and scope of my application is so small. Any view that is strongly typed to a domain entity is using all of the properties within that entity. I'm using TryOrUpdateModel in my controllers and have read some things saying this can cause a lot of problems, but not a lot of information on exactly what those problems can be. I don't want to use an incredibly complicated pattern for a very simple app.
Hopefully I've given enough detail, if anyone wants to see my code just ask, I'm really at a roadblock here though, and could really use some advice from the community. Thanks so much!
ViewModels: Yes
I only see bad points when passing an EF Entities directly to a view:
You need to do manual whitelisting or blacklisting to prevent over-posting and mass assignment
It becomes very easy to accidentally lazy load extra data from your view, resulting in select N+1 problems
In my personal opinion, a model should closely resembly the information displayed on the view and in most cases (except for basic CRUD stuff), a view contains information from more than one Entity
Repositories: No
The Entity Framework DbContext already is an implementation of the Repository and Unit of Work patterns. If you want everything to be testable, just test against a separate database. If you want to make things loosely coupled, there are ways to do that with EF without using repositories too. To be honest, I really don't understand the popularity of custom repositories.
In my experience, the requirements on a software solution tend to evolve over time well beyond the initial requirement set.
By following architectural best practices now, you will be much better able to accommodate changes to the solution over its entire lifetime.
The Respository pattern and ViewModels are both powerful, and not very difficult or time consuming to implement. I would suggest using them even for small projects.
Yes, you still want to use a repository and view models. Both of these tools allow you to place code in one place instead of all over the place and will save you time. More than likely, it will save you copy paste errors too.
Moreover, having these tools in place will allow you to make expansions to the system easier in the future, instead of having to pour through all of the code which will have poor readability.
Separating your concerns will lead to less code overall, a more efficient system, and smaller controllers / code sections. View models and a repository are not heavily intrusive to implement. It is not like you are going to implement a controller factory or dependency injection.

Model-Controller Abstraction with Core Data

In learning about Core Data, I've noticed how (in Xcode's templates) Apple directly used the query classes inside the view controller. This seems like it is bad MVC (having database access logic directly inside the view controller). Would it make sense to abstract out these kinds of actions to a separate suite of classes that obtain the data from the database and pass it back to the view controller calling it?
EDIT–
So, just to be clear, when I say "kinds of actions", I specifically mean CRUD Operations. Though if you have ideas about other things that a so-called "Model-Controller" would do, I'd be interested in hearing about them.
It's a matter of opinion, and often yes the templates are the most simple form of working example. It's hard to have a template spin out multiple files, for example.
Yes, personally, I generally spin out a separate NSManagedObject subclass. I like to have a _MySubclass object that has all the auto-generated stuff, then have the model actually reference MySubclass which has model-based business logic (you can use mogenerator or other methods to do this too if so inclined). Perhaps thinking of it as "Model-Controllers" and "View-Controllers" is another way of putting it.
This is a very good question and the answer likely depends on your situation. Perhaps architecture purists would insist on separate Model controllers and there are a lot of benefits to this approach. However, sometimes I find myself using Key Values when I'm doing a simple view. When things are more complex, for example, when coding the same Model for the Mac and iOS, having separate Model Controllers will allow you to reuse a lot of code. When you must diverge, Obj C Categories are a very clean way to extend functionality without adding a lot of overhead. I personally favor categories over extensive subclassing.
Since NSFetchedResultsController was released, my model classes are leaner. There are a lot of nuances to this and experience will help you come up with the best solution for your App. I've also found that writing unit tests up front will help you force through issues and validate your design, or send you back to the drawing board :)

Why does Apple documentation that getting ManagedObjectContext from UIApplicationDelegate is bad?

Just curious why ManagedObjectContexts should be passed to UIViewControllers when they are created, rather than just grabbing them from a UIApplicationDelegate?
The docs say that this makes your applications more rigid, but I am failing to see the nuances of when to use which pattern.
Thanks!
Imagine that I ask you to do some task, like painting a room. If I just tell you "go paint a room," you'll need to ask me a lot of questions, like:
Which room?
Where's the paint?
Where are the brushes?
Should I use a dropcloth?
In short, you won't be able to complete the task without help from me. If you have to depend on me every time, you won't be a very flexible painter. One way to deal with that problem is for me to give you all the stuff you need at the outset. Instead of "go paint a room," I'll say "please paint room number 348 using this bucket of paint and this brush, and don't bother with a dropcloth." Now, you've got everything you need, and you can get right to work with no further help from me. You're a much more flexible worker because you no longer depend on me.
The same thing applies to view controllers (and objects generally); it's better to give them everything they need than to have them depend on a particular object like the app delegate. It's true not just for managed object contexts, but for any information they need to do their job.
This is mainly because you want to use dependency injection with your UIViewControllers instead of just grabbing everything from UIApplication, this keeps your delegate clean instead of full of reference hacks.
This is also to keep with the MVC pattern:
Model
View Controller (Only for view logic)
Controller (For coordinating between the view and the model)
I tend not to agree with this pattern.
First of all I try to treat Core Data as an implementation detail, and as any implementation detail it should be hidden behind a good facade. The facade is the interfaces I expose for my model objects. For example if I have two model objects; Cource and Student, any cource can have a number of students. I do not want to let the controller take upon the duty to setup predicates and sort descriptors, and jump through all Core Data hoops just to get a list of students for a particular class. There is a perfectly valid way to expose this in the model:
#interface Cource (StudentAccess)
-(NSArray*)studentsStortedByName;
#end
Then implement the ugly stuff once and for all in the Model class. Hiding all the complex details of Core Data, and no need to pass around managed object contexts. But how would I find the sources, it has to start somewhere right? Yes, it does but you need not expose it to the controller. Adding methods such as these are perfectly reasonable as well:
#interface Cource (CourceAccess)
+(Cource*)caurceByID:(NSString*)courceID;
+(NSArray*)allCources;
+(NSArray*)courcesHeldByTeacher:(Teacher*)teacher;
#end
This also helps in minimizing dependencies between controllers. And reducing he dependencies between the model and controller. Assuming I have a CourceViewController and a StudenViewController is I did not hide the Core Data details behind a facade and wanted to pass around the managed object context as well, then I would end up with a designated initializer like this:
-(id)initWithManagedObjectContext:(NSManagedObjectContext*)moc
student:(Student*)student;
Whereas with good a good facade I end up with this:
-(id)initWithStudent:(Student*)student;
Minimizing dependencies behind facades, in favor of dependency injection also makes it much easier to change the internal implementations. Passing around the managed object context encourages each controller to implement their own logic for basic stuff. Take for example studentsSortedByName method. At first it might be sorter by last/first name, if later changed to last/first name sort you would have to go to each and every controller that has sorted students and make the change. Where a good facade method requires you to change in one method, and all controller automagically get the update for free.
The Apple Docs try to foster the most widely applicable and sustainable design patterns.
Dependency injection is preferred because it allows for the most flexible, expandable, reusable and maintainable design.
As apps grow in complexity, using a quasi-singleton like parking the context in the app delegate breaks down. In more complex apps, you may have multiple context tied to multiple stores. You might want the same view-controller/view pair to display data from different context at different times or you may end up with multiple context on different threads/operations. You can't pile all those context up in the app delegate.
If you have a simple app with a single context then using the quasi-singleton with the app delegate can work well. I've used it on several smaller apps in the past without immediate issue but I did hit scalability problems on a couple of apps when the apps grew overtime.
Which pattern to use depends on your shipping constraints and you best guesses about of the evolution app over its entire lifecycle. If its a small one shot app, then the app delegate quasi-singleton will work fine. If the app is more complex, might grow more complex or might spawn other related apps that will reuse existing components, then dependency injection is the way to go.

Resources