Под конец 2016 года разработано приложение для Тайного Санты под iOS. На работе не первый год уже в него играем. А тут в сентябре бизнес заказчик в лице жены объявил — «Ты ж программист, а нам на работе надо в Тайного Санту сыграть — можешь написать приложение к Новому Году для нас?» И было принято решение запилить приложение.
Далее расскажу про подробности разработки и используемые технологии.
Требования
Был составлен примерный список требований:
- Должно быть красиво
- Анимация снега
- В виду наличия форм для ввода данных
- Валидация данных
- Хранение данных
- Отправка данных
- Бизнес логика
О сроках
Они были оптимистично оценены в 1-2 месяца, а по факту в 4. Релиз был 20 декабря. Надо понимать, что это лишь в выходные пилилось. Где-то в выходные не получалось, где то писалось в будни дни. В совокупности получилось дней 20-25. Полный рабочий месяц. Можно прикинуть сколько стоила разработка приложения.
Структура навигации
Всего 8 View Controller’ов (Экранов), включая Navigation Controller.
- Стартовая страница
- Создание игры
- Добавление организатора
- Список игр
- Конкретная игра
- Добавление участника
- Конечная страница
- Создание игры
В первой реализации экран «Добавление организатора» и «Добавление участника» были объединены из-за почти идентичной визуальной составляющей, но потом были разделены из-за бизнес логики и для более чистого кода.
Архитектура
«Луковая»(слоистая) архитектура приложения была применена вместе с MVVM. В основном из-за желания попробовать binding для MVVM. Не такая тут сложная архитектура и требования, чтобы применять VIPER. Да и скорость разработки так же была важна — дедлайн в декабре.
Первые «подводные камни»
В первый месяц был готов рабочий прототип. Без анимации на всех экранах, без рандомизации, без валидации, но с отправкой и хранением данных.
Отправка писем по электронной почте
Надо сказать это не тривиальная задача для iOS клиента, учитывая, что хотелось использовать системное API, а-ля java mail api. Но не тут то было, все что мы имеем на клиенте это — MFMailComposeViewController. Можешь отправить данные в другие приложение по созданию писем. Но это и не правильный подход, если учесть, что будет приложение не только под одну платформу. Нужен сервер.
Сервер отправки писем
Свой сервер поднимать под API отправки писем не хотелось. Найдены альтернативы:
- SendGrid — платформа по маркетингу на основе отправки email
- Есть бесплатный лимит — до 12000 писем в месяц
- MailChimp — платформа по маркетингу на основе отправки email
- Есть бесплатный лимит — до 12000 писем в месяц
Все они примерно одинаковые. Был выбран SendGrid.
Но не все так гладко — нет sdk под iOS. Как быть?
Zapier
Неожиданно открыл для себя этот сервис по интеграции между веб приложениями(api). Очень в тему подошло для отправки писем. Планировалось, что данные игры будут записываться в Firebase, это в свою очередь будет тригерить отправку электронных писем.
Firebase+Zapier+Sendgrid
Но не срослось. Последнии изменения в api Firebase не позволяют отслеживать запись в таблицы. Не успели еще изменить документацию. Пробовал, писал в техподдержку, исправили в документации.
Webhook+Zapier+Sendgrid
На выручку пришел встроенный в zapier сервис по генерации вебхуков, ака api. Генерируется адрес, на который ты отправляешь json. Zapier его видит, парсит и можно с этими данными уже интегрироваться в другой сервис. Что и было сделано с Sendgrid. Дальше дело техники:
- Сформировать корректный формат для json Webhook’a
- Создать шаблон для отправки писем для Sendgrid
Анимация снега
По задумке надо было создать sprite kit particle и интегрировать в VC. По факту даже ничего создавать не пришлось. Шаблон снега уже есть + еще 6 других шаблонов.
Осталось интегрировать в VC и настроить background. Вот тут что то я не нашел адекватной документации, все либо сразу игру делают, либо сразу. Не нашел ничего адекватного для применения, в духе raywanderlich про интеграцию во VC. Только создаем Sprite Kit Game. Пришлось методом проб и ошибок.
Итак все просто. Коренной View у VC делаем SKView в storyboard. Дальше уже в жизненном цикле создавать SKScene и интегрировать в self.view. Причем сцену останавливать не надо на viewWillDissapear. Сцена в свою очередь состоит из SKNode. Вот в в ноду уже анимация и добавляет. Бэкграунд кстати тоже туда в виде отдельной ноды.
Вот анимация у нас и готова. Сделаны нужные сабклассы для минимума кода и можно уже ко всем VC где требуется снег применять.
Валидация полей
Итак текстовые поля говорите и MVVМ. Binding с KVO замечательный. Apple так не считает и сделала UITextField не KVO совместимыми. Прилетела птица обламинго. Используйте делегаты. Такую идею похоронили, но очевидно же, что нужен биндинг для форм. Android даст фору в этом направлении в несколько шагов.
Ах да, у вас же ошибки есть после валидации. Где их показывать apple? В alertView? Горите вы со своим alertView и uitextfield. Фраза про андроид.
Лирическое отступление. Вот все говорят, что технологическое отставание продуктов apple связано с их более адекватной доработкой. Допиленность софта, оптимизация. Да, возможно так и есть, но по части софта и дизайна есть явные недоработки. Год назад мне показались стандартные, базовые элементы жутко устаревшими на фоне Material Design, а если взглянуть на их стандартные приложение вроде store, то мне аж не по себе. Они не менялись со времен первого iphone. Добавили blur? Vibration effect? Я уже часто вижу floating button из MD, да чего уж там, я сам их хочу делать в приложениях. В плане дизайна приложений задает тон Android. И работы в этом направлении не видно. Swift говорите пилят? Новую MacOs? 3.5 мм выпиливают? Да вы б**ть выпилите свой старый дизайн сперва и xcode до ума доведите. Инноваторы хреновы.
Так вот где показать ошибку возле текстового поля? Есть несколько вариантов. Заморачиватся с ячейками меняющими размер не хотелось. Использовал библиотеку TextFieldValidator. Не самая свежая. С багами. Сделал pull-request. Вряд ли закоммитят в виду заброшенности. Бывает.
Ваши варианты валидации полей приветствуются в комментариях.
Хранение данных
Тут ничего особенного — Core Data + sqlite. Две сущности один-ко-многим. Игра и игроки. Все читал про MagicalRecord, мол уже не торт и не поддерживается в виду нововедений iOS 10. Вот решился попробовать. Шикарная вещь. Context и persistent store по «фен шую«. Крайне рекомендую к использованию.
Использовал Mogenerator для генерации NSManagedObject Subclass.
Отправка данных
NSUrlSession. В отдельной операции.
Составные операции
Не могу не затронуть эту тему. Это же просто прекрасно. Advanced Operations были показаны на WWDC 2015. Фактически Promise. У вас есть цепочка событий, атомарных. И каждое звено можно использовать в других цепочках. А то обычно начинают сабкласить NSOperations, они обрастают связями с другими операциями и потом уже не могут быть переиспользованы. SOLID во всей красе.
Надо отдать должное и сказать спасибо rambler и всем тем, кто разрабатывал COOperations.
Лирическое отступление. Посетив конференции гигантов отечественной и не очень IT индустрии по iOS. Яндекс, MailRu Group, Rambler&CO могу сделать небольшой обзор по подходу к организации кода и в целом поддержки проекта. Мнение чисто субъективное.
В Яндексе кто в лес, кто по дрова. Все зависит от команды. Кто то пишет тесты, кто то на них забивает. Кто-то не использует autolayout. Правят балом «эффективные менеджеры». Единобразия в подходах нет.
В мейлру прям такого как в яндексе заметить не удалось. Об этом не говорят. Они вообще мало говорят по iOS. В отличии от Android. Наработок по iOS в их гитхаб репозитории не найдено.
А вот рамблер приятно удивил. В отличии от не самого «приятного» образа по своим сервисам по сравнению с тем же яндексом и mail. По части iOS разработки они на голову впереди конкурентов. Главное, что отделяет их от конкурентов — это выработанный кровью и потом промышленный подход к созданию софта для iOS. Единообразный среди всех проектов. В результате получились прекрасные наработки по VIPER, COOperations, Generamba. Я бы их по праву назвал законодателями разработки iOS и не только в России.
Я так же скептически слушал их на конференции, всякие VIPER пиарят. Думал, что за бред, очередной пиар. Но стоит только попробовать и всех у кого сложные проекты сразу оценят все преимущества предлагаемых подходов.
В итоге получилась цепочка операций по формированию запроса к webhook’у. Оттестированных.
Бизнес логика
Из примечательного только сам алгоритм перетасовки получателей.
Тасование Фишера–Йетса/Алгоритм Саттоло
Именно так называется алгоритм на вход которого подается упорядоченный массив элементов, а на выходе уже массив со случайно расставленными элементам. Его реализация исключительно в оптимизации заключается.
Дальше просто по цепочке перебираем перетасованный массив. Все просто.
Можно усложнить 🙂 Но незачем.
Дизайн
Только на 3ей итерации зашел. Спасибо сестре 🙂 Контакты позже.
Вместо итога
Все только начинается 😉 Возможно придется переписать на VIPER. Но сперва Android версию.
С Наступающим Всех ! Чистого кода и стройной архитектуры в приложениях! Играйте в Тайного Санту!
Продолжение следует…