Modernising our native Android and iOS codebases by migrating to Kotlin and Swift.
As developers contributing to and maintaining the Android and iOS mobile apps that make up immedia’s Fabrik platform, there are a number of things we expect to happen during the lifespan of the mobile apps we deliver. Bugs will arise, new features will need to be ideated, and both Apple and Google will release major updates to their operating systems - to which our apps will be required to adapt.
At each of these junctures, we’ll need to respond quickly as, of high importance to ourselves and our clients, is the guarantee that as environmental challenges evolve, so do our mobile apps to meet these challenges. At a high level, there are 4 areas of coding support that Fabrik apps receive:
Corrective, better known as bug fixing.
Adaptive; adapting to the latest hardware and OS changes.
Perfective; dealing with changes in user requirements.
Preventative; code restructuring & optimisations aimed at reducing complexity and preventing future errors.
The first three areas are fairly self-explanatory and commonly practiced as our team works hard to ship regular app updates for our Fabrik clients with the latest bug fixes and improvements, additional feature enhancements and finally, updates required to become compliant with the latest OSes.
However, as developers, we don’t readily reveal the ‘preventative’ part of what we do i.e. the behind-the-scenes code improvements, re-writes and optimisations that are implemented on an ongoing basis.
In this blog post, we offer some insight into what that looks like for Fabrik in particular, and how we’re working to ensure the longevity of our product through modernising our mobile app codebases.
When immedia’s development teams started to build Fabrik’s Android and iOS apps, the Objective-C coding language was initially used on iOS whereas Java was used on Android. Since then, alternatives from Apple (Swift for iOS) and Google (Kotlin for Android) have matured and become the gold standard for developing apps on their platforms. Now, any new app developer just starting out will default to using one of these newer languages rather than the 36-year old Objective-C or 20-year old Java. Swift is one of the fastest growing languages in history and, in 2019, Kotlin became Google’s preferred choice for Android development.
One of the key benefits of these languages is that they can be used in conjunction with their predecessors. On Fabrik, the code is currently a combination of the old and the new, and our endeavour now is to future-proof our source code as much as we can and systematically re-create as much code as possible into Swift and Kotlin.
However, for some features this interoperability does take some effort, so in order for us to keep delivering new features and app enhancements in the future, we’ll need to allocate time now to preventative maintenance with an expanded effort around code rewrites and optimisations. We will move quickly to ease out the historical languages in favour of the modern counterparts, so that our platform will continue to be operational today and for years to come. When we end this journey, our apps will be more efficient and less error-prone, which will make our investment of time and effort into these code migrations worthwhile.
For the most part, Swift and Kotlin share the same ideologies and will deliver much of the same benefits on their respective platforms.
Here are a few key points on why we’ve chosen to make these transitions:
1. Speed
The new languages are fast; for example, a simple search algorithm has been benchmarked as being 2.6 times faster in Swift than Objective-C.
Historically Objective-C has never been a fast language. It’s been built as an after-thought on top of the C programming language. Which means it carries with it legacy C functions.
Swift has removed the limitations of the C language.
Further, Objective-C also uses runtime code compilation rather than compile time: this means that when an Objective-C object calls code in another object, it’s not a direct function call; rather it leverages message passing. The runtime determines if an object actually implements the function represented in the message. If it doesn't implement it, the class will either forward the message onto another object, or throw an exception. This is incredibly fast, but still adds an overhead which would be measurable when it happens millions of times.
Swift and Kotlin benchmarks continue to improve with each update of the language. This is a key factor as it’s important to stay up-to-date with the latest releases of the language in order to reap all of the benefits. Swift currently is in version 5.2 with Kotlin at 1.4. (languages also receive updates with additional capabilities, bug fixes and improved methods of performing tasks).
2. Better Syntax
The languages are lean, intuitive, easier to read and it’s more efficient to apply changes when needed. Kotlin has removed a lot of clutter and redundancy from code. Literally a class that used to be 100 lines is now only 2 lines. This aids in preventing common programming mistakes (resulting in far fewer crashes!) as the more code you have, the more it costs to maintain due to the additional overhead it brings.
An example of a Kotlin feature that helps to reduce the size of the code base are Data Classes which allows the expression of POJOs with minimal code. The following showcases the original code in Java versus the Kotlin implementation.
Java Class:
public class Person {
private String name;
private String surname;
private String id;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getSurname() {
return surname;
}
public void setSurname(String surname) {
this.surname = surname;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
@Override public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Person person = (Person) o;
if (name != null ? !name.equals(person.name) : person.name != null) return false;
if (surname != null ? !surname.equals(person.surname) : person.surname != null)
return false;
return id != null ? id.equals(person.id) : person.id == null;
}
@Override public int hashCode() {
int result = name != null ? name.hashCode() : 0;
result = 31 * result + (surname != null ? surname.hashCode() : 0);
result = 31 * result + (id != null ? id.hashCode() : 0);
return result;
}
@Override public String toString() {
return "Person{" +
"name='" + name + ''' +
", surname='" + surname + ''' +
", id='" + id + ''' +
'}';
}
}
Kotlin:
data class Person(var name: String, var surname: String, var id: String)
As you can see, Kotlin saves all of the Java boilerplate code that’s needed.
3. Improved Compiler
Humans make mistakes and software has bugs. Some of the causes of these bugs can now be detected whilst coding and not only when running the app. Error messages are more precise, and the compiler is now better at pinpointing the exact piece of code that needs fixing. Further to that, code completion is faster and there is increased reliability in debugging. Lastly, building the app, whilst developing, is way quicker.
One such improvement is the handling of nulls or, as it’s often referred to, The Billion Dollar Mistake. Be it Objective-C or Java, a pain point for developers is the null reference which causes runtime exceptions or apps crashing. To overcome this, Kotlin provides null safety at compile time with Swift utilising the Optional type.
Code examples:
Swift
let number: Int? = 10
let letter: String? = "abc"
Kotlin
val number: Int? = 10
val letter: String? = "abc"
4. Open Source
The inner workings of the language are freely available to explore, meaning that the developer community at large are constantly working on finding and fixing bugs - this is really why the language has been able to grow in stability.
Today on the Swift repo there’s 104 000 commits, 27 000 merged pull requests, 8 400 forks and 341 branches. Kotlin also has astonishing stats: 65 000 commits, 1 372 merged pull requests, 3 900 forks, 3 900 branches. Both languages are actively maintained by both the original developers and the community.
A side effect of this is that the languages are also available to perform other tasks. We now have Swift on the Server, Swift for Windows and many other projects and new operating systems. Whilst none of these are mature, being open source does drive the penetration of the language.
5. Industry Standard
Over 50% of Android developers now use Kotlin, and Google themselves now take a Kotlin-first approach with many of their new features and libraries being offered first in Kotlin. Apple re-wrote foundational parts of their established operating system in Swift. As an example, on MacOS, the Dock (which is used to launch and switch between apps) is now in Swift.
Uber’s iOS code base is now 90% Swift, and many other big apps have either already begun or completed their migration to it. Netflix, Evernote, Lyft, Twitter, Pinterest, Flipboard and AirBnB are just a few examples.
Further to this there are also official communities from Podcasts to a Subreddit and even a Slack Group all aiding in taking the languages forward.
6. Future Support
If anyone has learnt iOS development in recent years, they would have learnt Swift. And as time goes on, the only developers who can support Objective-C will be the senior developers who have been working on iOS for an extended period of time. The same roadmap will unfurl as developers migrate from Android to Kotlin.
Whilst both Apple and Google have made their intentions clear on the way forward for development, it’s unlikely that either predecessor language will become completely obsolete. However, it will become very niche, and already some of the documentation on Objective-C development from Apple has been retired.
7. Developer Happiness
This deserves a noteworthy mention. When both Lyft and Basecamp rewrote their Kotlin apps, one of the driving factors was to make a huge difference in programmer happiness. To quote one of the senior engineers at Basecamp: “Happier developers leads to great code and ultimately a better product.” In addition, they wanted to improve developer work quality and speed.
In the latest Stack Overflow Developers Survey, Kotlin and Swift positioned themselves at number 4 & 9 of the most loved languages to work in respectively. At the opposite end Objective-C ranked as the second most dreaded.
TL;DR:
Swift and Kotlin really are better languages - they’re cleaner and less laboured than working on the legacy languages. Debugging is superior and learning advanced coding techniques is easier.
Whilst all the hard work and optimisations our teams are doing may not always be visible, our clients can rest assured that we are busy building an even better product that can be enjoyed long into the future!
P.S. Don’t worry - it’s not all maintenance work, and we do have some exciting feature updates planned for the next year as well so watch this space!
Comments