This commit is contained in:
Михаил Капелько
2026-04-03 10:19:38 +03:00
parent 493863ae5a
commit d4028d2a0d
17 changed files with 1616 additions and 61 deletions

View File

@@ -0,0 +1,22 @@
Title: КМП как альтернатива сокращению
Кому: Зуев Игорь, Корнюшин Пётр, Сухов Сергей, Терентьев Евгений, Петров Виктор
Привет, коллеги,
завтра состоится серия созвонов по поводу сокращения троих человек из
команды iOS Connect.
У меня есть встречное предложение по повышению эффективности
команд разработки с помощью Kotlin Multiplatform. Предлагаю перевести
сокращаемых троих человек в новую команду КМП, которую я готов возглавить
без отрыва от руководства командой iOS Connect.
КМП может сэкономить около 21% времени разработки, подробно я это расписал
в статье на Хабре: https://habr.com/ru/articles/989286/
Если предложение заинтересовало, буду рад обсудить детали данной спецоперации.
С уважением,
Михаил.

View File

@@ -0,0 +1,93 @@
Title: Что нам стоит на КМП построить?
URL: https://habr.com/ru/articles/989286/
Может ли Kotlin Multiplatform сократить трудозатраты при разработке одного продукта под несколько платформ? Мои вычисления говорят, что да, на 21%. Покажу это на примере своего хобби-проекта GitBudget для Android + iOS.
# Текущее положение дел
Одним из популярных способов разработки под несколько платформ является схема «одна платформа - одна команда разработки». Например, взглянем на известный мессенджер, заточенный под парковки. Некоторое время назад я словил следующую багу исчезновения сообщений:
<cut/>
<iframe src="https://kornerr.ru/vid/max-msg-disappear_2026-01-28.mp4"></iframe>
Как следует из видео, в ходе переписки с GigaChat у меня пропадали сообщения: на Android бага проявилась лишь раз (4-я секунда видеозаписи), на Web бага повторялась стабильно. Разное поведение на разных платформах свидетельствует о том, что продукт под разные платформы делают разные команды разработки. У каждой команды свой язык программирования, своя архитектура, свой процесс code review, свой уникальный набор порождаемых багов, своя команда тестирования, свой ФОТ и т.д..
Таким образом, чем больше мы дублируем в коде, тем больше мы вынуждены дублировать организационно. КМП может помочь сократить дублирование части кода, но, конечно, не полностью, а лишь на определённый процент. Каков этот процент? Посчитаем на примере моего хобби-проекта GitBudget.
# Обзор GitBudget
GitBudget - это крошечный хобби-проект для упрощения ведения собственных трат. На текущий момент нет истории трат, поддержки Git и прочего запланированного. Тем не менее, я пользуюсь этим приложением не первый месяц для упрощения ежедневного подсчёта двух важных для меня цифр:
1. Перерасход: Насколько на текущий день траты превышают план (бюджет)
2. Осталось ₽/д: Сколько можно потратить сегодня и в последующие дни текущей недели средств, чтобы не превысить недельный план (бюджет)
Углубляться в формулу и в архитектуру сейчас не буду, т.к. они не предмет данной статьи. Пытливый читатель всё это найдёт сам [на GitHub](https://github.com/kornerr/git-budget).
Ознакомимся с внешним видом приложения на Android и iOS:
![Android, iOS](https://habrastorage.org/webt/e2/bz/f5/e2bzf5lblg0xsydakc88zb5a_hu.jpeg)
Никакой фантастики в UI/UX нет, все элементы интерфейса стандартные (и даже не везде выровненные). Использование приложения на текущий момент сводится к трём действиям пользователя:
1. Вставить из буфера обмена траты за вчера (Spent)
2. Вставить из буфера обмена остаток баланса на вчерашний день (Morning balance)
3. Скопировать итоговый расчёт в буфер обмена (Result)
# Трудозатраты на разработку
Для удобства подсчёта условимся о разделении всего кода приложения на три группы:
| № | Группа | Пример | Файлы Android | Файлы iOS |
| --- | --- | --- | --- | --- |
| 1 | UI | Jetpack Compose, SwiftUI | MainActivity.kt, VM.kt | AppView.swift, VM.swift |
| 2 | Платформа | ClipboardManager, UIPasteboard | budget.kt, main.kt, other-android.kt, registerOneliners.kt | budget.swift, cld-ios.swift, other-ios.swift |
| 3 | Логика | budgetShouldResetMorningBalance | budgetFun.kt, entities.yml | budgetFun.kt, entities.yml |
КМП в GitBudget я использую лишь для логики, а UI и платформенный код нативные. Почему так? Потому что логика полностью под моим контролем, она обновляется по моему усмотрению. С UI и платформенным кодом ситуация иная - это собственность корпораций Apple и Google, они задают правила игры и обновляют UI с платформой по своему усмотрению (например, придумывают [Liquid Glass](https://habr.com/ru/articles/956116/), от которого не увернуться).
Считать будем два объективных показателя - количество строк кода и время, затраченное на реализацию какой-либо функциональности. На каждый из этих показателей посмотрим в разрезе вышеобозначенных трёх групп - UI, платформа, логика - и двух платформ - Android, iOS.
## Первый показатель: Количество строк кода
| № | Платформа | Всего | UI | Платформа | Логика |
| --- | --- | --- | --- | --- | --- |
| 1 | Android | 692 | 160 (23%) | 221 (32%) | 311 (45%) |
| 2 | iOS | 540 | 90 (16%) | 139 (26%) | 311 (58%) |
**Вывод-1**: 311 строк логики для iOS я **не писал повторно** благодаря КМП, это **58%** всего кода iOS.
**Вывод-2**: 311 ненаписанных повторно строк кода для iOS с точки зрения обеих платформ (692 + 540 = 1232) означают, что **25%** кода всего проекта я не писал повторно.
## Второй показатель: Время реализации функциональности
Под запись я добавил кнопку `Paste` для поля ввода `Morning balance` как для Android:
<iframe src="https://kornerr.ru/vid/git-budget-balance-android_800_2026-01-28.mp4"></iframe>
Так и для iOS:
<iframe src="https://kornerr.ru/vid/git-budget-balance-ios_800_2026-01-28.mp4"></iframe>
В итоге получились такие цифры:
| № | Платформа | Тип реализация | Особенности реализации | Время |
| --- | --- | --- | --- | --- |
| 1 | Android | Первичная | Создаём новую функциональность, которой не было, собираем почти все грабли | 17:34 |
| 2 | iOS | Вторичная | Подключаем готовую логику, дописываем лишь UI, граблей практически нет | 07:33 (43%) |
**Вывод-3**: Повторение функциональности на iOS с готовой логикой заняло на **57% меньше времени**, т.е. произошло **в 2 раза быстрее**
**Вывод-4**: Если принять, что без КМП функциональность на каждой из двух платформ делали бы в сумме 17:34 * 2 = 35:08 минут, то сэкономленные 10 минут при повторении функциональности для iOS означают, что для всего проекта я **сэкономил 21% времени**.
# Выводы
Итак, экономия с КМП в цифрах выглядит так:
1. Количество строк для iOS снизилось на **58%**
2. Суммарно количество строк кода по всему проекту снизилось на **25%**
3. Время, необходимое на повторение функциональности для iOS, снизилось на **57%**
4. Суммарно затраченное время по всему проекту на реализацию функциональности снизилось на **21%** (эту цифру я использовал в самом начале статьи)
# Вопросы читателю
1. Суммарная экономия в 21% по времени проекта - это много или мало?
2. Окупает ли экономия в 21% явно не однодневный переход команд на новый процесс разработки?
3. Насколько важен синхронный выпуск функциональности на обе платформы, причём работающей одинаково на каждой платформе?

121
articles/2026-02_KMP-en.md Normal file
View File

@@ -0,0 +1,121 @@
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:
<iframe src="https://kornerr.ru/vid/max-msg-disappear_2026-01-28.mp4"></iframe>
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:
1. Overrun: Did I spend more than my daily budget allows? If so, how many rubles?
2. 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](https://github.com/kornerr/git-budget).
Let's see how the application looks like for Android and iOS:
![Android, iOS](https://habrastorage.org/webt/e2/bz/f5/e2bzf5lblg0xsydakc88zb5a_hu.jpeg)
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:
1. Paste from the clipboard the sum I spent yesterday (Spent)
2. Paste from the clipboard the remaining budget balance I had for yesterday's morning (Morning balance)
3. 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](https://www.nngroup.com/articles/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:
<iframe src="https://kornerr.ru/vid/git-budget-balance-android_800_2026-01-28.mp4"></iframe>
And iOS:
<iframe src="https://kornerr.ru/vid/git-budget-balance-ios_800_2026-01-28.mp4"></iframe>
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:
1. iOS lines of code down by **58%**
2. Total project's lines of code down by **25%**
3. Time spent to repeat the functionality for iOS down by **57%**
4. 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
1. Is 21% of saved time worth it?
2. Is 21% good enough to actually step into KMP realm yourself?
3. How important is it to synchronously release the same functionality for both OSes?