Beyond Objective-C, Beyond Swift

I had been writing software for less than a year when Apple introduced Automated Reference Counting (ARC) in iOS 4. Even in that short span of months I had struggled often enough with manual memory management (retain/release) that I immediately grasped the significance of ARC. I’ll never forget the figure that accompanied the transition guide documentation:

It perfectly illustrated the benefits of ARC. ARC didn’t make code shorter through syntax niceties or compacted expressions. It obliterated whole swaths of code throughout a project. An entire layer of error-prone state management was reduced to an almost invisible implementation detail.

ARC seemed too good to be true. Granted, to this day there are still some areas where memory management requires finessing, but for the most part it is quite close to magic — especially for anyone who remembers what it was like to write iOS software before ARC.

Progress is Offensive

During the first few years after the ARC introduction, mastery of old-fashioned manual reference counting was a point of pride among seasoned developers. Using ARC was somehow not “real” Objective-C programming. The kids these days and their ARC. That attitude is one that I don’t encounter much anymore. By the time Apple transitioned OS X to ARC, the stigma had all but disappeared.

Advances in software development are offensive to the practitioners of the technologies made obsolete. The new technology seems childishly simple in comparison to the complexity of what it replaces. At the risk of overgeneralizing, I think this reaction is natural. When you’re passionate about your work, you tend to fall in love with its idiosyncrasies, even those that might actually be burdensome.

Software development advances via abstraction. Best practices from lower levels of infrastructure are codified, automated, and optimized for common scenarios. It’s this abstraction and simplification that is the source of offense for the champions of older ways of working. When it’s done right, a new technology automatically handles tasks which previously required significant planning and effort. No one wants to see their expertise made obsolete — until they realize that the new layer of abstraction they thought was childishly simple is actually the building blocks for new complex things they’d never have been able to build with the old tools.

That’s what I want from an Objective-C replacement, but it isn’t what we get from Swift.

A Feeling of Disappointment

Some people are huge fans of Swift already. Others are ambivalent, doubtful, or outright opposed. I would place myself among those in the ambivalent group. I haven’t been able to articulate my thoughts and feelings yet. I think I can now.

There’s a lot to like about Swift. I especially love enums, string handling, the Playground REPL. Swift has clearly been designed with thoughtfulness and care. But nevertheless I can’t shake a feeling of disappointment. The best way I can sum it up is:

Swift solves problems that I don’t really have, and the problems I care about most Swift doesn’t solve.

Let’s use Apple’s Swift landing page as the canonical reference for the reason Swift was made. Here are the Swift features that Apple lists first (not including features that Objective-C had already, more or less, like automatic memory management):

These are all demonstrable improvements over Objective-C. Let’s set aside the tired debates about the merits of generics, inferred types, functional programming patterns, etc. and agree that yes, Swift is better at many things than Objective-C.

So why am I disappointed? My disappointment with Swift is because all the items in the list above are only iterative improvements. None of them address the biggest challenges I face as a developer. To explain why, let me first describe the way I work. Then I’ll return back to Swift.

How I Work: Coding in the Air

I build all my software in a manner I call coding in the air. It began as a fruitful working relationship with Jamin Guy, my colleague at Streamweaver and Riposte. We would sit in Jamin’s living room and discuss architecture at length. Sometimes sessions would last for five or six hours. Neither of us would be touching a keyboard. We’d build up and tear down APIs in our minds, rattling off class names, property lists and method signatures over and over, each time a little different. Our mouths were sore from repeating the same words. Gradually the right patterns revealed themselves.

At the end of these sessions, the implementations were so clear in our minds that the actual work of writing software was not much more than typing.

It takes enormous amounts of concentration to build software in this way, but it’s worth it — especially if you have the benefit of a like-minded partner. Other than an uninterrupted block of time, there’s virtually no cost to coding in the air. As soon as an idea doesn’t work, it vanishes. There’s no code to rewrite or files to delete.

Coding in the air shifts your focus away from implementation details and onto architecture. It’s architecture that is the hardest and most important part of any project. It’s the part that takes the most time to implement — and the most time to reimplement should you paint yourself into a corner with a bad assumption early on. Coding in the air reduces the risk that you’ll need to reimplement something.

Implementation is the Bottleneck

When at last the time comes to fire up Xcode, the implementations are fairly clear in my mind. But this is where my problems really begin. Every project I’ve worked on involves rewriting the same kinds of implementations, but this code isn’t re-usable. Things like:

These are just some of the time-consuming tasks we all face when writing Objective-C applications. They take a long time to do well, and involve a great deal of repetitious, brute-force work. These tasks deplete limited resources. Developer time is the biggest expense subtracted against a startup’s bottom line. It’s also mentally and physically taxing. It’s hard to stay focused on the core problem that matters most: building something that users love.

Back to Swift

Swift doesn’t reduce the time and energy it costs to implement the boilerplate goo that comprises our applications. Even factoring out the learning curve (which is steep), Swift merely shifts the locus of debugging from runtime into compile time. It solves some common implementation mistakes with Objective-C, but it doesn’t make whole applications faster to implement. Saying Swift makes programming easier is like saying that iOS 8 extensions make it easier to use an iPad the way that Federico Viticci does — more straightforward, perhaps, but as a workflow it’s just as complex.

The net result will be this: Objective-C developers will spend the next several years transitioning to the new syntax and assumptions in Swift. When that transition is finished we will likely still be where we left off in 2014. We’ll still be spending long hours writing boring, buggy, non-reusable implementations of persistence, networking, trigger/response, and layout code.

What I Want

On a continuum from the abacus to punch cards to Objective-C, Swift is only an iterative improvement upon Objective-C. Perhaps someday Swift will serve as the underlying language behind the kinds of solutions I’d like to see. Regardless of how it happens, here’s some of the things that I want:

I want whatever comes after Objective-C to obviate whole layers of architecture the same way that ARC made memory management a concern of the past. I understand that what I’m asking for is more than just a programming language. But that’s because the biggest obstacles holding back Objective-C development can’t be solved by a language alone. We need a new paradigm.

|  25 Sep 2014