Как стать автором
Обновить

Как мы обновляли мобильное приложение для официантов: выбор стека и тест трех версий. Кто победил?

Блог компании r_keeper Разработка мобильных приложений *Разработка под Android *Kotlin *Flutter *
Всего голосов 5: ↑5 и ↓0 +5
Просмотры 3.5K
Комментарии 36

Комментарии 36

rkeeper просто тихий ужас для разработчика. Извините ребят, просто наболело. Делал интеграцию сайта ресторана с Rkeeper (+ ваша же CRM для бонусов) Не знаю как сейчас, но полгода назад не было метода, с помощью которого можно было получить количество бонусов у клиента из CRM, список пользователей, проверить, есть ли такой пользователь и так далее.

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

Худшее API. Поддержки 0, им задаешь вопрос, в ответ - обратитесь к вашему дилеру. Да дилер сам не знает. Он не является разработчиком...

Еще раз, не принимайте близко к сердцу, реально накипело.

Если не верите, смотрите:

1) https://docs.rkeeper.ru/delivery/arhiv/api-webdelivery/opisanie-api/crm-api#CRMAPI-%D0%9F%D0%BE%D0%BB%D1%83%D1%87%D0%B5%D0%BD%D0%B8%D0%B5%D0%B8%D0%BD%D1%84%D0%BE%D1%80%D0%BC%D0%B0%D1%86%D0%B8%D0%B8%D0%BE%D0%BA%D0%BB%D0%B8%D0%B5%D0%BD%D1%82%D0%B5(GET)

Метод получения информации о клиенте, окей, а как мне получить сам ID клиента из существующей базы? А никак.

2) Как узнать бонусы? Никак.

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

Это все относится к самому r_keeper, тут речь про приложение для официантов.

Можете ли поделиться тестовыми проектами (1. 2. 3)? Особенно интересен 3.

С удовольствием бы, но в проектах используется проприетарный backend-API, руководство, к сожалению, не разрешило выкладывать код в открытый доступ
Извините за поздний ответ, надеялся договориться

А почему не рассматривали React Native?

. Javascript они не знают — из-за этого выбыли React Native и Cordova. 

Когда вы решите сделать web версию приложения, по какому пути вы пойдёте?

А, собственно, в чем разница? KMM работает под WEB, даже недавно вышел драйвер под JS для БД SQLDelight. Flutter также в этом году в марте дошел до стадии релиза для Web. Схема та же, аналогична приведенной в статье.

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

А как данные передаются между flutter и kotlin кодом? Имхо самый интересный аспект, как получить данные в UI с этим подходом и как вызвать методы kotlin слоя.

Вообще, во флаттере существует вполне удобный механизм для работы с платформой https://flutter.dev/docs/development/platform-integration/platform-channels.
Можно и вызывать методы другого слоя напрямую, и подписываться на потоки, слушая изменения. Сущности через этот механизм platform-channels передаются через сериализацию\десериализацию в json.

во второй части статьи про это будет подробнее рассказано

Если оно идёт через сериализацию, то не приходится ли писать один и тот же класс 2 раза в котлине и дарте? И не будет потом проблем с поддержкой 2х вариантов класса? Есть какая-то валидация консистентности этих дубликатов во время компиляции?

Именно писать 2 раза не приходится, есть же готовые конвертеры из JSON вроде https://javiercbk.github.io/json_to_dart/. То есть мы писали в kotlin-части сущности в виде data-классов, конвертили в JSON и потом его же в Dart.

Ну проблемы при общении между слоями всегда могут быть, разве общение с бэкендом через API и передача сущностей в обе стороны чем-то принципиально отличаются от общения flutter с kotlin? Там тоже могут быть проблемы с разными вариантами одного класса. На практике, в реальном проекте в этой части мы серьезных проблем не ловили
Валидации на этапе компиляции нет, как прикрутить тут тесты не придумали

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

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

ну никто не мешает покрывать тестами обе части и делать изменения в контракте между флаттером и котлином максимально осторожно. Собственно, так у нас и происходит на практике

Но хотелось бы в идеале как-то автоматизировать проверку консистентности на этапе компиляции, тут целиком согласен

Можно поподробнее, чем плох вариант Flutter и только Dart? использование Котлин мультиплатформ, на мой взгляд, это излишнее усложнение, которое имеет смысл только при наличии кодовой базы на котлин

Извините, что повторяюсь, но еще раз приведу консёрны из статьи:

"Не было уверенности, что неопытный в этой технологии разработчик сможет качественно выстроить архитектуру и написать бизнес-логику. Мы также опасались, что кроссплатформа не позволит полностью реализовать все специфические особенности каждой платформы, вроде работы с push-уведомлениями или железом. Были сомнения и в достаточной производительности Flutter на слабых устройствах (такие нередко встречаются у корпоративных клиентов). "

Если резюмировать - то разработчики отлично знали котлин и не знали дарт. Плюс хотели иметь резервный вариант по-быстрому написать UI на нативке, если вдруг flutter-UI будет медленным или неудобным.

Сейчас, по прошествии полугода, выбор пал бы на чистый флаттер, полагаю

Спасибо за ответ. В целом тогда - да, выбор Котлин мультиплатформ кажется логичным и оправданным

На мой взгляд, тут больше вопрос не "на чем", а "зачем":
- зачем с нуля что то переписывать?
- зачем был выбран flatter (на Dart) вместо React Native (на javascript) если команда не знала ни тот ни другой язык?
- зачем вам вообще было нужно нативное приложение (какие преимущества вы ожидали в отличии от веб версии)?
- если разработка хотела на kotlin и знала его, то почему не был выбран https://github.com/JetBrains/kotlin-wrappers/tree/master/kotlin-react?
- зачем вам в вашем приложении в котором выводится картинка и информация, нужно быстродействие нативного приложения?
- я верно понимаю, что вы в приложении объединили все три слоя на которые разделили свое приложение?
- не понятен результат выбора технологии: вы окончательно перешли на выбранный технологический стек и если да то сколько времени вам на это потребовалось и сколько разработчиков в этом участвовали?
- ну и самый важный вопрос, вы указывали что есть желание сократить ttm, какой он был средний и какой он стал после перехода на новый стек?

Мне кажется, вы невнимательно читали статью.

зачем с нуля что то переписывать?

Если код в старом приложении дурно пахнущий, то его отрефакторить и переписать заново — задачи одного уровня времязатрат. Тут же их 2 нативных, так что рефакторить можно и дольше. Плюс в кроссплатформенное приложение потом быстрее изменения вносить, потому что это надо делать один раз.

зачем был выбран flatter (на Dart) вместо React Native (на javascript) если команда не знала ни тот ни другой язык?

Dart максимально похож на Java, который Android-разработчики точно знали. Можно буквально сказать: "private/public/protected теперь нет, используйте _ для обозначения приватности. Все, можете приступать к работе". У меня с Dart так и было. JS же — это целый свой мир.

зачем вам вообще было нужно нативное приложение (какие преимущества вы ожидали в отличии от веб версии)?

Нормальный доступ к нативным функциям устройства? Не знаю, допустим, считывать NFC-чипы официантам надо будет.

kotlin-react

Штука намного менее мейнстримная, чем даже Flutter.

зачем вам в вашем приложении в котором выводится картинка и информация, нужно быстродействие нативного приложения?

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

Спасибо, все верно, сам бы не ответил лучше

сорь, но достаточно внимательно.
мой опыт показывает, что зачастую переписать и отрефакторить - это разные уровни задачи по времезатратам и бюджету. Если у вас иной опыт, то я завидую вашему опыту.
я веб разраб и для меня не очевидно какие именно нативные функции необходимы для официанта в приложении, быстродействие ему не нужно т.к. бизнес логики кроме отправить запрос в rest api ему тоже не нужно, на мой взгляд. Даже nfc функционал зачем ему? (@SergeiArsyonov тут наверное к тебе вопрос)
по поводу того что js (ts) это другой мир - соглашусь. но с вашего позволения обновлю ваши знания о js и теперь там есть приватные методы и свойства (https://developer.mozilla.org/ru/docs/Web/JavaScript/Reference/Classes/Private_class_fields)

  • какие именно нативные функции необходимы для официанта в приложении, быстродействие ему не нужно т.к. бизнес логики кроме отправить запрос в rest api ему тоже не нужно, на мой взгляд. Даже nfc функционал зачем ему?

Ну оплата заказа карточками (в виде взаимодействия с драйверами терминалов), сканирование QR-кодов камерами, понимать состояние коннекта с интернетом и т.д.

хм. я думал, что мобильное приложение для официанта не имеет прямой доступ к кассе, а касса - это отдельное приложение и/или устройство которое получает данные с сервера транзакций

Ну формально да, оплата это мобильная касса, не совсем приложение официанта. Но у r_keeper эти два приложения объединены в одно: официант набивает заказы в приложение, оно передает все на сервер\стационарную кассу (на которой тоже можно сделать оплату), и это же приложение офицанта может принять оплату

и оплату мобильный официант принимает qr кодом?
я верно понимаю, что ради сканирования qr были объединены 2 функционально разных приложения?
сорь, реально интересно т.к. я всегда думал, что касса как отдельный терминал который выполняет узкоспециализированную задачу и более никто ее не выполняет в целях безопасности

Ну почему обязательно QR-кодом? И обычной банковской картой тоже через выносной терминал. А код может использоваться для скидок, програм лояльности и т.д.
Само приложение синхронизируется с кассовым сервером, поэтому проблем с платежами нет. В любом случае, безопасность при использовании традиционного бумажного блокнотика и оплате наличными или карточкой ничуть не выше.

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

оке. пасиб

Уважаемый Bringoff уже абсолютно верно ответил за меня на основные вопросы. Немного дополню его ответ:

  • зачем с нуля что то переписывать?

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

В целом, по грубой оценке, переписывание с нуля сэкономило 50% усилий (человеко-часов) и сильно повысило удовлетворенность разработчиков от работы, что тоже важно

  • я верно понимаю, что вы в приложении объединили все три слоя на которые разделили свое приложение?

Не очень понял вопрос. В приложении 3 классических слоя чистой архитектуры. Слой представления сделан на флаттер, остальные два - на КММ, все слои объединены в одном приложении

  • не понятен результат выбора технологии: вы окончательно перешли на выбранный технологический стек и если да то сколько времени вам на это потребовалось и сколько разработчиков в этом участвовали?

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

  • ну и самый важный вопрос, вы указывали что есть желание сократить ttm, какой он был средний и какой он стал после перехода на новый стек?

Не замеряли. Но за полгода был почти полностью повторен функционал старого приложения + внедрены фичи, которые висели в бэклоге пару лет. ttm совершенно явно значительно сократился

Признаюсь честно, последние 3 года, где я работал - начинал именно с разгребания легаси и дурно пахнущий кода, внедрение линтеров, код ревью, тестирования, типизации, ci/cd и отсутствия документации.
В связи с этим, всегда интересен опыт компании, которая перешла с одного стека на другой.
Потому и спрашиваю, ведь переход на новый стек - это всегда вопрос компромиссов и дополнительных ресурсов. Когда говорят что "мы хотим улучшить ttm" то всегда встает вопрос "улучшили?" и метрика в виде "явно значительно сократился" немного расплывчата и не говорит вообще ни о чем, ведь мы должны продать бизнесу идею перехода на новый стек, а не "просто потому что". Из этого и спрашиваю, что переход на другой стек (который в себя вбирает обучение своих сотрудников языку и фреймворку, построению верного релизного цикла и разработки, переделка с нуля всех компонентов вью, переделка с нуля всей бизнес логики, обмазывание всего тестами, возможно описание новых интеграционных и e2e тестов, а самое главное, что стек в среднесрочной перспективе может вообще не подойти) действительно ли дороже трансформации текущего кода в котором уже есть тесты и который разрабы знают как свои 5 пальцев (рефакторинг и разделение вью и бизнес логики, что бы подготовить базу к возможной смене одного из слоев архитектуры на любую другую технологию)?
Особенно интересено, для меня, в связи с частичным уходом компании Wrike от Dart и перехода на Typescript их вью части. И да, я понимаю, что у них веб приложение, а у вас нативка. От того более интересно, с какими проблемами вы встретились как со стороны языка, так и со стороны фреймворка

Особенно интересено, для меня, в связи с частичным уходом компании Wrike от Dart и перехода на Typescript их вью части

Позволю себе продолжить вмешиваться в диалог 🙂 Wrike ушли в основном потому, что AngularDart не развивался, а Flutter for Web ещё не готов к боевому использованию, да и когда будет готов, это не совсем общего назначения фреймворк. Flutter же для мобильных устройств развивается довольно быстро.

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

Продать идею было несложно. Был проведен аудит, менеджменту сказали - чтобы отрефакторить текущее приложение до состояния вменяемости нужен год, чтобы написать то же самое с нуля нужно полгода. Но отрефакторенное все равно будет хуже, ибо стек совсем уже плохо пахнет. Плюс разработчиков новых будет сложно найти, никому не хочется ковыряться в древнем стеке с задепрекейченным кодом. Плюс кроссплатформа даст большую выгоду в плане минимизации усилий.
Менеджмент все равно боялся и говорил что-то похожее "стек в среднесрочной перспективе может вообще не подойти" . Для этого и сделали тестовые приложения на всех исследуемых технологиях и проверили, как оно.

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

Приветствую )
Не рассматривали, в нашем случае у этого варианта множество минусов и ни одного явного плюса:

  • Нужно кормить 3х условных программистов (android, ios и ++) вместо одного универсального андроид-флаттериста

  • нужно 2 раза писать UI на нативке для каждой платформы (а то и 3, для десктопа)

  • имхо, kotlin как язык, все-таки, гораздо современнее плюсов

Но вы тогда жертвуете нативными контролами и немного производительностью.

Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.