Behind the Bleeding Edge - Why I'm Still Using Objective-C in 2016
I really like Swift. It has an expressive type system, a concise syntax, named parameters and a nice implementation of an option type. My experiences with it so far have been mostly very positive.
Up until now, however, I haven’t shipped a single line of Swift code into production.
Hello Objective-C, My Old Friend
I’ve been learning and writing Objective-C since 2006. Since that time, it has gone through several rounds of iteration and improvement, with Apple adding properties, Automatic Reference Counting and blocks. Probably my favourite aspect of Objective-C is its “reads as a sentence” paradigm, which comes from the combination of the Smalltalk-inspired method invocation syntax and Apple’s very explicit conventions. More than any other language I’ve worked with, good Objective-C code comes pretty damn close to the ideal of self-documenting code. I’ve been through thick and thin with Objective-C, and in that time I’ve encountered enough of the rough edges of both the language and the tooling to be able to debug even the nastiest of bugs.
Experience Matters
With many years of experience with a particular language or framework under their belt, a senior developer can:
- Estimate the length and risk of a project with a reasonable degree of accuracy
- Design a complex project whilst knowing that certain architectural patterns are likely to succeed
- Write sensible code under pressure (with looming deadlines)
If you take Objective-C out of the equation, an experienced, senior iOS developer can make estimates, but they’re likely to be much less accurate. They can architect a complex project, but it’s much more likely that there will be poor choices made along the way.
Experience leads to mastery, and there are currently no developers outside of Apple with even 2 years of experience writing native apps for iOS in Swift.
Compatibility and Obselescence
As part of the process of open-sourcing Swift, Apple has declared that the Swift 3.0 release, which has an expected release date of “Late 2016”, will include a Stable ABI. Until then, any Swift code that is written effectively has built-in obselescence.
Since pre-3.0 Swift explicitly breaks both source and binary compatibility on each update, developers making use of Swift need to ensure that every line of Swift code that is linked into an application binary is using the same Swift version (whether as sourcecode, or as part of a compiled binary framework or library that the app links against). This can become a particularly onerous requirement if your project makes use of lots of dependencies (either 3rd party or internal). By using Swift, your app’s development schedule will become closely coupled to not only Apple’s Xcode release schedule (which isn’t always known publicly ahead of time), but also to the development schedule of every library or framework that your app makes use of.
Once Swift has a stable ABI, it will be possible to use different versions of Swift across different modules by compiling them into their own libraries or frameworks, so in 2 years time, even if a 3rd party library didn’t update from Swift 3.0 to Swift 4.0, you could still compile it using an older toolchain, then link against the binary.
This compatibility issue is a considerable problem for app developers, but it’s also a major problem for companies or developers shipping frameworks or libraries in either source or compiled binary form.
Until Swift 3.0 ships and the ABI is stabilised, the only way to write library code that is either source or binary compatible in 12 months time is to use Objective-C.
The Bleeding Edge is Sharp
While Objective-C idioms are well established in the community, Swift best-practices are well and truly in flux. Apple is, for the first time in their history, holding discussions on the evolution of their APIs and languages in the open. This is a fantastic change in approach, but the extra insight into Swift’s evolution reveals just how significant the changes from 2.x to 3.0 will be. Given that even Apple are uncertain about what “idiomatic Swift” is going to look like in 12 months time when Swift 3.0 is released, 3rd party developers can assume that anything written in Swift 2.x will be not only source incompatible, but potentially style and idiom incompatible
as well.
There are a large number of open questions when it comes to architecting a complex app using Swift: unexpected performance issues, the use of reference vs value types, when to use enums, failable initialisers, and how best to deal with asynchronous error handling. As both Apple and the wider development community gain experience with the language, hopefully we will see a new set of best practices emerge that truly makes use of what Swift has to offer.
Tooling
From long-compile times, to crashing bugs, to regular losses of syntax highlighting, the current state of tooling around Swift should really be considered to be in beta. Hopefully, Xcode 8 and Swift 3.0 will remedy many of these shortcomings. By comparison, Apple’s tooling around Objective-C is (relatively speaking) mature and stable, meaning that you can spend more time writing and debugging your code than fighting the tools themselves.
Choice and Responsibility
As developers, we now have a choice of programming languages for iOS and OS X app development, which is a great thing.
As professionals, we have a responsibility to communicate, openly and honestly, the repercussions of our technology choices to our managers, employers and clients. Major source and binary incompatibility issues, lower productivity due to immature tooling and a rapidly changing language and API are all good reasons to avoid Swift 2.x in many commercial contexts.
For the projects that I’ve worked on since Swift was first announced, the business arguments for adopting Swift have been weak. Once Swift 3.0 arrives however, and we have a stable ABI, a stable standard library, and more mature tooling, a large number of the arguments against adopting Swift will no longer be valid. I hope to start writing the vast majority of iOS code in Swift at that point.
Until then, I’ll continue making use of Objective-C, which, while by no means perfect, has helped me ship many, many projects over the last 10 years.