Привет, я Андрей Кучеренко, тимлид мобильной разработки Skyeng. Мы делаем мобильные приложения под iOS и Android. У них одинаковая функциональность и одинаковый с точностью до стилистики интерфейс. Но из-за разных платформ разработка вроде бы одного приложения получается довольно дорогой. В поисках возможности сэкономить на мобильной кросс-платформенной разработке, мы опробовали четыре решения:
Мне довелось выступить с несколькими докладами о том, что из этого получилось; в этой статье я собрал основные наблюдения и результаты.
Два года назад у нас было два отдельных мобильных приложения и две команды разработчиков, связанных только общим продакт-менеджером. Из этого вырастала куча проблем: приложения друг друга внешне напоминали лишь отдаленно, работали во многом по-разному, разработчики не имели представления о том, как устроено соседнее приложение, регулярно вылазили всякие баги и ошибки в логике. В определенный момент стало понятно, что продолжать так нельзя, и первое, что мы в этой связи сделали – объединили разработчиков iOS и Android в одну продуктовую команду, сделав ряд процессов общими.
Одним из таких процессов стало техническое ревью.
Прежде чем попасть к разработчику, задача проходит определенный путь. Для начала она формулируется в формате User Story, по ней рисуются скетчи или макеты, после чего заводится эпик, в котором описывается пользовательская проблема и ее решение. В таком виде история попадает к тим-лидам, если это кросс-командный эпик, или к одному тим-лиду, если он на одну команду. Там все декомпозируется до уровня отдельных задач. В каждой такой задаче, если это уместно, описывается возможное решение, задачи внутри Эпика линкуются друг с другом, проставляются различные блокеры, что убирает множество лишних коммуникаций. После этого происходит непосредственно техническое ревью, на котором будет зафиксировано финальное решение и будет выставлен эстимейт. Также на этом этапе задача может быть дополнительно декомпозирована, если эстимейт получается больше двух дней.
Как мы экономим на совместном техническом ревью:
Автобусный фактор: количество человек в команде, которых должен сбить автобус, чтобы проект не мог дальше продолжаться.
Очень часто для решения задачи нам помимо непосредственно написания кода нужно провести какое-то исследование, выполнить проектирование, а если задача предполагает межкомандное взаимодействие, потратить много времени на коммуникации. В контексте мобильной разработки – любые задачи, которые всего этого не требуют, представляют собой что-то тривиальное, не предполагающее работы со стороны бэкенда. Их я называю «простыми», а все остальные – «сложными».
Я проанализировал ворклоги на предмет распределения времени, которое тратится на написание кода, коммуникации, проектирование и research. Вот что получается для простых задач:
Здесь все понятно, в основном пишем код, затраты на него – до 80% времени.
Очень часто задачи предполагают какую-то доработку со стороны бэкенда, это автоматически делает ее межкомандной. Здесь больше времени уходит на проектирование и на коммуникации. Доля написания кода снижается:
Часто продакты приходят с задачами, которые плохо вписываются в текущую архитектуру приложения, и нам нужно потратить время, чтобы найти хорошее решение: возможно, спланировать какой-то рефакторинг, сразу его провести в рамках задачи и т.д. В этом случае много времени уходит на проектирование:
Наконец, задачи, с которыми вообще непонятно, как подступиться, где надо сначала исследовать и проектировать:
Если работу над сложными задачами никак не координировать, то вся работа, не относящаяся непосредственно к написанию кода, будет делаться два раза. А в сложных задачах это по 50% времени решения, часто еще больше.
Я нашел выход: просто взял и замкнул все эти задачи на себя. Время сэкономить получилась, но я стал постоянно перегружен, у меня не хватало времени, чтобы уделить внимание низкоприоритетным задачам, разработчикам приходилось меня дожидаться, все было плохо. Снова возникла проблема, и ее уже мы решили созданием рабочих групп.
Рабочая группа – это несколько iOS- и Android-разрабочиков, которые будут заниматься непосредственно реализацией данной фичи. Один назначается ведущим, именно он будет отвечает за проектирование, research, взаимодействие с другими командами. Результатом его работы будет документация, где все зафиксировано; эти доки затем ревьювятся рабочей группой и тимлидом, и команда приступает к реализации.
В результате получили:
Документацию мы решили вести в маркдауне и хранить в гитхаб-репозитории. Документация ревьювится вместе с кодом и с пулл-реквестом, таким образом мы исключаем ситуации, когда что-то написано, но никто этого не читал, и когда оно потребовалось, то никто ничего не понимает. Документация с кодом позволяет погрузиться в контекст, понять, о чем вообще был пулл-риквест.
Редактируем документацию мы прямо из IDEшки, большинство из них умеют рендерить маркдаун, это не отрывает от написания кода, не надо лезть куда-то в конфлюенс, снижается опасность, что разработчик просто забьет ее обновлять. Тем, кто скачал репозиторий локально, мы кидаем ссылки на Гитхаб, они тоже могут все читать.
Наконец, такой стиль ведения доков помогает в онбординге нового разработчика: вместе с кодом он получает все возможные код-стайлы, конвенции, инструкции по сборке приложения, вход в команду проходит намного проще.
Идея писать общий код не самая новая, существует куча инструментов, чтобы это делать. Мы пробовали C++ для написания библиотеки словарного тренажера, и у нас есть небольшое приложение, полностью написанное на Kotlin Multiplatform. Теоретически, при использовании инструмента кросс-платформенной разработки наши расходы на написание кода должны бы снизиться в два раза. Но появляются дополнительные:
расходы на старте. Массу времени придется потратить на то, чтобы это все собрать, запустить, протестировать, проверить гипотезы, обучить команду. В некоторых случаях эти расходы получаются такими большими, что профита не видно вообще;
написание платформенного кода. По своему опыту и основываясь на ряде источников могу сказать, что какой бы вы инструмент ни выбрали, если у вас достаточно сложное приложение, то рано или поздно вам придется писать платформенный код. Время на его написание сильно различается в зависимости от выбранных инструментов;
устранение недоработок. Большинство инструментов все еще довольно сырые, в них есть баги, вам придется столкнуться с какими-нибудь ломающими обратную совместимость релизами, и на устранение всего этого тоже придется потратить какое-то время;
обход ограничений. У кросс-платформенных инструментов могут быть архитектурные или еще какие-то ограничения, в которые можно упереться и потратить время на их обход. Иногда такие ограничения оказываются настолько серьезными, что приходится вообще отказываться от инструмента. Так, например, Airbnb отказались от React Native и откатились назад к нативной разработке;
Усложнение разработки. Вам приходится или писать код под две платформы сразу, что не все умеют, плюс появятся дополнительные коммуникации. Отсутствие нативных IDE тоже не упрощает такую разработку.
Чтобы сравнить расходы на те методы кросс-платформенной разработки, которые мы попробовали, выделил четыре основные группы:
Взял ворклог тасок и сравнил время, фактически потраченное на кроссплатформенную разработку и время, которое мы бы предположительно потратили на нативную разработку.
Каждый столбец – таска. В случае C++ получился довольно легкий старт, но расходы на инфраструктуру оказались существенными, общая экономия – всего 29%. От C++ отказались еще и потому, что этот язык понижал автобусный фактор: наши мобильные разработчики не знают С++, они могут поддерживать код, но серьезного опыта ни у кого в команде не было.
Очень высокие стартовые, зато пока расходы на платформенный код и инфрастуктуру невелики. У нас не было достаточного для хорошего анализа количества задач, по текущему положению сэкономили 19%. Предположив, что мы сделаем очень много задач, и отбросив стартовые расходы, получим экономию порядка 40%, если, конечно, в дальнейшем не вылезет каких-то серьезных проблем. Еще один плюс – большинство разработчиков неплохо знакомы с Kotlin.
Минус очевиден – усложнение процессов. Мы или пишем под обе платформы сразу, а не все это могут, или дожидаемся, пока кто-то напишет общую часть, потом мы ее проревьювим, потом окажется, что она не подходит и т.д. и т.п. Приходится закладывать дополнительные расходы на этап проектирования, чтобы все наверняка сразу завелось.
Итого:
К сожалению, не доступен сервер mySQL