Better Programming

Advice for programmers.

Follow publication

An Opinionated View on KMM

Raphael Moutard
Better Programming
Published in
8 min readApr 18, 2023
Spendesk Mobile App

Let’s start with why?

In 2019, I was the manager of the mobile team at Spendesk. The app handles budget and expense management for teams and employees.

The mobile app was first developed in React Native as a Proof of Concept. The codebase was shared for both iOS and Android. But we quickly reached the limit of the technology (slow, lack of native features, UI bugs and crashes). So we hired 2 dedicated mobile teams (3 iOS and 3 Android dev) and took a year to rebuild the app using only native technology (Kotlin and Swift). The investment was a success. We increased crash-free rate sessions from 81% to >98%.

However, we had one main issue. The Android team was twice faster than the iOS team. The development cycle was longer on iOS and Project Managers struggled to keep them in sync. To solve this issue, a senior Android developer recommended migrating the mobile app to Kotlin Multiplatform Mobile (aka. KMM). The Android team was mostly in favour of the change, while the iOS team was reluctant to it. I decided to dive deep into the topic and make my own opinion. Here are the results of my discovery.

What is KMM?

Kotlin Multiplatform Mobile is a technology for cross-platform development. Developers share a common code base for business logic, written in Kotlin. The build process generates 2 native code libraries one for Android and one for iOS. You then import those libraries to your native project. The idea is to centralise the shared business logic (Data and state management) in one place and only have platform-specific code for the View (UI).

Kotlin MultiPlatform Architecture

KMM is a subset of KMP (Kotlin MultiPlatform). It supports other clients like desktops or web browsers. KMM is NOT a new cross-platform tool (such as Xamarin or ReactNative), as it builds native code.

KMM Benefits

The main benefits according to the website are:

  • share code (don’t repeat yourself).
  • native performance as it builds native code.
  • easy adoption as 60% of Android developers already use Kotlin.

However I don’t trust a marketing website, so I asked the Android team to write a document to explain why we should migrate to KMM. This is how the document starts:

Spendesk has 2 mobile teams (3 Android devs and 3 iOS devs). The two apps are identical in terms of features they only differ by their UI which adapts to the device. However teams don’t have the same velocity, iOS is consistently slower. For instance, the new Home Screen feature in Q4 2020, took 1 month on Android and 2 months on iOS. The Android team had to put on hold their release, and the marketing team had to delay the launch until iOS was ready.
This can be explained by two reasons: The Android team is more senior than iOS, (they work faster) and the Android code base is organised around Clean Architecture principles, so refactoring tasks like the new Home screen are easier.
By migrating to KMM:

  • The business logic will be shared and written in Kotlin by the Android team.
  • The iOS team will have less code to write, and they will benefit from Clean Architecture.
  • Better testing of the business logic shared in KMM
  • PR reviews would be faster and knowledge shared between teams.

👍 So far so good. We had a really specific problem in our team, and KMM looked like a reasonable solution to solve the velocity issue. This is one way to solve the issue, as a manager I just thought hiring another senior iOS engineer to balance the team would do it. As I kept reading the end of the document, I became more concerned.

As Android developers, we need to keep ourselves updated with the latest trends in a fast-evolving mobile world. KMM has been a recurring topic for a year and has become more trendy. The community is slowly leaning towards KMM, more and more companies are talking about it, even big dogs like Netflix (who documented their decision in an article on their engineering blog). So why not us?

🤨 I was surprised that trendiness would be part of the decision process. From my experience, choosing a new technology just because it’s cool is a bad reason. So I asked more questions.

  • What percentage of the code can we really share across iOS and Android?
  • What would be the cost of the migration to KMM?
  • The document focuses on the pros, can you list some cons?

I also involved the iOS team, as I mentioned they were reluctant to use KMM. I first didn’t want to bother them because they were late, but clearly, that change would have a massive impact on their work.

Sharing code

Sharing code has always been a trend, it’s DRY (Don’t Repeat Yourself). But it’s important to understand what you can share. Kotlin’s philosophy is different from React Native. It aims to replace specific parts of the code, not everything. According to the website, it focuses on networking, data storage/validation, and business logic.

Based on the results of KMM Survey 2022.

For instance, Netflix had a compelling argument for choosing KMM. They use it for the Studio App (not the one you use to stream video on your iPad). It’s used by movie production teams. “By nature of their work, the app is write-heavy, in a distributed environment, on devices where less than ⅓ of our users have reliable connectivity whilst on set. The high likelihood of unreliable network connectivity led us to lean into mobile solutions for robust client-side persistence and offline support.” (see article)

In other words, the Netflix Studio App has a lot of business logic directly inside the client. On the opposite, Spendesk has almost no business logic in the client. The behavior is driven by the backend. According to my estimation, we would abstract around 25% of the codebase by using KMM. (Data fetching and validation, caching strategy, and some Domain layer). For us, there is not a lot of benefit to sharing code.

Cost of migration

Migrating an Android app to KMM is straightforward, (especially if the app is already using Kotlin)

  • Change the building process (gradle file) to have 3 targets: commonMain , androidMain, iosMain
  • Change the directory folder to map the expected KMM structure.
  • Move the shared code into commonMain.
  • Migrate Multiplatforms compatible dependencies. (inside the common code you can only use dependencies that support multiple targets. Many modern Android libraries already have multiplatform support, like Koin, and Apollo, but some are still missing).

The good news is that your current codebase and KMM can cohabit. Migration can be done incrementally, one feature at a time using micro-libraries. It’s pretty easy to set up.

Migrating an iOS app is more complex. The code in commonMain needs to be able to build for both iOS and Android, and it’s not true by default.

  • Migrate your Xcode build to the Gradle KMM build.
  • Move your iOS code to the KMM project.
  • Update all interfaces that use native inputs (like BigNum) with expect or the @optional annotation, to make sure the common code can compile for both Android and iOS.
  • Write custom iOS code in Kotlin for parts that can not be shared.
  • Rewrite some iOS code to use the KMM-generated library instead.

On our Spendesk repository, the iOS team estimated 3–6 months to migrate our entire iOS codebase to KMM. I was surprised by the large estimation, but it also tells you about the lack of confidence they had in this project. That’s why many advocates for KMM are using it for “scratch projects”. It’s much easier to start a project in KMM than integrate KMM into an existing iOS codebase.

Drawbacks of KMM

  • Not production ready: in 2019, the technology was in the alpha stage (Beta was released in October 2022).
  • It means we needed to take into account the cost of non-backward compatible changes in the near future.
  • Crash easily on iPhone because iOS has a stricter memory model. (Need to “freeze” Kotlin objects to make them immutable before passing them to the iOS thread). Disclaimer: I haven’t tried the new Kotlin Native memory model that is supposed to solve those issues.
  • The learning curve for iOS dev: They have to learn Kotlin to be able to use KMM.
  • Learning curve for Android dev: They have to learn iOS/Xcode to make sure the common code they produce works on iOS.
  • Recruitment: difficult to find profiles that already know KMM. Especially harder to hire iOS dev willing to learn, as cross-platform solutions (like React Native or PhoneGap) had a bad reputation on the iOS ecosystem.
  • Poor iOS developer experience: Xcode integration is done through unofficial plugins and build scripts. To develop, engineers need both Xcode and Android Studio open at the same time.
    - Apple does not show any willingness to support KMM officially.
    - Kotlin builds in Objective-C and doesn’t support Swift yet. Making it harder for the dev to debug.
    - Generics on Kotlin can not be inferred on iOS
    - Doesn’t support Coroutines, Codable, Default argument or Swift enums.
  • Lack of support: The KMM community is still small and relies on a few companies (Jetbrains, Touchlab) to provide resources and libraries to enable developers.
  • Flutter competition: Google's cross-platform solution is Flutter. It became the official tech for apps of their next mobile OS Fuschia.

Conclusion

Is KMM a good technology? As usual, the answer depends on your requirements.

✅ It worked well for companies like Netflix or Deezer. They had specific needs like offline features that require moving business logic from the backend directly onto the client. I would even say that it’s better than React Native. It’s perfect to start a new project with fewer engineers and it will definitely give you a better experience than ReactNative when the app grows as it benefits from native technology. I like the philosophy to share only the business logic, it helps you structure your code. It can support sharing UI as well, yet wouldn’t recommend it. It’s a good tradeoff between short-term Bootstrap and long-term maintainability.

❌ However, because it’s not production ready, the poor iOS experience, the difficulty in hiring, and the politics between Apple and Google both pushing for their own technology, I am less confident in the durability of this solution. If you already have two native apps, I would recommend keeping them and don’t invest in the migration. If most of the business logic is in the backend, I would also avoid KMM.

My final concern is Why? Why are we so obsessed with reusing code? Is sharing code really beneficial? As a developer, It’s not the first time, DRY principles have made my life harder.

  • DRY bring strong coupling.
  • DRY makes it harder to test.
  • DRY can create convoluted code just to avoid copy-pasting.

I will have to dedicate an article about DRY principles, but I keep wondering, why is it bad to have different code bases for two different platforms?

Raphael Moutard
Raphael Moutard

Written by Raphael Moutard

VP engineering - Former @Amazon — Passionate about tech and Theater.

Responses (4)

Write a response