Modular Objective-C

18 Apr 2014

Modular Objective-C has been a good conversation starter lately, yet it's
still a little bit of an unexplored topic. Modular can mean lots of things
when seen from different points of view, but this post will focus primarily on
organizing code.

While working on Yammer, I've seen some interesting
challenges to solve; In the past year we've completely reorganized the iOS code,
shipped brand new iPad and iPhone apps, and got our codebase in a way better shape.
This also allowed us to move faster and do weekly iOS releases.

CocoaPods

A tool that has been around for a while, originally written by
Eloy Durán and Fabio Pelosin, has brought some new ideas of tackling
code organization; it also encouraged people to properly do
Semantic Versioning, tag code, and think how to write
better reusable software.

If you take a look on the bullet points above as they're separated, it might
ring a bell: avoid coupling these!. In the real world, don't couple
persistence with UIKit or AppKit. Don't couple business logic with persistence;
don't couple networking with persistence.

Given the above example, let's try to build a sane project structure that can
be reused and shared among developers on the team. We'll focus on iterating as
fast as possible, and because of that we won't use the intermediate podspec
server.

Project structure

I've made a small example structure for Silicon. It's an incredible
app for finding investors, evaluating companies on the fly, getting
funded, and so on. Except it doesn't exist in the real life.

While building this disruptive piece of technology that's about to change
the way people work, think and create, it was a good idea to separate
shareable files into SiliconKit. We can use it build an iPad app or even
better, find a business model and rent the framework as SAAS.

One important thing is that Source and Specs folders consist only of plain-old
Objective-C files. There's no .xcodeproj or any build related stuff.
This way we make it trivial to maintain and move around without breaking the
whole build system.

I've mentioned not using an intermediate podspec server; but somehow need
to keep track of the SiliconKit state. You need to be able to go back
in time, and for any commit tell - this is the state where it worked.
You may want to use git submodule only for having SHA committed, but I'll let
your creativity solve this one.

Podspecs

Podspecs are here to tell Xcode how to organize and link files with certain
targets. You can create and rename files using any editor or even Finder.app;
pod install will take care of linking them properly.

We'll make two podspecs, one for production files and one for testing. We need
a separate testing one so we can decouple test frameworks and settings from the
build system.

Of course - you won't run these every time while developing, but makes sense
on an CI server when you want to test against many SDKs / devices. The most
common point of failure is - while developing a concrete app together with
SiliconKit, one might change an API in shared code itself. While all the
tests are passing in context of that particular app, some other dependants might
start failing.
For a more visual explanation of the problem, take a look at the illustration
below:

Wrapping up

Your shared code should consist only of source files and domain resources.
Having extra Xcode projects will bite you in the long run; let CocoaPods do
project organization and target linking for you.

Codewise - decoupling your domain logic from frameworks like UIKit, AppKit,
CoreData, will let you reuse it in any of your projects. I'll try to write on
this subject later.

BTW, sorry for a little bit of trolling and never forget: #startuplife

Like this article? You may want to Tweet about it.
You can also shoot me an email, or visit me on Twitter / Github.