NDA
Медицина
Россия, Москва
Май 2024
Привет! Это Софториум, команда разработчиков из Сибири. Уже 3 года мы делаем сложную разработку, чтобы упрощать компаниям жизнь. В нашем послужном списке работа с Sokolov, R-Keeper, IIko и несколькими аптечными сетями.
Рассказываем, как мы переносили модуль корзины с приложения, написанного на SwiftUI, в приложение на UIKit. Объясняем, почему у нас ничего не вышло, и зачем вам уходить с UIKit, если вы планируете расширять приложение в ближайшее время.
Нам доверили доработку самой проблемной части приложения
Наш заказчик — сеть аптек в Москве и Санкт-Петербурге. Всего в этих городах и их областях открыто больше 140 офлайн-точек. Чтобы сделать покупки в аптеках доступнее для людей, они вместе с компанией-разработчиком решили улучшить мобильное приложение сети.
Бэкенд и Андроид разработчики взяли на себя, а нас позвали на доработки iOS, в числе которых была переделка корзины.
Из-за неудобной корзины аптечная сеть теряла клиентов
Баги в корзине появлялись периодически. А значит, их замечали пользователи и, конечно, не были от этого в восторге.
Но баги — еще полбеды. В корзине не отображались статусы товаров и не было понятно, есть ли лекарство в наличии или доступно только под заказ. Нередко случалось следующее: пользователь оплачивал товар, ему приходила отбивка о выполненном заказе, а уже в аптечном пункте он узнавал, что нужного ему лекарства нет. Ноль удобства + потраченные нервы.
Вернется ли клиент в аптеку после такого?
Нам предстояло добавить статусы товаров — так клиент сразу увидит, какие товары есть в нужной ему аптеке, какие лекарства доступны под заказ, а каких и вовсе нет в продаже.
Мы умеем работать с легаси-проектами и бесстрашно берёмся за доработки уже существующего кода. Например, для крупной сети аптек мы делали перенос корзины из одного приложения в другое. Проект был сложным, но мы сдали задачу, основательно перед этим намучившись. О наших попытках, поисках и ошибках и будет этот кейс.
Вместе с заказчиком и его разработчиками решили, что можно взять наработки по корзине из приложения во многом аналогичного по функционалу, над которым мы совместно работали до этого. Заказчику эта корзина очень нравилась, и мы думали, что сможем обойтись малой кровью.
План был такой:
1. Взять корзину другой сети, благо в ней есть весь нужный клиенту функционал и идентичный нашему заказчику API;
2. скопировать основную часть кода;
3. подредактировать.
Profit!
Единственная загвоздка здесь в том, что исходное приложение было написано на более новом и прогрессивном фреймфорке SwiftUI, а то, куда переносим решение, — на UIKit. Была вероятность, что из-за сложной совместимости этих двух фреймворков у нас могут возникнуть проблемы. Но кто не рискует, тот не делает мобильные приложения.
Про то, как наша гипотеза провалилась, а разработчик чуть не выгорел
Сперва Кирилл перетащил всю логику корзины и… ничего не получилось. Корзина просто не появилась в приложении — так гипотеза с копипастом не сработала.
Потом Кирилл решил, что нужно вручную прописать весь код корзины на Swift UI, встроив его в UI Kit код имеющегося приложения. И вот представьте: он сверстал все экраны, загрузил в них все данные, потратил на каждый из них кучу времени. А потом обнаружил, что эти самые данные не передаются с экрана на экран!
Что это значит? К примеру, выбираете вы на одном из экранов аптеку в соседнем доме. Приложение должно среагировать на то, что вы выбрали именно этот пункт, и на следующем экране показать, что такого товара в пункте нет, а такой-то доступен под заказ. В нашем случае этого не происходило — приложение изначально не подразумевало такой функции.
Как тогда скопировать готовый функционал, если приложение его не поддерживает? Переписать архитектуру, конечно же. Архитектура — это свод правил, который описывает, как различные части приложения взаимодействуют между собой, как передаются и обрабатываются данные.
Кирилл каждый день правил эту самую архитектуру, чтобы хоть немного заставить экраны взаимодействовать друг с другом. Иногда у него кое-что получалось: одни экраны начинали работать, но вместе с тем другие тут же отваливались. Так продолжалось три месяца, до тех пор, пока Кирилл не выгорел.
Мы посмотрели на Кирилла, посмотрели на приложение и сделали вывод: оно слишком монолитно — просто так его не расширить. Требовались новые решения.
Чтобы Кирилл не выгорел основательно, мы аккуратно перевели его на другой проект, а заниматься корзиной поставили Сашу. Решили, что в этот раз разработчик даже не будет смотреть на референс, как и не будет пытаться переписать приложение полностью. Он просто продолжит писать на UIKit — используя те подходы, которые там уже были.
Вот что увидел Саша, когда пришел на этот проект:
1. корзина не работает;
2. связи корзины с остальными модулями нарушены;
3. ошибки приходят из разных частей приложения.
К тому моменту над приложением уже поработали разные разрабы. По коду было видно, что не все из них взаимодействовали друг с другом. На проектах, которые переходят из рук в руки, такое вроде бы даже считается за норму.
Но пока новый специалист разберется в коде и начнет писать свой, он столкнется со множеством чужих ошибок, на устранение которых потребуются дополнительные ресурсы. Это все равно, что несколько авторов одновременно будут писать книгу, не советуясь друг с другом. Конечно, они будут пытаться переделать те части текста, которые могут помешать их дальнейшей работе.
Вместе с разработчиками мы решили, что нужно все менять. Ведь однажды текущее положение дел аукнется заказчику проблемами с производительностью.
Саша чуть покопался в коде, вроде бы сделал переход данных с одного экрана на другой, но потом в разных частях программы повылетало кучу ворнингов. Было понятно, что разбираться в каждой из этих ошибок нет смысла — нужно было искать, что все эти ошибки объединяет.
Все дело в связях
Проблема в том, что корзина — самый главный модуль в программе, и все остальные экраны приложения завязаны на ней. Когда корзину копипастили, эти связи оборвались, а восстановить их не получилось — как и исправить все за один раз.
Если мы меняем что-то в корзине, то что-то придется поменять и в другом месте. Если переделываем корзину полностью, то, скорее всего, понадобится переписать все приложение. И все время фиксить связи корзины с другими модулями!
Саша решил не повторять ошибку, а прописывать связи и добавлять нужные функции на UIKit. Для этого он каждый день созванивался с менеджером заказчика и уточнял детали работы.
Почему все в итоге заработало? Потому что Саша двигался исключительно в тех подходах, которые были предусмотрены приложением.
Да, работа кропотливая. Да, всякий раз, когда компании захочется добавить новый функционал, его нельзя будет просто скопипастить — команде придется писать все без опоры на уже существующие решения. Потому что таков UIKit. И такова архитектура приложения — сложная, негибкая, «железобетонная».
Чтобы справиться со всеми трудностями UIKit, нам потребовалось 3 месяца. К слову, если бы те же самые задачи мы делали на SwiftUI, работа над проектом заняла бы всего неделю.
Да, текущий код не выглядит красивым. Да, если команда будет вновь его расширять, то напорется на трудности. Все будет снова рушится, ломаться, слетать, пока...
Сперва заказчик планировал расширять уже существующее приложение, написанное на UIKit. Коллеги думали, что сначала обновят корзину, потом добавят сервис для личного учета приема лекарств, а потом внедрят еще кучу фич. Но проблема с корзиной показала, что это будет долго, дорого и сложно — поэтому разработчики решили переписать приложение.
Так как серверная часть обоих приложений одинакова, было решено делать для них общую кодовую базу. А к ней уже прикручивать верстку, уникальный дизайн и функционал.
Общая кодовая база нужна, чтобы код с одного приложения можно было переиспользовать. И чтобы, условно, в этот раз у Кирилла получилось скопипастить корзину без нервотрепки, а заказчику — сэкономить деньги на разработке.
Так не придется дважды писать один и тот же функционал под разные приложения и мучаться с совместимостью фреймворков.
Исправили баги, смержили ветки
После первой неудачи мы взялись за корзину основательно: параллельно прописали кучу нового функционала, исправили множество багов, подключили крашлитикс (отчеты о сбоях в приложении), подключили пуш-уведомления, все не раз протестировали. И тут оказалось, что ветки функционала, которые писались давно, разошлись.
Ветки — это копии проекта, в которые можно вносить любые изменения и которые не влияют на основной проект.
Из-за того, что код писали шесть месяцев назад, объединить ветки (читай — разом внести все финальные изменения в проект) без конфликтов не выходило.
Представьте, что вы с командой собираете дом. Один человек занимается крышей, другой — каркасом, третий — фундаментом. И все это без согласования друг с другом. Потом начинаете соединять все части, и оказывается, что величина каркаса не соответствует фундаменту. Что крыша получилась слишком большой, а стены маленькими.
Чем дольше специалисты работают над одним проектом в отрыве друг от друга, тем сложнее будет в итоге объединить усилия и выкатить релиз. Это уже не говоря о том, что из-за подобных сложностей работа сильно тормозится.
Мы долго пытались смержить ветки, а в итоге придумали целую систему, которая позволяет нам сэкономить до нескольких десятков часов на этапе завершения проекта. Надеемся вскоре сделать про это кейс — если тема вам интересна, пишите, пожалуйста, в комментарии. Расскажем обо всем без утайки.
Корзина готова!
Доделать корзину мы смогли — релиз состоялся 27 мая. Такой выдох и облегчение!
Наши страдания с корзиной убедили заказчика менять приложение: все же оно железобетонное, негибкое, написанное по старой технологии. Чтобы без лишних проблем его расширять, нужно перейти на SwiftUI, чем мы сейчас как раз занимаемся.
Анна Сабадаш
Вот такой кейс у нас получился. Спасибо всем, кто дочитал до конца! И снова благодарим наших друзей-разработчиков за доверие экспертизе. Классно сработались — будем рады помочь ещё! Подписывайтесь на наш канал https://t.me/+e3YmBK7CjcQ2ZTRi. Сейчас мы идем в новое позиционирование: делаем ребрендинг, контент-маркетинг и пишем обо всей внутрянке, с которой сталкивается IT-компания. Ну и конечно ждем ваши комментарии по кейсу.
Софториум с удовольствием обсудит вашу задачу