...

четверг, 19 июня 2014 г.

Разработка мобильного ПО: проблемы интеграции


Удобные и простые решения проблем при интеграции с серверными мощностями — что делать, если возникает задача сделать два продукта, которые бы идеально стыковались, предоставляли бы друг другу консистентные данные и сами по себе работали без сбоев.


С подробностями Егор Тафланиди, Redmadrobot.


Если вы не создаёте самодостаточный продукт (а таких на мобильных платформах в действительности совсем мало), вы создаёте так называемое «бизнес»-приложение, за спиной которого обычно стоит сервер, предоставляющий актуальные данные и решающий некоторые трудоёмкие задачи.


Связка сервер/клиент настолько прочно вросла в среду мобильной разработки, что современный «умный телефон» без подключения к интернету может просто превратиться в кирпич. Некоторые библиотеки и framework'и (типа RhoMobile/RhoConnect) в своей сути строятся вокруг этой самой сервер/клиент интеграции, оставляя её глубоко «под капотом».


Существует множество подходов к реализации подобной архитектуры (два продукта, которые бы идеально стыковались, предоставляли друг другу консистентные данные и сами по себе работали без сбоев).



  • Разработку можно доверить одному человеку (или же тесно сотрудничающей команде, сидящей в одной комнате – это одно и то же). Он сам состыкует все необходимые узлы и максимально эффективно решит все возникающие проблемы интеграции.

  • Вы можете отдать реализацию сервера своим партнёрам, занимающимся разработкой серверного ПО.

  • У заказчика может быть своя команда серверных разработчиков – так часто бывает в случаях сотрудничества с банками.




Какой бы вариант вы не выбрали, к сожалению, зачастую даже чётко прописанная спецификация протокола взаимодействия сервер/клиент не может обеспечить корректную интеграцию. И перед вами возникнет простая, очевидная проблема: протоколы клиента и сервера не совпадают.

С точки зрения разработки клиента это приводит к тому, что мобильное приложение получает некорректные данные. Или же не получает их вовсе.

Если архитектурный дизайн недостаточно «пуленепробиваем», и времени на разработку было выделено мало – приложение будет «падать», отображать белиберду и вообще вести себя некрасиво.

Соответственно, не гарантируется корректность обратной связи: кто сказал, что сериализованные данные от вашего приложения будут адекватно распознаны на сервере?


Как быть?



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

Вы получаете какой-нибудь JSON, вроде этого:

{
data: {
“field1”: “value1”,
“filed2”: “value2”
}
}

Вместо того, что прописан в спецификации:



{
data: {
“entity”: {
“field1”: “value1”,
“filed2”: “value2”
}
}
}

Ценная информация – “field1” и “field2” как бы и так приходит. Так почему бы не допустить небольшую хитрость — вычитывать информацию из того, что уже предоставлено?

Я уже упоминал ключевое слово «консистентность». Дословно с английского «консистентно выполнять» = «последовательно выполнять», в том смысле что «придерживаться заданной линии поведения».


Например, если изначально какое-то явление было обозвано «phenomenon», то оно и в документации должно именоваться «phenomenon», и в исходном коде должно быть классом «Phenomenon», и в приходящих JSON’ах должно иметь ключ «phenomenon».

Когда все участники проекта используют один и тот же глоссарий – это значительно снижает риски недопонимания.

Рано или поздно кто-то из разработчиков может обнаружить несоответствие документации – и исправить. И с другой стороны системы всё обрушится.

Кроме того, на основе уже написанной документации для сервера впоследствии могут создаваться другие клиенты под другие мобильные и, возможно, desktop-платформы – и они будут натыкаться на эти же проблемы: реализация не соответствует документации.

Это приведет к тому, что система начнёт обрастать костылями и гнить изнутри.


Решения





http://apiary.io

Небольшой сервис — очень простой и довольно ограниченный в своей функциональности, но этим же и привлекательный. Он предоставляет макетную реализацию вашего API.

Вы получаете уникальный URL, на который можете натравить своё мобильное приложение. В комплекте идёт аккуратная документация по всем реализованным макетным веб-сервисам плюс типичные ответы, которые от этих веб-сервисов должны приходить.


Например, вам необходим сервер, который будет отдавать набор каких-то сущностей Entity. Список пользователей, список ресторанов, список банкоматов – не важно.

У каждой сущности есть свой ID, по которому сервер должен уметь предоставлять подробную информацию о данной сущности.

Плюс API должен отдельно предоставлять, скажем, служебную информацию – поле timestamp – время обновления сущности с заданным ID.


Итак, мы предполагаем, что у нас есть:


Адрес



Сервис 1:




  • на GET-запрос отдаёт набор сущностей

  • на POST-запрос отдаёт подтверждение добавления новой сущности




Сервис 2:




  • на GET-запрос отдаёт подробную информацию о сущности;

  • на UPDATE-запрос отдаёт подтверждение обновления сущности


(небольшая оговорка: к сожалению, apiary.io не позволяет реализовать полноценный REST, поэтому отдавать на UPDATE-запрос обновлённую сущность вряд ли получится).
Сервис 3:




  • на GET-запрос отдаёт дату последнего обновления сущности.




И т.д.

Пример подобного «сервера» находится здесь.


Описание макетных сервисов крайне простое и носит декларативный характер.

При создании нового макетного API вам сразу предоставляется пример:



FORMAT: 1A
HOST: http://ift.tt/1lBRnbM

# application
Notes API is a *short texts saving* service similar to its physical paper presence on your table.

# Group Notes
Notes related resources of the **Notes API**

## Notes Collection [/notes]
### List all Notes [GET]
+ Response 200 (application/json)

[{
"id": 1, "title": "Jogging in park"
}, {
"id": 2, "title": "Pick-up posters from post-office"
}]

### Create a Note [POST]
+ Request (application/json)

{ "title": "Buy cheese and bread for breakfast." }

+ Response 201 (application/json)

{ "id": 3, "title": "Buy cheese and bread for breakfast." }

Данный код описывает работу сервиса, отвечающего на GET- и POST-запросы.


И сам сервис apiary.io может выступать в роли прокси. Посредством одного переключателя вы можете перенаправить весь трафик, приходящий на макетный сервер, на «боевой» back-end, не меняя ничего в исходном коде клиента.



Казалось бы, всё хорошо, всё красиво, сервис позволяет команде работать без блокировки процесса, предоставляет удобный скриптовый язык…

Проблема в том, что особой логикой он, увы, не обладает.

Можно сымитировать возвращение сущности в зависимости от её ID, но в любом случае это будет конечный автомат, не способный сколько-нибудь анализировать ситуацию – у него слегка другое предназначение.




http://www.soapui.org

Если вам необходимо копнуть чуть глубже – не беда. Всегда есть старый, проверенный Soap UI.


SoapUI является мультизадачным комбайном, изначально предназначенным и нацеленным на тестирование SOAP- и REST-сервисов в автоматическом режиме. Кроме всего прочего, он сам умеет выступать в роли соответствующего сервера и предоставлять макетные данные.


Инструкция к действию:

Создаём проект и выпиливаем из него всё лишнее


Создаём новый макетный REST-сервис



Добавляем action



Пусть возвращает список Entities



Добавляем макетные данные





Пусть сервис возвращает этот список только по наличию авторизационного ключа.



Добавляем ответ для «неавторизованного» пользователя



Переключаем Dispatch-режим в состояние “SCRIPT” и копируем один из приведенных примеров проверки параметров запроса



Запускаем (предварительно проверив порт в настройках сервиса; по умолчанию – 8080)



Проверяем





Всё, макетный сервер готов.


Выводы



Естественно, приведенный сервис – не единственный, и существует ряд его аналогов, типа mockable.io, предоставляющих схожий функционал.

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

Действительно функциональных и удобных сервисов для создания макетных API – не так уж и много.

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

Так, apiary.io вполне может быть задействован при создании прототипа или proof-of-concept-решения, а по мере эволюционирования проекта уже можно думать о последующем переезде на более продвинутые сервисы с логикой, скриптами…

А там глядишь – уже и боевой сервер готов.

Отдельной статьёй, конечно, идут BAAS-сервера, но это уже слегка другая история.


А как вы решаете проблемы интеграции?


This entry passed through the Full-Text RSS service — if this is your content and you're reading it on someone else's site, please read the FAQ at http://ift.tt/jcXqJW.


Комментариев нет:

Отправить комментарий