Cocoa Touch Architecture

iOS Architecture Patterns by Bohdan Orlov

Really interesting read highlighting the pitfalls of a lot of common approaches to iOS App Architecture.

In my experience I’ve found that testing is the hardest thing to keep up with in a typical Cocoa architecture. I do sometimes tend to fall back to a Massive View Controller, but try to keep everything organized with #pragma mark (or // MARK:) and well documented marking groups so it’s easier to keep track of a growing ViewController, so navigating my code isn’t usually the biggest problem I have. But it is difficult to write specific tests when you have a lot of logic grouped into UIViewController classes or even AppDelegate, which is another class I use for more than I know I should. Keeping things modularized in small chunks allows for much more robust test coverage and usefulness (one thing I’ve learned in previous jobs is that coverage != usefulCoverage).

UITests can do a lot to bridge this gap, allowing you to test core controller logic without hacking your existing code base to bite-sized pieces, but with the obvious caveat that the test becomes more of a function test of how the view and controller units work as a pair rather than individual tests of each piece. Again, coverage != usefulCoverage.

These days I think it’s very important to remember that a good application doesn’t just mean a rectangle that takes up the full screen and displays information and transitions well. There’s a lot more to the Apple platforms than just UIKit, so platform agnostic modules are something I’m trying to keep in mind. This is something Orlov highlights really well, that a well abstracted controller should treat a UIViewController like a generic View class, and allow you to plug in a UIViewController, or a WKInterfaceController, or whatever container is appropriate for the context.

The final thing I want to address is ReactiveCocoa and RXSwift. I really like a lot of the simplicity that you can get from reactive programming architectures, but the screenshot of a callstack when working with RactiveCocoa is a key example of why I don’t think this is ready to use yet. Debugging is a pain, and tools matter in an IDE. Until Xcode and Cocoa adds native support for these patterns I think this is something I’m going to be avoiding like the plague in my own personal projects. There’s also my general feelings about third party layers of abstraction, which is a matter for a whole other post.