Upload
yandex
View
345
Download
0
Embed Size (px)
DESCRIPTION
Рассказ о том, как удалось портировать сервис машинного перевода на мобильное устройство, какие сопутствующие задачи пришлось решить и какие грабли поджидали на пути. Обсудим также, насколько современные мобильные приложения зависимы от наличия сети и как проектировать архитектуру так, чтобы в будущем не набить шишек при добавлении офлайн-режима.
Citation preview
перевод
Переводим без интернета
Ваня Москалёв, отдел машинного перевода
Mobile!60 %
Мобильный интернет
Процент мобильных пользователей интернета в мире в 2013 году
Web of Apps
• Приложения стали практически неразделимы от веба, стали "представлением" веб-сущности на устройстве.
• Разработчики подчас строят бизнес-логику вокруг получения данных от веб-сервиса.
Где нужен офлайн?
• В путешествиях. Например, перевод больше всего нужен там, где обычно недоступен интернет.
• При плохом подключении (метро).
• Для экономии трафика.
Я.Перевод
• 16 марта 2011 – бета-версия онлайн-сервиса Яндекс.Перевод.
• В декабре 2012 – первое мобильное приложение – для iPhone, спустя полгода Android, спустя год Windows Phone.
• Весна-лето 2014 – версия 2.0 для iOS с офлайн-переводом.
Архитектура и реализация
Как устроен Перевод
Синхронный перевод
Машинный словарьПредиктор
Озвучка
Определение языка
Используемые веб-сервисы
Клиентская логика
Translate Detect
Dictionary
Predictor Text-To-Speech
Прочее
Что нужно было сделать
• Сжать/урезать переводные модели и измерить качество.
• Портировать серверный код на устройство.
• Зарефакторить приложение.
Что было
• Система, спроектированная в краткие сроки для работы в онлайн-режиме.
• Довольно высокая связность. • Накопившиеся поправки для логики работы приложения.
Как рефакторили
• Четко определили и описали проблемную область.
• Понизили связность системы (помогла абстракция над сервисами).
• Определили, описали и реализовали юзкейсы, обложили их тестами.
Проблемная область
YTR Domain
LanguagePair
Translation
Prediction
Dictionary
Errors
Business Logic
<I> DAL
Больше абстракций!
Business Logic
Translate S. Presentation Logic
Predictor S.
Dictionary S.
Больше абстракций!
Business Logic
Presentation Logic
Web<I>
Offline
Web
Offline
Web
Offline
<I>
<I>
Проектирование логики
• Нужно было объединить и описать в спецификациях все юзкейсы.
• Был объявлен базовый класс, представляющий составной запрос (гибрид Strategy и Command).
• Написаны тесты на конкретные реализации этого класса.
Юзкейсы
• Fail-over: переход к офлайн-модели, если веб-сервис недоступен.
• Логика синхронного перевода. • "Сборка" ответов разных сервисов в составной ответ.
Загрузчик
• Один из самых важных и сложных компонентов – загрузчик.
• Две реализации: для iOS 6 и iOS 7, фоновая загрузка на iOS 7.
• Оказался многофакторным компонентом.
Выводы
• Построенная вокруг концепции абстрактных сервисов архитектура оказалась самым подходящим решением.
• Нельзя недооценивать сложность сопутствующих задач (загрузчик).
Грабли
Грабли: NSURLSession
• Сетевые задачи, созданные в фоне, всегда создаются с флагом discretionary
• Такие задачи тормозят и перестают работать если у устройства осталось мало заряда. На это жалуются пользователи ;)
Грабли: NSURLSession
NSDictionary *userInfo = @{ @"background" : @(self.context.isBackground) }; !// Сериализуем в JSON NSData *data = [NSJSONSerialization dataWithJSONObject:userInfo options:0 error:nil]; NSString *description = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]; !// Прописываем в taskDescription sessionTask.taskDescription = description;
Можно хранить метаданные в -[NSURLSessionTask taskDescription]
и при входе в приложение пересоздавать discretionary-задачи
Грабли: NSURLSession
• NSURLSession не умеет возобновлять загрузки из Content Delivery Network.
• Под капотом – If-Modified-Since и ETag.
• Если CDN отдает ETag, то возобновление загрузок сломается (каждый сервер отдает свой ETag).
Грабли: mmap
• Переводные модели состоят из нескольких файлов, каждый из которых отображается в память.
• Для перевода в одном направлении нужно ~270 МБ виртуального адресного пространства.
Грабли: mmap
File = fopen(path.c_str(), "rb"); fseek(File, 0, SEEK_END); Size = static_cast<size_t>(ftell(File)); fseek(File, 0, SEEK_SET); Data = mmap(0, Size, PROT_READ, MAP_SHARED, fileno(File), 0);
Объем виртуального адресного пространства на iOS ограничен, mmap может вернуть MAP_FAILED, если она занята другими
процессами или недоступна одним чанком.
Грабли: mmap
• На iPhone 4 / 4S система выделяет около 700 МБ пространства на девайс.
• Оптимизация: пришлось пожертовать скоростью отклика при переключении между направлениями.
Грабли: донести фичу до пользователей
Пользователи сами не вникнут в сложный функционал. Нужно как можно больше учить и объяснять.
Важно: фидбек внутри приложения
Некоторые пользователи любят жаловаться. Встроенная форма фидбека поможет быстрее разбираться с багами.
С чем мы столкнулись
• NSURLSession не дружит с CDN.
• NSURLSession оптимизируется системой.
• Ограничения виртуальной памяти. • Про фичи нужно не только рассказывать, их нужно показывать.
• In-App фидбек – очень удачное решение.
Открытые вопросы (обсудим вместе?)
• Как грамотно собирать статистику по User Experience в гибридном приложении?
• Как лучше всего осуществлять переход между онлайн и офлайн-режимом? Ручной и автоматический подходы.
Спасибо за внимание!
Ваня Москалёв iOS-разработчик, отдел машинного перевода [email protected] @ivanmoskalev