Frictionless Project Organization for iOS

Posted April 5, 2013 by Cameron Desautels

There comes a time in every MVC(-ish) app's life when it starts to get a bit heavy. Sure, a few out-of-place lines of code here or there don't hurt too much when the codebase is young and agile, but in a middle-aged app they start to be a concern. Slovenly habits beget more slovenly habits; refactorings don't come as easily as they used to. And before you know it, your methods won't even fit on a standard-size Cinema Display anymore. Something's gotta give.

Rails developers talk a lot about this problem1. Should we have fat models and skinny controllers? Or skinny models and fat controllers? (No one really talks about views because we're all in agreement that we shouldn't be hiding our complexity there). But personally, I'm convinced that a lot of this problem comes down to nomenclature; specifically the nebulousness of the word "model."

The problem with the term "model" is that it's overloaded to mean two different things—things we'd often like to distinguish between, viz. (1) our business objects (the actual entities in the domain of the problem we're trying to solve, be they Orders, Widgets, or BlogPosts) and (2) anything in the logic layer of our application. Is (say) a CurrencyFormatter a model? Depends on who you ask.

The secret to escaping MVC bloat is to take code out of both your controllers and your (business object) models and put it into other lightweight, coordinating objects. Make decorators, presenters, services, translators, interpreters, wrappers, and sometimes even—(gods have mercy)—factories. These objects are comprehensible, testable, and maybe even reusable. And they reduce the surface area of each object's API so you can wrap your head around it. As a very smart man2 once said, the only way to deal with complexity is to eliminate it.

But when we decide to extract these objects, where do we put them in our codebase? Where should a GrueFrobnicator live? In the Rails world the gods have seen fit to give us the app/models, app/views, and app/controllers directories which, while handy, suffer from one major problem: when all you have is models, views and controllers, everything looks like one of them.

Do these misfits belong in app/models? lib? Elsewhere? I remember being a beginner and wondering if I could even add classes to app/models which didn't inherit from ActiveRecord::Base. Could I make an app/frobnicators directory? (Hint: both of these work). Should I? That's a tougher question.

What all of this amounts to is friction. And every time we hesitate about the right place to put our code, we raise our chances of leaving it in a very wrong place.

In the iOS development world we have none of this. The default project organization scheme is Supporting Files and everything else (which, honestly, sounds a lot like blah and blah to me). Thanks, Xcode. But maybe that's not all bad. I mean, no scheme is better than a broken one.

So one day I spent way too long on the C2 wiki, thinking about names and trying different variations, and I what I eventually came up with was the deceptively-simple formula I'm now using for all of my new projects:

  $ mkdir -p ProjectName/{Assets/Images,Frameworks,Logic/Models,Presentation/View{,Controller}s}
  $ find ProjectName -type d

It's fairly self-explanatory. The pieces worth calling out are:

  1. Frameworks — External libraries bundled into the project (not core iOS .framework files, however, which still live in the top-level Frameworks group in Xcode).
  2. Logic/Models — "Business object" style models. We're never going to get everyone to agree on what the term should mean, but nesting it under Logic makes it clear in this case.

Here's why I think this helps:

I've been using this structure for several weeks now and I'm still quite happy with it. What do you think? I'd love to hear from others who have tried this scheme or have other project organization schemes they love.


  1. Regretably I don't hear iOS developers talk that much about software design even though we face many of the same problems.
  2. I could have sworn this was Rich Hickey but I can't find the quote. In any case, he nearly says as much in his Simple Made Easy talk when he discusses (human) limits. Consider that your appeal to authority.
  3. Or even views, if you're walking that dark path.

Cameron Desautels is a polyglot developer originally from Colorado Springs, CO. He holds a masters degree in Computer Science from The University of Texas at Dallas, in OrgSync's own backyard. He joined OrgSync in April of 2012 after a three year foray into mobile app development. Cameron firmly believes that being a good developer implies being a good designer—that developers must have an in-depth understanding of the way non-technical users think and interact with products and should design to align with user intuitions. In his free time he enjoys drinking tea, coding in Lisp, and studying Japanese.

comments powered by Disqus