There are little details in app architecture that may not be obvious, but make a big difference over time. We’ll start with modal view controllers, then step back for the larger lesson.
Say you have a view controller that displays the user’s profile. There’s an “Edit” button that shows a modal editor.
When you’re done editing, You tap a “Save” button inside the editor:
According to the docs:
The presenting view controller is responsible for dismissing the view controller it presented. If you call this method on the presented view controller itself, UIKit asks the presenting view controller to handle the dismissal.
While self-dismissal is supported– maybe for convenience– UIKit tells us it’s really the responsibility of the presenter. You may have noticed this the first time you used
UIImagePickerController. “Why doesn’t the camera close after I take a photo?” A half-hour later, “Oh. I have to dismiss it in the delegate.”
Let’s adopt the same pattern for our editor, if only because keeping present/dismiss in the same place makes things clearer.
Our editor now makes fewer assumptions about how it’s shown. Will it always be presented modally? What if we decide that on iPad, we should display it side-by-side with the profile, for a realtime preview?
I think it’s OK for parent objects to be tightly coupled with children, but a child should be loosely coupled with its parent. Doesn’t this code give you a little shiver?
We’ve shown controllers and views, so let’s look at models. Say we have an
Account class, which owns a REST API class.1
We assume requests will always come from an account, but almost every app has a logged-out experience. Do we create a fake “Logged Out” user?
This should feel wrong. You’re probably sharing view controllers between the logged-in and logged-out experience, so it’s only a matter of time before you accidentaly expose a “Fake User” label in the UI.
When we write unit tests for authentication, we have to build a fake account just for firing requests. Maybe mocks will get involved. Don’t get me started on mocks.
Instead, consider this:
That feels better.
Whether it’s view hierarchies or vanilla object composition, Always reach down. Never reach up. You can send messages up, but don’t making assumptions about who you’re sending it to, and never modify your parent’s state.