Недавно, (хотя уже в прошлом году) было опубликовано приложение Шереметьево (ссылка), которое было продемонстрировано на выставке «Транспорт России». Так как я был конструктором этого приложения, и Шереметьево попросило выделить разработчика для присутствия на выставке и для консультации в трудных вопросах, я согласился с большим удовольствием – не каждый день удается побывать на таких выставках (а тут еще и за счет рабочих дней :).
На самой выставке был проявлен живой интерес к приложению и пришлось очень много общаться и рассказывать. Спрашивали по теме и не по теме. Неожиданно много пришлось рассказывать про сам Windows Phone, который некоторым был в новинку. Меня довольно часто принимали за сотрудника Шереметьево, а те, кто узнавали, что я один из разработчиков этого приложения интересовались и самой разработкой. Также я получал от друзей и коллег просьбы рассказать о разработке приложения Шереметьево и теперь, когда Аплана разрешила рассказать о разработке этого приложения, решил опубликовать статью с ответами на самые часто задаваемые вопросы.
Проектирование приложения
Конечно же проектирование приложения является важным моментом для дальнейшего планирования архитектуры и объема работы приложения. Прототип позволяет выделить необходимую функциональность и требования к приложению и позволяет избежать многих будущих ошибок. В первую очередь мы проработали навигацию и дизайн приложения. Например, один из первоначальных вариантов карты приложения выглядел следующим образом
рис. Design Map (картинка кликабельная (pdf))
Первоначальный дизайн впоследствии тоже подвергся незначительным изменениям.
рис. Visual Design (картинка кликабельная (pdf))
Конечно при этом у всех есть понимания, что это не строгая документация со всеми нюансами, а всего лишь примерная версия. Такие прототипы существенно упрощают понимание объема работ, который предстоит и позволяет заказчику примерно увидеть, что будет в конечном итоге. После согласования с заказчиком окончательного проекта мы приступили к написанию непосредственно самого приложения и бекенда.
Разработка клиентского приложения.
Ключевой функциональностью приложения является табло рейсов. Этой функции была отведена первая вкладка элемента Panorama на первой странице.
По умолчанию на главной странице в первой вкладке отображаются всего два тайла с переходом на страницу с табло, где было осуществлено разделение рейсов по прилетам и вылетам в элементе Pivot.
Соответственно на этой странице с табло предусмотрен поиск по номеру рейса или названию города. При выборе определенного рейса добавлена возможность «закрепления» этого рейса на главной странице приложения и на рабочем столе с возможностью закрепления вторичного тайла и возможностью подписаться на оповещения об изменениях статуса. При этом на вторичных тайлах можно отслеживать изменения статуса рейса:
Также при реализации функциональности отписки от изменения статуса рейса мы столкнулись с проблемой. Хотели реализовать изначально простую функциональность: закрепил тайл – подписался на уведомления изменения статуса рейса с получением Toast нотификаций, открепил тайл – отписался от получения уведомлений статуса рейса. Решение было вполне логичным, с учетом того что Toast нотификация зачастую почти бесполезна, так как высока вероятность, что пользователь просто пропустит ее, тем более в шумной обстановке.
Реализовать такое поведение в чистом виде помешало несколько обстоятельств:
1. Обязательное требование гайдлайна – Нельзя спамить пользователя Toast нотификацией если он на это не подписался явно.
2. После удаления вторичного тайла с рабочего стола, без запуска приложения нет возможности узнать, был ли удален тайл, соответственно отписать пользователя.
В конечном итоге мы остановились на чуть более сложном варианте:
При закреплении рейса предлагается выбор — подписаться на изменения рейса или нет. В случае подтверждения закрепляется вторичный тайл на рабочем столе и на главном экране и приложение подписывается на получение Tile и Toast уведомлений. В случае отказа только закрепляется вторичный тайл на рабочем столе без возможности обновления.
Пожалуй, одним из самых сложных компонентов приложения оказалась карта аэропорта с картами по терминалам на каждом этаже с картой объектов POI (Point Of Interest, далее в статье я буду использовать термин POI, ставший у нас рабочим термином для обозначения объектов на карте). Идея заключалась в том, что на карте отображаются POI и по клику на них мы можем переходить на страницу деталей этого POI и наоборот из страницы деталей POI можно переходить на карту где расположено это POI. При этом на самой карте должна быть возможность фильтрации отображаемых POI по категориям.
В приложении также требовалaсь возможность фильтрации POI на карте по категориям, в связи с чем возникло несколько проблем. В частности, оптимизация используемой памяти.
В первоначальном варианте у нас не было никакой информации о конкретных координатах POI (кроме информации о терминале и этаже) и соответственно не было связей между точками на карте и самими POI. Из-за этого переход на карту со страницы деталей POI пришлось сократить до открытия карты того терминала и этажа, на котором расположено POI.
В связи с этим я принял решение держать несколько отдельных слоев с нарисованными иконками POI для каждой категории, а перед отображением на карте слои из выбранных категорий склеиваются в одну картинку.
Позже, когда мы все-таки получили информацию по POI с координатами, я переписал работу со слоями таким образом, что иконки POI с выбранными категориями рисуются на основной подложке в момент отображения карты.
Вначале я боялся, что склеивание карты в конечную картинку будет затратной по ресурсам и медленной операцией. Однако это решение оказалось более эффективным, нежели отображение нескольких слоев друг на друге (т.к. не хватало памяти) и позволило избавиться от лагов даже в тех случаях, когда памяти было достаточно (накладывание большого числа иконок на подложку).
Следующим шагом планировал переписать движок с использованием тайлов для более эффективного использования памяти, что может дать возможность работать с картами еще большего разрешения. Сейчас максимальный размер 2000 х 2000 пикселей. Однако, судя по отзывам, для пользователей сейчас куда более актуальна поддержка местоположения и более полная информация по POI, нежели карты более высокого разрешения.
Помимо табло и карт, в приложении еще много разной информации о POI, данные по авиалиниям, правила для пассажиров, справочная информация. Предполагается, что обновляться она будет крайне редко, а систему управления контентом планировали разработать только к релизу более поздних версий. Поэтому мы решили зашить такие данные внутри приложения в виде файлов в формате JSON, в котором и предполагалось получать их из сети.
Разработка серверной части приложения
К моменту когда мы приступили к разработке приложения у нас не было точной информации об инфраструктуре серверной части. Поэтому я принял решение разработать обычное серверное приложение на ASP.NET. Предполагалось, что это будет обычное поставляемое решение которое будет развернуто специалистами Шереметьево на отдельно выделенных серверах.
Но в ходе разработки появились новые требования от заказчика: должна быть возможность отдать поддержку системы на аутсорс.
Однако внутренние стандарты аэропортов содержат особые требования по безопасности и любые изменения в инфраструктуре должны пройти множество согласований. Именно ‘благодаря’ этим требованиям нельзя предоставить доступ напрямую к внутренней инфраструктуре аэропорта. API для подключения мобильных устройств к серверу не было предусмотрено изначально (по сути мы и разрабатывали это API).
В итоге остановились на Azure как наиболее безопасном решении (по сравнению с
Текущая архитектура серверной части в упрощенном виде выглядит следующим образом.
В новой версии отличие только в том, что сервер работает не с конкретным WNS для WP, а сразу с для несколько платформ и к REST API подключаются Android, IPhone приложения.
Еще одним преимуществом использования Azure стало автоматическое управление количеством экземпляров сервиса в зависимости от нагрузки. Т.е. при повышении нагрузки на сервер запускаются дополнительные экземпляры, при этом было введено ограничение на максимальное количество экземпляров для избежания незапланированных расходов. Серверная часть самостоятельно обеспечивает свою работу таким образом, чтобы максимально сэкономить на своем содержании и при этом обеспечить бесперебойную работу без необходимости мониторить работу сервера 24 часа в сутки.
Так как в присылаемой нам информации о рейсах есть только текущее состояние, работа серверной части заключается в анализе регулярно получаемой информации о рейсах, сопоставление с предыдущими данными, обновление активного кеша и отправка нотификаций по тем рейсам, на уведомления по которые подписались пользователи
.
Особо интересно отметить то, что сейчас в нашем приложении новую информацию можно увидеть немного раньше чем на табло в самом аэропорту или на сайте.
Почему Windows Phone?
Пожалуй этот вопрос был одним из самых популярных вопросов на выставке. Особенно на фоне того что мало у кого из посетителей был WP. Присутствие на подобных выставках позволяет видеть насколько сильно может отличается предпочтения моего круга общения с предпочтением других «кругов». Если не большинство, то точно половина моих знакомых и друзей которые пользуются смартфонами, пользуются Windows Phone (и признаться, для некоторых я сыграл определенную роль в выборе). На выставке же, несмотря на то что в России по разным статистикам лидирует Android, мне показалось что, IPhone-девайсов было подавляющее большинство, а те кто пользовались Android в основном пользовались Samsung Galaxy что в итоге делало этот вопрос особенно актуальным.
Небольшое отступление немного не в тему: Для моих друзей не секрет что я хоть и занимаюсь разработкой под все платформы, мое предпочтение отдано Windows Phone. Часть людей подходили просто пощупать WP8 девайсы, любезно предоставленные компанией Nokia, куда мы установили приложения, и соответственно я с удовольствием отвечал не только на вопросы о приложении но и на вопросы о самой платформе WP. На удивление многие из текущих владельцев Apple техники, которые вживую щупали Windows Phone на нашем стенде отозвались крайне положительно. Больше всего, как мне показалось, людей подкупали живые тайлы с актуальной информацией и сама возможность закрепления вторичного тайла (в нашем случае возможность закрепления живых тайлов отдельно для рейсов). Был лишь один человек который достаточно жестко протроллил меня на тему отстойности Windows Phone и железа, и что круче железа и ОС чем у IPhone быть не может (его не убедил даже мой личный Lumia 920, который я с удовольствием демонстрировал). Я не стал вступать в полемику с этим человеком и убеждать что WP тоже не плох – на выставке я показывал возможности нашего приложения и платформы Windows Phone, а выводы каждый делал сам.
Перед началом разработки мы должны были выбрать одну платформу и окончательный вариант приложения портировать на другие платформы. Конечно, выбор платформы Windows Phone был сделан не из наших личных пристрастий (к слову сказать наш директор тоже пользуется WP как и я), и не столько из-за того что сейчас эта платформа быстро набирает популярность, сколько из-за того, что это самая простая и быстрая платформа для разработки. Как и предполагали, в конечном итоге это оказалось наиболее удачным решением, так как в процессе разработки мы вносили множество кардинальных изменений в проект. Приходилось менять практически все – как UI приложения, так и логику во всех трех приложениях (клиентская, серверная часть и утилиты).
Использование одной платформы (.NET) для серверной, клиентской частей и специально разработанных утилит для работы с контентом позволило относительно дешево вносить изменения. Зачастую приходилось вносить изменения всего в одну сборку с моделями для всех трех типов проектов (Отдельное спасибо за Portable Library, который теперь стал частью VS2012 и предоставлялся в виде расширения для VS2010). Любые изменения в модели данных сразу же оказывались во всех проектах.
Трудности встретившиеся в работе.
На этапе разработки
Как я уже писал выше, больше всего провозился с картами. Это было одной из самых тяжелых компонент для разработки, к которому требования менялись несколько раз.
LongListSelector уже не раз подводил и даже в последнем обновлении не исправили багу отрисовки картинок, который можно наблюдать, если вместо привычных букв в заголовках использовать тайлы. В конечном итоге после некоторых попыток исправить эту багу своими силами, решили заменить на более качественный Telerik-овский аналог, который был избавлен от этого бага.
Контролы Telerik просто шикарны, но я стараюсь максимально избегать платных продуктов из-за особенностей сопровождения.
Так же в этом проекте я использовал свой проект с открытым кодом WPExtensions, в частности, AdvancedApplicationBar, который значительно упростил работу с ApplicationBar. Например, в деталях POI необходимо было скрывать те кнопки в AppBar, для которых не было информации (например, позвонить или открыть веб-сайт и т.п.), а в стандартном AppBar свойство Visibility отсутствует. Соответственно с помощью этой библиотеки так же удобно было использовать MVVM с ApplicationBar. К сожалению в версии, которая лежит в nuget есть несколько багов с некрасивым передергиванием AppBar. В проекте использовал более свежую версию, исправленную от этих недостатков, но не достаточно хорошо проработанную с точки зрения качества кода для выкладки в nuget.
Организационные проблемы
Как и любая другая крупная компания, Шереметьево обладает определенным бюрократическим механизмом. Конечно же, в данном случае это более чем оправдано – ведь на кону безопасность пассажиров и вся деятельность компании строго регламентируется. Шереметьево – это не страртап, который может очень быстро менять структуру, ответственности людей и самих людей в зависимости от меняющихся внешних требований. С другой стороны это вылилось в то что порой приходилось ожидать недели для получения даже простейших данных или согласования незначительных изменений. Надо отдать должное коллегам из Шереметьево, которые прилагали немало усилий, добывая необходимые для приложения данные и проводя согласования изменений через разные отделы внутри компании, без чьих усилий мы бы не выпустили приложение в прошлом году.
От некоторых функций все-таки пришлось отказаться в пользу следующих обновлений. К примеру, на первом этапе нам не удалось раздобыть GPS привязки к картам и мы так и не успели сделать позиционирование внутри помещений. Сейчас это одно из приоритетных обновлений.
Проблемы сертификации
Сертификация тоже прошла не без неожиданностей.
В нашем случае приложение не прошло сертификацию из-за того, что в приложении «задеваются религиозные чувства в Китае». Чем же именно китайцем не угодил контент, выяснить так и не удалось Таким образом, мы потеряли еще 5 дней на перепубликацию приложения, на всякий случай исключив все страны с ужесточенными требованиями к контенту.
В будущих версиях надеемся пройти сертификацию и в Китае, а разработчикам могу только посоветовать, что если приложение необходимо выпустить пораньше, то при первой публикации не надо указывать страны с повышенными требованиями к контенту, даже если на 100% уверены, что никаких нарушений нет.
Автор: Atreides07