Throughout my career, I was always focused on learning only native iOS technologies such as Objective-C and Swift. I considered (and still consider) myself as a "non-believer" in cross-platform solutions like React Native or Flutter - it's interesting and usable for small-scale projects and not really for bigger ones, because of its maintenance problems and scalability. And recently, at FootballCo, we started building brand-new Goal news and live scores application for Goal.com, which will be developed using Kotlin Multiplatform, and in this article, I want to share my experience of writing and maintaining a Multiplatform code.
At first, I was very confused (and a bit scared, there's nothing to be ashamed of).
Surely, I've already had some experience in building Android applications in Kotlin, but still, as an iOS Engineer, just the thought of working with Kotlin on a daily basis was frightening. Imagine - you just started a career with a pretty complicated language like Objective-C, then switched to much more pleasant Swift, developed your skills there and now you should change your paradigm and work on Kotlin and think as an Android developer (spoiler - not really).
Swift, Kotlin, and Objective-C "Loved vs. Dreaded" comparison, according to StackOverflow
But as an Engineer - you should be always open to new challenges and for learning new technologies, our world evolves so fast that you should be on the same pace with new technologies, and gaining new skills is a MUST if you want to succeed.
And surely I wasn't a totally new person in the Android world - my Uni thesis was about an application written in Kotlin, so life kind of prepared me for such a turn of things :)
The biggest benefit - code reusability and maintenance. In our legacy applications, we saw that big chunks of codebase could be shared between platforms - network layer, analytics, data persistence, most parts of business logic. All of these are pretty essential parts of any mobile application and we could easily write them once in cross-team collaboration, cover it with tests and use it on both platforms.
Every Multiplatform project in a nutshell
With it, comes the speed of delivery, better quality, and knowledge sharing. Just imagine - this big part of business logic, that your team worked on for months, could've been written by x2 amount of people, which could catch more bugs and come up with some interesting solutions.
Along with KMM (from now on I'll use this as a shortcut for Kotlin Multiplatform), we decided to write our apps using brand new platform technologies such as SwiftUI and Jetpack Compose. We kicked off our process with an MVP project in order to test all of the frameworks which I mentioned above and it turned out pretty well. We built a simple proof of concept application, integrated and tested all frameworks which we would use in a production app, and prepared all necessary automations.
To learn more about our MVP project and our findings , check this article by our Android Engineer Aleksander Jaworski: https://akjaw.com/kotlin-multiplatform-mobile-poc-conclusions/
We decided to put all our automations into fastlane, most of our engineers are used to use it and it contains a lot of pre-built solutions suitable for our needs. From the get-go, we understood that, at the initial stages, we would need to rebuild the KMM framework regularly - pretty much with every minor change in it, so putting it to the separate repository and accessing it from there was not the way to go, so we needed to come up with a solution that builds shared framework fast enough. At later stages, when changes to the shared framework will occur more rarely, we will surely encapsulate it into a separate repository.
While creating this proof-of-concept, we also changed our approach to daily ceremonies and merged most of them, we "switched" our mindset from thinking that we are two different teams (Android and iOS ) and started to position ourselves as one mobile team. I think for every project and every company it's very important to have such close communication between Android and iOS folks - after all, we are building almost the same application but for two different platforms, and our end-users should have the same experience on both.
As part of this process, we introduced pair-programming sessions, during which iOS developer sits with Android folks and, in collaboration, they build a multiplatform part of some feature - from modeling, implementing, and covering it with tests to performing a basic platform integration and checking if everything works fine.
These sessions were the most helpful thing so far - they gave our team members a brief introduction to Kotlin and after just one session you can debug, test, and introduce changes to multiplatform code by yourself!
So, after 6 months of working in a multiplatform approach, we already noticed a lot of very cool things that changed our way of work in a positive way.
Some of them are minor and not widely applicable, some will be surely helpful for any team, so here's the list:
You are a pioneer of new technology. I've heard only about 2–3 serious applications written in KMM and it's very exciting to try and work on something that fresh.
You can learn Kotlin and widen your horizons. Believe me - it's very similar to Swift and pretty easy to write in.
Shared codebase - write once and use by two teams. It is really very comfortable to write some big chunk of business logic just once and re-use it on a different platform (just imagine starting a sprint and receiving a message that we introduced a DB layer in our app and there's no need to build it!)
All core libraries are there to use! You are free to call iOS SDK libraries in KMM without any problems if needed.
You can see how the project works on Android and you can take part in the development of it. It's really crazy: Gradle, modules for features, co-routines, manifests - there's lots to learn about the d̶a̶r̶k̶ Android side of app development.
No need to test business logic on the app's side. All code that we share in KMM framework is covered by tests on the Kotlin side. This also means that you'll learn how to write and maintain tests in Kotlin
Our team and our possibilities doubled! Now it's not just two groups of people with different mindsets and proficiency in different technologies, but one big team of mobile engineers that collaborates on a daily basis, plans accordingly and solves problems much, much faster. In all approaches that I recollect thought my career, KMM was the only one that made it possible.
Knowledge sharing. I'm sure, your initial thought about the KMM approach was that only you, iOS Engineer, will need to adapt and learn, but that's not the case. The Android team also runs and debugs our code, so it works in both ways and is very beneficial for the team as a whole.
In order to start - you'll need to invest some time into learning the basics of Kotlin and Android development. There's no way to go around it - you just need to do it.
Very similar to the first one - you should bear in mind that it's a very fresh technology, so be ready to come up with workarounds and solutions for some weird problems.
You'll need to have two IDEs on your Mac - Idea or Android Studio for Kotlin/Android side and Xcode for the iOS one (AppCode - please don't do it)
It takes time to familiarise yourself with a new language and IDE. You'll need to learn a lot of new shortcuts, terminal commands and in general how the project is structured in Android.
Slow feedback loop. As mentioned before, any change in the shared KMM framework requires rebuilding it, so changes could be used in the iOS environment. The only way around is to run KMM tests, which will build a shared framework much faster.
In order to use the KMM code in Swift, you'll need a lot of wrappers. Like a lot. Most of the things are returned to our iOS world as Flow/Suspended Wrappers and you need to know how to handle them properly, keeping in mind async calls and error handling. It sounds kind of like RxSwift, but you will use it not only in network calls - even in order to get some static data (hardcoded in KMM or taken from some DB). At first, it might sound like taking a sledgehammer to crack a nut
Debugging might be really painful. If anything crashes on KMM side - you'll need to scroll through the debugger a lot and do it very carefully in order to find a source of the problem. Also, familiarise yourself with InvalidMutabilityException - it will be there with you for quite some time :)
In general, our team (as a whole, not just the iOS part of it) is very happy with the KMM approach. Quality-wise, positive feedback that we have is much bigger than the cons of it - most of the problems, like learning Kotlin and IDE, will be resolved in the first months and later on - you'll just catch the wave and you'll forget you used to hate it :)
We do see a very big future in the Multiplatform approach and we are looking forward to seeing where it gets us.
If you have any questions regarding our process, interesting findings during building proof-of-concept application, maintaining KMM in the iOS environment - don't hesitate to ask!