5.9 KiB
TODO-Title: Does LinkedIn publication have a title? TODO-URL: LinkedIn TODO: Вернуть хостинг своего сайта на GitHub? TODO: Починить открытие видеозаписей TODO: Сделать ссылку на Русскую статью из Английской TODO: Сделать ссылку из Английской статьи на Русскую
Is Kotlin Multiplatform able to cut development costs for products that support multiple platforms? My calculations say yes, by 21%.
Current state of products for multiple platforms
One of the most popular ways to develop for multiple platforms relies on having a separate team for each platform. For example, here's one particular bug I faced in the russian messenger MAX some time ago:
As you can see, while I was chatting with GigaChat AI my messages were disappearing: Android had the bug once (the 4th second), Web had the bug multiple times. Having a different behavior on multiple platforms means there are different teams doing the same product for multiple platforms. Each team has its own programming language, its own architecture, its own code review process, its own set of unique bugs, its own team of testers, its own wage fund, and so on.
Thus, the more we duplicate the code, the more we have to duplicate the organization structures. Kotlin Multiplatform (KMP) can help reduce code duplication. Of course, KMP won't remove code duplication completely, only to some degree. Let's have a look at my hobby project GitBudget to find out that degree.
GitBudget summary
GitBudget is a tiny hobby project to help me ease calculating my day-to-day spendings. Currently there's no history, no Git support, etc. Nonetheless I've been using it for several months now to speed up tedious calculations of the two important figures:
- Overrun: Did I spend more than my daily budget allows? If so, how many rubles?
- Left ₽/day: How many more rubles do I have left to spend a day by taking the overrun into account?
I don't intend to dive deep into the formulas, it's outside the topic of the article. If you're interested you can have a look at the source code here at GitHub.
Let's see how the application looks like for Android and iOS:
No fancy UI/UX here, each UI element is a standard one (sometimes not even aligned correctly). As a user I usually use the application the following way:
- Paste from the clipboard the sum I spent yesterday (Spent)
- Paste from the clipboard the remaining budget balance I had for yesterday's morning (Morning balance)
- Copy the result of calculations into the clipboard (Result)
Development costs
Let's divide the source code by three groups;
| № | Group | Example | Android files | iOS files |
|---|---|---|---|---|
| 1 | UI | Jetpack Compose, SwiftUI | MainActivity.kt, VM.kt | AppView.swift, VM.swift |
| 2 | Platform | ClipboardManager, UIPasteboard | budget.kt, main.kt, other-android.kt, registerOneliners.kt | budget.swift, cld-ios.swift, other-ios.swift |
| 3 | Logic | budgetShouldResetMorningBalance | budgetFun.kt, entities.yml | budgetFun.kt, entities.yml |
I use KMP only for logic in GitBudget. UI and platform code are native. Why? Because logic is under my full control, it's only updated when I need it. UI and platform, on the other hand, are the properties of Apple and Google. They dictate the rules and update UI with the platform to their liking (for instance, Apple's unavoidable Liquid Glass).
We'll have a look at two objective indicators: lines of code and time spent to implement a functionality.
Indicator #1: Lines of code
| № | OS | Total | UI | Platform | Logic |
|---|---|---|---|---|---|
| 1 | Android | 692 | 160 (23%) | 221 (32%) | 311 (45%) |
| 2 | iOS | 540 | 90 (16%) | 139 (26%) | 311 (58%) |
Conclusion-1: I didn't write 311 lines of code for iOS again thanks to KMP, that's 58% of all iOS code
Conclusion-2: From the perspective of both operating systems (692 + 540 = 1232), these 311 unwritten iOS lines of code result in 25% of code I didn't write for the whole project
Indicator #2: Time spent to implement a functionality
I've recorded the process of adding a new Paste button for Morning balance input both for Android:
And iOS:
The results are:
| № | OS | Implementation type | Description | Time |
|---|---|---|---|---|
| 1 | Android | Initial | I've created a new functionality that has not existed before | 17:34 |
| 2 | iOS | Secondary | I've used already existing logic in KMP, only added a new UI | 07:33 (43%) |
Conclusion-3: It took 57% less time to repeat the functionality for iOS, i.e., it happened 2 times faster
Conclusion-4: If we assume that creating the same functionality for both OSes without KMP would take 17:34 * 2 = 35 minutes, then the saved 10 minutes to repeat the functionality for iOS result in 21% of saved time for the whole project
Conclusions
Thus, these are the figures when using KMP:
- iOS lines of code down by 58%
- Total project's lines of code down by 25%
- Time spent to repeat the functionality for iOS down by 57%
- Total time spent to implement the functionality for the project as a whole down by 21% (this is the figure I've used in the beginning of the article)
Questions to a reader
- Is 21% of saved time worth it?
- Is 21% good enough to actually step into KMP realm yourself?
- How important is it to synchronously release the same functionality for both OSes?
