I have to reiterate these are guidelines, not rules, and among guidelines, this one isn’t critical. A
Manager here and there warrants an audit when it’s time to refactor. But if you’ve got dozens of classes like
DataManager, you’ve probably got architectural problems.
Managers can be a symptom of poorly-defined responsibilities. When you think about it, the word “Manager” means nothing. In object oriented programming, every class is a manager. Cocoa Touch could have
UIViewManager, and even a humble
Like the real world, the worst
managers start with good intentions. Say your
AvatarUploadController is over 3,000 lines long, and most of it deals with, like validating image dimensions, resizing it, uploading it, checking for network errors, and so on. If you cut and paste code into another class and call it
AvatarManager, it’s progress.
Now take a step back and ask why “massive view controllers” are a problem. It’s the Single Responsibility Principle. Every class should be responsible for a single bit of functionality. Small view controllers are good, but I can live with a massive view controller so long it only handles view controller stuff, like setting up view hierarchies and responding to adaptivity changes. When your controller handles networking, you’re in for trouble.
Extracting tons of business logic into a
AvatarManager solves the immediate problem. If we’re talking fifty lines of code, maybe that’s enough. But if you’re dealing with thousands of lines of business logic, wrapping it in a
Manager is a half-measure. You cleaned up the mud in the living room by sweeping it into the kitchen.
On the other hand, managers can be a symptom of faux object oriented design. Consider
NSFileManager, which is really just a collection of file functions. In a true OO design, rather than call
removeItemAtURL(), you might instance an
NSFile() object with a URL, and then call its
That’s not to say all code needs to be object oriented, but
NSFileManager does a disservice by faking it. Its uses a singleton,
defaultManager, so there’s a risk of someone (probably a random third-party library) assigning to its
delegate property, and messing up file operations for the whole app. Is this really better than a loose collection of file functions?
How to Fix It
I can already see junior engineers clicking the “Refactor” button, ready to swap
Utility and so on. That’s the problem with rules: jank finds a way.
When you audit a
Manager class, ask, “What is this class responsible for?” If you have trouble answering that, ask, “Can I break it down?” In the avatar upload example, I’d pull out a NetworkAPI,
Managers aren’t a big red flag because it’s an easy noun to fall back, even when you know what you’re doing. If a senior engineer sits at a screen for too long thinking of a name, their “you’re being too clever” sense kicks in. You don’t want to be that amateur who waxes on about aesthetics while shipping nothing.
Even Apple frameworks use the noun, like Core Location’s
CLLocationManager. Hey… let’s audit that class?
What are its responsibilities? It tracks changes to the user’s location. Does it take on too many responsibilities? I don’t think so. I’d be worried if it included unrelated stuff like reverse-geocoding.
Ok, can we rename the class to clarify things, and fight responsibility creep? I’d go with
Except Apple would be nuts to rename
CLLocationManager this late in the game. Too much legacy code depends on it, and even if you built code-migrators to help, it’s hard to justify wasting time on this when you could be delivering features to users.
But if you’re building something to last, or building any sort of dependency, it’s worth spending an extra few minutes to name things right the first time.