8 февраля 2019

Как горбатого приложение исправило

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

Noveo iOS application for healthy back

После оценки мы поняли, что выполнить этот заказ будет непросто: первую рабочую версию клиент ожидал уже к концу декабря (в контексте отношений с французами – до католического Рождества), а работы нужно было выполнить очень много. Во-первых, создание приложения включало в себя интеграцию с Bluetooth-устройством, которое предоставлялось командой разработки Заказчика. Это не рядовая задача для iOS-разработчиков, а потому несёт дополнительные риски. Во-вторых, приложение должно было работать как по сети, так и офлайн, а значит, необходимо было добавить функциональность хранения данных. Даже такое небольшое, но неожиданное требование документировать абсолютно все функции и типы данных сулило дополнительные трудозатраты. Предварительно оценив наши возможности, мы согласились, а затем и заказчик выбрал нас для реализации проекта, так что отступать было некуда, и в первых числах ноября мы начали планирование.

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

На старте казалось, что всё идеально: начинали три старших разработчика и один младший. Пока младший занимался реализацией независимых от проекта View-компонентов, остальные взяли задачи создания архитектурного каркаса приложения, написания отдельного API-модуля и работы с устройством по BLE-протоколу. Первая неделя прошла безупречно, а на второй подключился ещё один младший разработчик, и первый закончил со своей подготовительной работой. В этот момент имела место пробуксовка: не все компоненты были готовы (реализация БД, например, вообще была запланирована на второй спринт), но на сроках это не сильно отразилось, хоть и пришлось написать немного «лишнего» кода (были добавлены временные фиктивные объекты (mock), которые симулировали поведение этой необходимой, но отсутствующей функциональности). Считаю, что это была хорошая школа по написанию такого рода кодовых заглушек.

В дальнейшем осложнения возникали лишь при работе с самим устройством, поскольку разработка его прошивки шла параллельно во Франции, а потому приходилось держать связь с командой программистов заказчика. Несколько проблем было связано с некорректными данными для некоторых показателей датчика. Порядок байт в них отличался от задокументированного, и обнаруживать такие нестыковки получалось, только когда степень подозрения становилась максимальной. А самый трагикомичный момент мы пережили, когда нужно было реализовать обновление прошивки по воздуху, а необходимый для этого модуль DFU (device firmware update) в нашем экземпляре устройства просто-напросто отсутствовал. Задачу пришлось отложить на неделю, пока не пришла посылка с двумя новыми гаджетами.

Что же мы получили к концу декабря?

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

Теперь немного расскажу о технических решениях, которые мы использовали. В качестве архитектуры мы выбрали нашу адаптацию шаблона MVVM, работающую на основе RxSwift:

MVVM-RxSwift

При этом

  • События задаются в виде перечисления.
  • Объекты модуля не уничтожаются, пока жив View-слой.
  • Вью-модель держит координатор под видом роутер-обёртки (объект, хранящий ссылку на функцию, ответственную за обработку событий).
  • Вью-модель инжектится во View-слой при создании модуля координатором.
  • Вью-модель работает только со структурой Input и не имеет никакой информации о View-слое.
  • Input – набор Rx-сигналов о событиях, происходящих во View-слое. Output – набор Rx-сигналов, снабжающий данными View-слой.
  • Контекст – объект, предоставляющий все необходимые модулю сервисы и провайдеры данных.
  • Навигатор – объект, умеющий осуществлять UI-переходы.

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

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

Хранение данных мы реализовали с помощью фреймворка Realm. В дополнение был создан протокол (интерфейс), позволяющий преобразовывать объекты БД в экземпляры структур и обратно. За счёт этого удалось оставить конкретику использования выбранного фреймворка лишь в рамках реализации сервиса базы данных, а в остальном проекте работать только с иммутабельными структурами.

Локализацию проекта сделали в гугл-таблице, что позволило заказчику изменять строковые ресурсы, не внося собственные правки в git-репозитории. В свою очередь, команде разработки это позволило не заботиться о правильности написания текстов, а сосредоточиться на написании кода. А ещё мы воспользовались фреймворком SwiftGen, который позволяет генерировать набор абстракций для сторибордов, цветов и шрифтов проекта, а также локализованных констант, что искореняет возможность опечаток и даёт возможность проверки компилятором. В скором времени в нашем блоге появится статья, которая более подробно разберёт вопрос локализации iOS-приложения. Не пропустите!

И наконец, чтобы извлечь максимум из кодогенерации, мы подключили к проекту Sourcery для следующих целей:

  • Автоматическая генерация публичных инициализаторов структур, относящихся к отдельному API-модулю.
  • Автоматическое создание типов Realm-объектов по соответствующим им структурам.
  • Представление объекта «Контекст» в виде композиции (объединения) протоколов о владении каким-либо свойством. Благодаря этому в каждом модуле удалось максимально точно указать зависимость от внешних сервисов (композиция владения только теми сервисами, которые требуются).
  • Добавление возможности создания координатора любого модуля приложения объектом «Контекст» (при этом в создаваемый координатор вставлялись все необходимые зависимости).

Наконец, пару слов об инфраструктуре проекта. В качестве репозитория и системы управления задачами мы использовали GitLab, чей модуль в виде досок и стикеров хорошо вписался в Scrum-модель разработки, сделав работу команды наглядной и азартной. В качестве Continuous Integration использовалась среда на основе Jenkins. Тестовая спецификация и отчёты по тестированию велись в TestRails.

Конечно, как и в любом проекте, в нашем можно найти места, требующие улучшения. Написание юнит-тестов ограничилось созданием соответствующего таргета; профилировка производительности делалась лишь для пары экранов; перекрёстная проверка с помощью merge-request-ов изредка давала сбои из-за поджимающих сроков, и в девелопменте появлялись коммиты с непроверенным (но, надеюсь, рабочим) кодом. Но всё же считаю, что проект получился неплохим, и работать над его реализацией было интересно. А потому искренне желаю коммерческого успеха клиенту и жду заказа на разработку следующей версии приложения.

Здоровья Вам и Вашей спине!

Noveo iOS application for healthy back

Если вы нашли ошибку, пожалуйста, выделите фрагмент текста и нажмите Ctrl+Enter.

Читайте в нашем блоге

Сообщить об опечатке

Текст, который будет отправлен нашим редакторам: