31 августа 2013 года в Минске прошел Я.Субботник, в ходе которого сотрудники минского, московского, питерского и симферопольского офисов Яндекса делились своим опытом. Для тех, кто не присутствовал на конференции, была организована онлайн-трансляция и трансляция в Твиттере по хэштегу #yasubbotnik.
Юрий рассказал, что архитектура мобильных приложений построена на клиент-сервере. Клиент посылает запрос на сервер и получает ответ, таким образом происходит взаимодействие. Основа этого взаимодействия - Pull-технология, когда мобильное приложение делает реквест на сервер, получает ответ, который анализируется, что-то записывается в базы, что-то выводится на экран.
Преимуществами такой технологии является то, что запрос инициирует клиент, это легко реализуется, и можно организовать и синхронный, и асинхронный режим всех запросов и работы. Недостатки заключаются в том, что для такого взаимодействия необходимо постоянное подключение к интернету, приложение постоянно должно находиться в активном режиме, и это сильно повышает энергопотребление мобильного телефона.
Чтобы избежать этих минусов, используется Puch-технология, главное отличие которой заключается в том, что все взаимодействие инициирует сервер.
Сервер отправляет сообщение, и после этого клиент уже думает, что ему дальше делать. Плюсы такой технологии состоят в том, что разработчики на сервере могут контролировать приложение. Также плюсом является пассивный режим работы такого приложения, что обеспечивает квазимногозадачность, что особенно актуально для iOS-приложений. Эти плюсы позволяют также снизить энергопотребление на телефонах. А большим минусом является то, что необходимо иметь сервер управления сообщениями, и реализовывать взаимодействие можно только в асинхронном режиме.
Основным требованием, которое предъявляется к Push-серверам, является способность выдерживать высокие нагрузки, потому что предполагается наличие множества телефонов с Push-клиентом и множества приложений, которые на них реагируют. Push-сервер должен обеспечивать гарантию доставки, поэтому он обязательно должен поддерживать и offline-режим. Характерной особенностью всех Push-серверов является наличие собственной платформы, и многие из них требуют лицензирования. Немаловажной также является способность серверов предоставлять API для внешних разработчиков.
В доставке Push-сообщений участвуют четыре компонента:
Backend генерирует Push-сообщения и начинает сессию взаимодействия. Он посылает сообщение на Push-сервер, который обрабатывает Push-сообщения и доставляет их клиенту. Сообщения попадают на Push-сервис, который отправляет их в какое-то из приложений.
Далее Юрий рассказал, как организована генерация сообщений бэкенда на сервисе Яндекса.
Делается пост-запрос, в котором указывается четыре параметра:
app — имя пакета
app_tokens — cписок токенов приложения (device+apk)
ttl — время жизни сообщения в секундах
data — payload нотификации в json формате
Официально Яндекс обеспечивает время хранения сообщений 30 дней. Это время можно уменьшить.
Push-клиент поставляется в виде библиотеки. Реализовать клиент можно на готовых сырцах, чтобы их было проще интегрировать (пример реализации).
Собственный сервис должен соответствовать определенным требованиям. Сервис Push-сообщений должен обеспечивать безопасное соединение, работать непрерывно и обрабатывать 100% входящих сообщений.
Сегодня служба Push-сообщений Яндекса находится в бета-тестировании, она была официально запущена 25 февраля вместе с релизом Яндекс.Store, и на данный момент предоставляется вместе с услугами магазина приложений. На сегодняшний день сервис работает на телефонах по всему миру, у него более 400 тысяч пользователей.
Алексей рассказал о ситуации, когда у разработчиков несколько приложений, и возникает необходимость связать между собой все приложения, которые работают на одном устройстве, чтобы была возможность передавать между ними какие-то данные, либо использовать общие компоненты. Проблема заключается в том, что неизвестно, что пользователь может установить себе на устройство, сколько приложений, и каких именно.
Далее речь пошла об Account Manager'е, позволяющем работать со встроенными в систему аккаунтами. Это сервис, который встраивается в систему и позволяет добавлять аккаунт на устройство:
Еще одним примером общих компонентов является сервис Push-сообщений, о котором рассказывалось ранее. При тестировании выяснилось, что на одном девайсе может появиться сразу два магазина приложений, соответственно, два Push-сервиса. Каждый из них получает свой логин, и для сервера это выглядит, как два отличных друг от друга пользователя:
Клиентское же приложение в процессе своей жизни будет взаимодействовать как с одним, так и с другим, что противоречит Push-технологии.
Решение, которое предлагает Google — это все общие компоненты, сервисы, которые предположительно будут использоваться многими приложениями, выносить в отдельный пакет и устанавливать его отдельно. И даже лучше — все компоненты в свой отдельный пакет. Решение самое простое и надежное. Но так почти никто не делает, потому что это пугает пользователей.
Когда при установке приложения оно тут же предлагает скачать еще что-то, у пользователя могут возникать неприятные ассоциации с принудительной установкой бара, или еще чем-то подобным. Преимущество Google заключается в том, что он может сам ставить какие-то приложения, даже не уведомляя об этом пользователя. Большинство так делать не могут.
В качестве одного из решений проблемы можно просто оставить все, как есть: каждое приложение будет жить само по себе, никак не зависеть от других. Плюсом будет предельная простота решения, а минусом - как в аккаунт-менеджере, в каждом приложении нужно будет заново вводить свои данные. Трудности будут при предоставлении доступа другим приложениям, например, нельзя будет обеспечить доступ из любого приложения к списку контактов. К тому же, поведение общих компонентов также нельзя будет предсказать.
По словам Алексея решением может стать выделение главного приложения, приложения-флагмана. Флагманом может быть приложение, которое несет в себе все общие компоненты.
С случае, когда трудно выделить одно главное приложение, можно все общие компоненты вставить в каждое приложение. Но все равно придется выбрать главное по какому-то критерию, которое активирует в себе все эти компоненты, и все остальные приложения будут ходить к нему пользовательскими данными. Если же главное приложение будет удалено, то выбирается новый мастер.
Плюсом многократного дублирования будет то, что в системе будет один набор компонентов, сервисов. И это наиболее интересное решение с точки зрения разработки. Минусы же заключаются в том, что это наиболее сложное решение, так как нужно обеспечить надежную синхронизацию данных между всеми приложениями. Из-за синхронизации данных возникает дополнительная нагрузка, затраты на пересылку данных, хотя и незначительные. Увеличивается размер приложений. К тому же, нужно обеспечить безопасность синхронизации.
Механизмы обмена данными между андроид-приложениями:
Общее пользовательское ID обеспечивает защищенный доступ приложений к файлам и базам данных приложений с тем же UserID. Однако у этого решения есть большой минус — связывать надо сразу, до выпуска всех приложений потому, что дальше в процессе использования общего ID очень сложно обновлять версии. Теряется доступ к старым данным, и необходимо переустанавливать приложение вручную.
Передача данных через Content-провайдеров — это второй вариант решения, стандартный механизм для предоставления доступа к данным приложения. Все резервные сервисы обращаются к главному и копируют себе его данные. Это решение хорошее, только если данные одной структуры. Минус состоит в том, что при таком решении каждое резервное приложение должно обратиться к главному и вычитать из него данные. Если в процессе что-нибудь произойдет с главным приложением и оно будет удалено, то резервные приложения останутся без новых данных. Системный баг в самом Андроиде, также является серьезной проблемой, которая была решена только в четвертой версии OS.
Было решено использовать бродкасты. Их предназначение — уведомление о случившихся событиях, но вместе с ним можно передать небольшой пакет данных.
Плюс использования бродкастов в том, что исчезает зависимость от состояния отправителя. Бродкаст примут резервные приложения и вычитают из него данные. Минус состоит в том, что размер отправляемых данных ограничен, в большинстве случаев 512 килобайтами.
Артем считает, что главным в тестирование является обратная связь. Основным свойством обратной связи является время обратной связи, потому что, чем меньше это время, тем обратная связь эффективнее. Если смотреть на обратную связь в процессе разработки, то в целом ее можно разделить на два подхода: статический и динамический анализ, куда входит классическое ручное тестирование или написание автотестов. То есть, когда уже выполняется код в каком-то окружении, и можно анализировать, как ведет себя приложение.
Статический анализ. Если расположить виды обратной связи на некоторой шкале обратной связи, на которой есть КПД и время, то КПД тем выше, чем меньше анализ занимает времени:
Компилятор, подсветка синтаксиса — это обратная связь, которая получается моментально.
Статический анализ может быть автоматическим и ручным. Автоматический анализ позволяет обеспечить понятность и простоту разрабатываемого кода. Понятность кода напрямую вытекает из следования стандартам. Каждый язык заточен под определенные задачи, соответственно, у каждого есть какой-то свой стандарт. Для Python это — РЕР 8, Perl — Perlstyle, Js — Framework depend, .NET — MSDN, Java — Oracle.
Стандарт оформления кода облегчает понимание и поддержание исходного кода при работе в команде, также помогает программисту при беглом просмотре кода дать заключение о функции и определить корректность работы без глубокого погружения в контекст.
В целом, стандарт состоит из шести правил:
Цикломатическая сложность вычисляется по формуле С = е - n + 2.
Любой код можно представить в виде блок-схемы, некоего графа переходов между состояниями. В таком случае сложность считается как число ребер этого графа, минус число вершин, плюс два. То есть, для линейной последовательности сложность равняется единице. В общем случае любой из условных операторов, который вызывает ветвление кода, добавляет по единице к сложности кода. При разработке ограничение на сложность метода — 10.
При разработке тестов ограничение на сложность — 1, то есть, тесты должны абсолютно линейными, простыми. Если тесты делать сильно сложными — есть некоторая вероятность того, что они будут более сложными, чем тестируемый код.
Ручной статический анализ (Code-review) ведет к хорошей архитектуре.
Юрий рассказал о разработке и внедрении факторов ранжирования. По его словам, качество поисковой системы можно измерять различными способами, туда входит объем поисковой базы, качество сниппетов, качество ранжирования.
Ранжирование — это выбор и упорядочивание наиболее релевантных результатов для запросов. Из огромного количества проиндексированных страниц нужно выбрать 10 лучших документов по запросу. Решать эту задачу и помогают факторы ранжирования.
Факторы ранжирования — это числовые или категориальные характеристики пары «документ-запрос», причем, можно еще включить регион пользователя или пользовательский идентификатор.
Классификация факторов ранжирования по источнику данных:
1. Текстовые (одни из самых важных)
2. Ссылочные
3. Статистические
4. Географические
5. Временные
Можно подсчитывать статистику, насколько данный запрос популярен среди пользователей даже в данное время суток, или насколько данный сайт популярен среди пользователей Яндекса по результатам поиска.
Виды факторов по месту расчета:
Функция ранжирования по набору факторов определяет оценку релевантности
Инструменты факториста:
1. C++, Python и др. (в экспериментах)
2. Платформы распределенных вычислений
3. Платформа FML
Обзор подготовила Александра Кирьянова
Комментарии