The Cost of Swift
Before I get started, I need to preface this essay with a few important points:
I really like Swift. I’ve built quite a few apps with it, both at work an on my own. Astra is almost entirely written in Swift, with only a few classes that touch Core Audio written in Objective-C.
My opinions are my own - they don’t reflect those of my employer or my coworkers.
Swift, a language that is less than three years old (publicly), has gained an amazing amount of momentum within the iOS/Mac community, as well as the broader programming populace. It boasts some ambitious goals of speed, safety, and expressiveness. Naturally, Apple’s emphasis on the language has also bolstered its adoption.
After building my own product in Swift and watching other product owners struggle with a common issue, it’s time to address a problem with the language: the cost of using Swift. To demonstrate, I’m going to share a story.
Astra was initially written in Swift 2.3. In the interest of releasing version 1.0 of the app, I delayed the Swift 3 migration last fall and shipped with Swift 2.3. As the product owner, I had to make a conscious decision about when I was going to bite off the Swift 3 migration, and getting the app in the market outweighed the debt of an older Swift version.
Once version 1.0 shipped, I began working on the next minor version of the app - a few new features, some enhancements - typical dot-fix things. As anticipated, a patch release needed to be shipped, so I fixed a couple critical bugs in 1.0.1, and then enjoyed the holidays with my family.
Side Projects Cost Time
Astra is a side project; I have a full time job, as well as a family and other “real world” responsibilities. When I get time to work on side projects, it’s usually for 30-60 minutes at a time, and almost always after 10:30pm.
All projects have some sort of constraint. It’s usually budget. Since I work on Astra for “free,” my constraint isn’t budget, but time. Each minute I spend working on it takes me away from my family, sleep, other hobbies, or a whole list of other things I really need to do.
The Swift 3 migration took me four nights, somewhere between 6-8 hours in total. This effort spanned a couple weeks, since I don’t necessarily have consecutive days to work on Astra. This was relatively quick, compared to other stories I’ve heard and witnessed.
Once I had code that compiled, I spent another couple nights getting the app to work again. In the end, I spent well over two weeks migrating the app to Swift 3.
This amount of time has very real consequences, but users will never see those efforts as direct improvements in the product.
I track Astra bugs and features in Trello, and I try to keep each card small enough to complete in one sitting. I keep the list prioritized, but when I know I have a small amount of time, I hunt for a card I know I can do all at once.
The Astra board didn’t change for over two weeks because of the Swift 3 migration. That was two weeks I didn’t get new features or enhancements built, or customer-reported issues fixed. I was simply agreeing to proposed changes by the tools, and then fixing the problems it created along the way.
The language an app is written in does very little to serve the needs of a customer. There are weak arguments that some languages result in fewer crashes or bugs, but that doesn’t play out in reality. A product built with proper testing practices always demonstrates a higher level of quality in my experience, regardless of language.
Fundamentally, a developer’s role in app development is to translate interaction and visual designs into functioning software. That means it’s their job to deal with unexpected errors and failures. It’s risk management. These risks also have to be balanced with product timelines - press events, market changes, and competition.
When the ability to ship a product is affected by a tool or programming language, a product owner has to question if it is the right tool. For software, the programming language is a means to speed up development of a product. For iOS, Swift keeps developers from having to write in C or Assembly, much like using UIKit keeps them from having to develop graphical interfaces from scratch. And while Swift is pleasant to use as a developer, it doesn’t provide tangible benefits to a product owner, much less end users.
Swift is both an academic venture and a product for Apple. It is mastered by two conflicting objectives - to aggressively evolve and simplify difficult development tasks, while marching along a scheduled release cadence. Caught in the middle, developers who choose to use the language end up with code that breaks regularly.
Last week, we also learned that ABI stability has been deferred from Swift 4.
Apple has been aggressive in deprecating versions of Swift, which means Apple dictates Swift migration timelines, and not the product owner. The next release of Xcode is expected to remove support for Swift 2.3. In the case of Astra, this hasn’t been a problem yet, but easily could be.
I had to spin a quick 1.0.2 release to Astra a few weeks ago. If you’re following along, you realize that meant fixing a bug in Swift 2.3. In addition to fixing the bug quickly, I had to decide how to get the the fix in both Swift 2.3 and Swift 3 branches. In the end, I implemented the bug fix twice, due to how divergent the project was after other refactoring.
With a fix in place, I had to build the code. Fortunately, I haven’t jumped to Xcode betas, so Swift 2.3 is still supported on my build machine. What if the timeline had played out differently? Sure, Apple still allows submissions from old Xcode versions. That would have meant lost time setting up an older Xcode version. There’s even more time I’m not building features or fixing bugs.
The choice to use Swift imposes a lot of otherwise unnecessary decisions and time costs.
Here are a few points to consider as you decide how to embark on a new project, whether it be personal, contract, or a product at work.
If the project is intentionally going to be short-lived (less than a year), use Swift. You’re already in the realm of quick and dirty. Constrain yourself to specific versions of libraries, and make sure you clearly communicate this approach is being used to all stakeholders.
For something medium-term (1-3 years), cautiously use Swift, but avoid third-party code. Projects with Swift frameworks need to match Swift version throughout. This means carefully matching versions of frameworks you’re pulling in, especially during migration periods. This is an easy place to burn a lot of time.
If you’re building a framework (especially a commercial one), use Objective-C. Do not impose unnecessary burden on apps integrating your library. Carefully design your interfaces for elegant Swift integration, but implement your code in Objective-C.
For a projects anticipating long-term development, or that have the scrutiny of investors, or are the primary means of putting food on your table, seriously consider Objective-C. It may not be glamorous or flashy, but it is reliable and proven. Seize the opportunity to demonstrate wisdom and expertise to clients by articulating a case for avoiding new shiny things.
As a developer, I’m very excited to watch Swift continue to evolve. I’m deeply impressed by Apple’s approach, both in making the language open source, and the level of public collaboration they’ve continued to demonstrate.
As a product owner, I have to be cautious when selecting tools. If it can’t be directly translated into value for my customers, then a flashy new tool or language isn’t the best choice. Today, Swift’s breakneck pace and deprecation cadence make it a risky choice for a product, whether it be a side project or a breadwinner.