SwiftUI и UIKit: как мы переработали корзину федеральной аптечной сети

UIKit
Swift
SwiftUI

Рассказываем, как мы переносили модуль корзины с приложения, написанного на SwiftUI, в приложение на UIKit. Объясняем, почему это оказалось невозможно и зачем вам уходить с UIKit, если вы планируете расширять приложение в ближайшее время.

Команда с хард-подходом в разработке

Мы умеем работать с  легаси-проектами и бесстрашно беремся за доработки уже существующего кода. Этот кейс о том, как мы делали перенос корзины из одного приложения в другое для крупной сети аптек. Проект был сложным, но мы сдали задачу.

Нам доверили доработку самой проблемной части приложения

Наш заказчик — сеть аптек в Москве и Санкт-Петербурге. Всего в этих городах и их областях открыто больше 140 офлайн-точек. Чтобы сделать покупки в аптеках доступнее для людей, было решено улучшить мобильное приложение сети.

Нас позвали дорабатывать клиентскую часть iOS-приложения. Одной из крупных задач была переделка корзины.

Из-за неудобной корзины аптечная сеть теряла клиентов

Баги в корзине появлялись периодически. А значит, их замечали пользователи и, конечно, не были от этого в восторге.

Вот что о корзине говорили пользователи. Из-за ее нефункциональности сеть теряла клиентов и опускалась в рейтингах

Но баги — еще полбеды. В корзине не отображались статусы товаров, и не было понятно, есть ли лекарство в наличии или доступно только под заказ. Нередко случалось следующее: пользователь оплачивал товар, ему приходила отбивка о выполненном заказе, а уже в аптечном пункте он узнавал, что нужного ему лекарства нет. Ноль удобства + потраченные нервы.

Вернется ли клиент в аптеку после такого?

Нам предстояло добавить статусы товаров — так клиент сразу увидит, какие товары есть в нужной ему аптеке, какие лекарства доступны под заказ, а каких и вовсе нет в продаже.

Решение № 1: копипаст

У заказчика было еще одно приложение для другой сети аптек. О работе с ним мы писали в кейсе «Исправили баги и увеличили аудиторию приложения с 50 тыс. до 110 тыс. Кейс федеральной аптечной сети». Вместе с заказчиком и его разработчиками решили, что можно взять наработки по корзине из второго приложения, во многом аналогичного по функционалу.

План был такой:

  • взять корзину другой сети, благо в ней есть весь нужный клиенту функционал и идентичный нашему заказчику API;
  • скопировать основную часть кода;
  • подредактировать.

Единственная загвоздка состояла в том, что исходное приложение было написано на более новом и прогрессивном фреймворке SwiftUI, а то, куда переносили решение, — на UIKit. Была вероятность, что из-за сложной совместимости этих двух фреймворков у нас могут возникнуть проблемы, но было решено попробовать.

Про то, как наша гипотеза провалилась, а разработчик чуть не выгорел

Сперва мы перенесли всю логику корзины, и… ничего не получилось. Корзина просто не появилась в приложении — так гипотеза с копипастом не сработала.

Потом было решено вручную прописать весь код корзины на SwiftUI, встроив его в UIKit-код имеющегося приложения. Сверстали все экраны, загрузили в них все данные, после чего  обнаружили, что эти самые данные не передаются с экрана на экран!

Что это значит? К примеру, выбираете вы на одном из экранов аптеку в соседнем доме. Приложение должно среагировать на то, что вы выбрали именно этот пункт, и на следующем экране показать, что такого товара в пункте нет, а такой-то доступен под заказ. В нашем случае этого не происходило — приложение изначально не подразумевало такой функции.

Как тогда скопировать готовый функционал, если приложение его не поддерживает? Переписать архитектуру. Архитектура — это свод правил, которые описывают, как различные части приложения взаимодействуют между собой, как передаются и обрабатываются данные.

Стали править архитектуру, чтобы заставить экраны взаимодействовать друг с другом. Частично это получалось. Одни экраны начинали работать, но вместе с тем другие тут же отваливались.

Приложение оказалось слишком монолитно — просто так его не расширить. Требовались новые решения.

Решение № 2: допилить то, что есть

Решили, что в этот раз разработчик даже не будет смотреть на референс, как и не будет пытаться переписать приложение полностью. Он просто продолжит писать на UIKit — используя те подходы, которые там уже были.

К тому моменту, как мы приступили к задачам приложения, с ним уже успели поработать разные разработчики. По коду было видно, что не все из них взаимодействовали друг с другом: в приложении накопилось много ошибок, связанных с разным подходом.

С UIKit удалось сделать перенос данных с одного экрана на другой, но потом в разных частях программы повылетала куча ворнингов. Было понятно, что разбираться в каждой из этих ошибок нет смысла — нужно было искать, что их всех объединяет.

Все дело в связях

Проблема в том, что корзина — самый главный модуль в программе, все остальные экраны приложения завязаны на ней. Когда корзину копипастили, эти связи оборвались, а восстановить их не получилось — как и исправить все за один раз.

Если мы меняем что-то в корзине, то что-то придется поменять и в другом месте. Если переделываем корзину полностью, то, скорее всего, понадобится переписать все приложение и при этом все время фиксить связи корзины с другими модулями!

Решили не повторять ошибку, а прописывать связи и добавлять нужные функции на UIKit.Для этого каждый день созванивались с менеджером заказчика и уточняли детали работы.

Вернулисьна UIKit и решили действовать в прежних рамках

В рамках старых подходов удалось переписать корзину.

Да, работа кропотливая. Да, всякий раз, когда компании захочется добавить новый функционал, его нельзя будет просто скопипастить — команде  придется писать все без опоры на уже существующие решения. Потому что таков UIKit. И такова архитектура приложения — сложная, негибкая, «железобетонная».

Чтобы справиться со всеми трудностями UIKit, нам потребовалось три месяца. К слову, если бы те же самые задачи мы делали на SwiftUI, работа над проектом заняла бы неделю.

Да, текущий код не выглядит красивым. Да, если команда будет вновь его расширять, то напорется на трудности. Все будет снова рушиться, ломаться, слетать, пока...

Пока приложение не будет полностью переписано

Сперва заказчик планировал расширять уже существующее приложение, написанное на UIKit. Коллеги думали, что сначала обновят корзину, потом добавят сервис для личного учета приема лекарств, а потом внедрят еще кучу фич. Но проблема с корзиной показала, что это будет долго, дорого и сложно.

Так как серверная часть обоих приложений одинакова, было решено делать для них общую кодовую базу. А к ней уже прикручивать верстку, уникальный дизайн и функционал.

Общая кодовая база нужна, чтобы код с одного приложения можно было переиспользовать.

Исправили баги, смержили ветки

После первой неудачи мы взялись за корзину основательно: параллельно прописали новый функционал, исправили множество багов, подключили крашлитикс (отчеты о сбоях в приложении), подключили пуш-уведомления.

Из-затого, что код писали шесть месяцев назад, объединить ветки без конфликтов невыходило.

Ветки — это копии проекта, в которые можно вносить любые изменения и которые не влияют на основной проект.

Чем дольше специалисты работают над одним проектом в отрыве друг от друга, тем сложнее будет в итоге объединить усилия и выкатить релиз. Пришлось разработать новую систему слияния веток.

Корзина готова!

Доделать корзину мы смогли — релиз состоялся 27 мая. Такой выдох и облегчение!

История с корзиной убедила заказчика менять приложение. Чтобы без лишних проблем его расширять, нужно перейти на SwiftUI.

***

Спасибо всем, кто дочитал до конца! И снова благодарим заказчика за доверие.

Подписывайтесь на наш канал. Сейчас мы идем в новое позиционирование: делаем ребрендинг, контент-маркетинг и пишем обо всей внутрянке, с которой сталкивается IT-компания.

Написать в телеграм

Читать еще

Приложение «Экодар». Помогаем компании стать ближе к покупателям, а людям пить чистую воду

React Native