How Coursera uses Swift

SITE NAME
2015-11-07T01:00:00+00:00

Coursera provides universal access to the best education. The Coursera iOS app lets our learners all over the world take courses on the go. They can watch lectures, take quizzes, post questions on forums and use other features to learn. All of this is native and we are constantly working on improving our app and adding new features.

We have been using Swift since it was released for all our new features. The following reasons led to that decision:

Good interoperability with Objective-C

Learning opportunity for the team

We were re-writing the app for a newer Coursera platform

We decided to go with iOS 8 as our minimum version for the new features (Apple allowed older iOS versions to download the old version)

We would not use complex features of Swift until it matures (like Curried Functions), and instead try to keep it simple.

When we started using Swift, we knew that we would hit roadblocks. The interoperability with Obj-C was perhaps the biggest reason that we were comfortable in doing so. If we were to have a compiler issue with Swift or if something required a more dynamic language, we could always switch to Obj-C for that part of the problem. An example of where we decided to use Obj-C was when we wanted to add a category to NSObject that automatically implemented NSCoding for us or when we wanted to use KVO.

When we started using Swift, we knew that we would hit roadblocks. The interoperability with Obj-C was perhaps the biggest reason that we were comfortable in doing so. If we were to have a compiler issue with Swift or if something required a more dynamic language, we could always switch to Obj-C for that part of the problem. An example of where we decided to use Obj-C was when we wanted to add a category to NSObject that automatically implemented NSCoding for us or when we wanted to use KVO.

Some roadblocks that we hit while using Swift:

Longer build times (This has improved considerably over the last few Swift releases)

Debugger had bugs (basic debugger commands didn’t work)

No code coverage tool in XCode

Not having visibility to code in tests (This was fixed in Swift 2.0 with @testable)

We wanted to build an architecture that lets us keep writing new features in a consistent manner.

A good architecture allows you to improve quality, deliver timely releases and develop features in a consistent manner as new team members join the team. With this in mind, we designed a new modular architecture for the app. Instead of rewriting the app, we introduced the new architecture to the app in an incremental manner, one feature at a time. As the Swift language evolved, this architecture has helped us get through migrations and enabled us to release new features with good quality. This architecture is also common to our iOS and Android apps.

Architecture

Each feature is a module which is a separate library. We have 3 Core libraries for persistence, networking, common UI elements and utilities. Since each feature is a separate library, they can be used in a standalone app without any of the other feature modules.

When we migrated to Swift 2, we first migrated the core modules. Once that was done, we were able to parallelize the migration of the other modules. This allowed us to migrate to Swift 2 in a reasonable amount of time. It left us with some time to work on iOS 9 features like Picture in Picture.

The Coursera app uses a remote configuration server for feature switches. We guard each new feature with a configuration switch. This allows us to do A/B testing when needed and also helps us to turn features off if there is a bug. This is especially helpful on the iOS platform since we cannot do hotfixes. If a feature has a bug, we are quickly able to turn it off.

Swift and MVVM

We use KVO for observing view models and protocols to communicate events out of the view. We have our own API around KVO to guard against any crashes because of misuse of KVO. The view model doesn’t have any direct knowledge of a view. We kept most logic out of the view, which helped us write unit tests.

Swift 2 migration stats:

Converted 120K lines of Swift code

+8602 lines, -262 lines

Took 3 days

Swift 2.0 and beyond

We really like the updates to Swift since the first version. With each Swift release, the pain points with Swift were reduced. Some of our favorite features in Swift 2.0 are:

guard and defer which help us write more readable code

New error handling features have simplified our internal API’s

Better interoperability between Obj-C and Swift with features like Nullability annotations and better support for enums between the 2 languages

Overall, we are happy with our decision to use Swift for new features. It has helped our team learn Swift and we have been able to improve the quality of our releases. 60% of our code is now in Swift and it is increasing with every new release.