понедельник, 16 ноября 2020 г.

Ошибки которые мы обожаем повторять - API для мобильных приложений

         Есть определенные типы ошибок которые повторяются из проекта в проект. Куда бы я не пришел - там эти ошибки либо были когда-то, либо есть до сих пор. Сегодня делюсь своими размышлениями по поводу разработки API для мобильных приложений. 

            Ошибки при разработке API для мобильных приложений как правило возникают из-за того что проектируют это API - бэкэнд разработчики. Мобильная разработка - это довольно замкнутая область и люди выросшие в ней как правило мыслят довольно узко. Для них мобильное приложение это то что ставится на сматрфон клиента. Поэтому на проектирование мобильного API они как правило кладут болт. Вы нам данные дайте, а дальше мы сами разберемся. Мобильные разработчики не понимают что бэкэнд мобильного приложения - такая же его часть (не технически, а с точки зрения клиента, а значит и бизнеса).  

            А бэкэнд разаработчики не понимают специфики мобильного приложения - то что зарелизив/опубликовав его однажды - ты уже никак не сможешь его изменить. Ты не можешь "закатить" его назад.  Эта операция, довольно привычная для бэкэнд разработчика, совершенно не возможна в мире мобильной разработки. И отсутсвие этого понимания часто порождает проблемы. Итак перейдем к практической части: о чем необходимо подумать заранее чтобы потом не было мучительно больно? 

Как мы будем обновлять приложение ? 

         Предположим что мы накосячили в релизе и что-то пошло не так. Как мы можем заставить пользователя обновить его приложение (чтобы перейти на новый билд) без ошибки. Здесь как всегда два решения - очевидное и правильное. 

        Первое что приходит на ум(очевидное решение) - сделать ручку которая будет говорить - нужно нам обновляться или нет. Мобильное приложение соответсвенно должно эту ручку время от время дергать и проверять нужно обновляться или нет. Вроде все просто и должно работать. Но в чем же подвох ? Проблема в том что если дергать эту ручку редко (при старте приложения к примеру) то пользователь скорее всего много раз нарвется на баг прежде чем узнает что мобильное приложение стоит обновить. Если дергать ручку слишком часто - то это увеличивает время отклика приложения(перед совершением каких-то важных действий нам нужно проверить - а не пора ли нам обновится ? может быть там уже все поломалось)

          Более правильный подход состоит в том что при каждом запросе мы должны передавать версию мобильного приложения. И ожидать что на любой запрос может прийти ответ с ошибкой и просьбой обновится. В этом случае в мобильном API всегда есть информация - от какого клиента пришел запрос, и в случае если мы знаем что на этой версии приложения что-то сломано, мы всегда, в ответ на любой вопрос можем получить ошибку - "Версия не поддерживается, пожалуйста обновите приложение"

Как мы будем обновлять API приложения?  

Ответ на этот вопрос немного проще - всегда нужно использовать версионирование  хэндлеров мобильного АПИ. Самый простой способ - всегда включать версию  хэндлера в request path. То есть request path должен быть не просто /handler-name/, а либо /v1/handler-name/ либо /handler-name/v1/  Это требование должно быть обязательным вообще для всех API, не только для мобильного API. Но как правило это понимают только те кто ввязался по полной в SOA архитектуру.  В более простых проектах об этом как правило не задумываются.        

А что если данными сессии беда ?

Есть целый класс ошибок в мобильном приложении вызванный тем что операция логина была выполнена одной версией мобильного приложения, а дальнейшая работа с сессионными данными будет выполняться в другой версии мобильного приложения. Да, можно предложить версионировать не только хэндлеры API, а еще и структуры данных хранящихся в сессиях - но тогда ты в версиях закопаешься. Поддерживать такое решение на практике будет - ад. 

Более практичным будет предусмотреть еще одну стандартную ошибку, которую может вернуть любой хэндлер мобильного API: Please login again. То есть если мы сбросили пользователю пароль(иногда такое приходится делать) - мы можем в ответ на любой запрос к API ответить - "пожалуйста авторизуйся еще раз" и проблема решена. Либо если нужно обновить данные которые загружаются один раз при входе в мобильное приложение - мы всегда можем вернуть данный код ошибки и пользователь зайдет в мобильное приложение еще раз.

Про безопасность

Не надо надеятся что запросы мобильного приложения никто не видит. С помощью Burp Suite их можно очень легко посмотреть. И рано или поздно найдется тот кто захочет посмотреть запросы/ответы. И если там вместо сессионного токена будет что-то типа  customer_id=121212, то рано или поздно это всплывет наружу. Не надейтесь на авось - сразу используйте что-то вроде JWT token

Ну и напоследок

Не надо забывать про maintenance. Да, в идеальном мире розовых пони софт должен работать всегда, и сервера должны обновляться без всякого maintenance. Но на практике это к сожалению не так. Время от времени приходится проводить работы в продакшене которые требуют остановки бизнеса. И тут будет полезно иметь какую-то стандартную ошибку, вроде "Мы прямо сейчас не работаем, но мы скоро себя починим." Если у нас maintenance, то мы на все запросы возвращаем данную ошибку. Приложение должно ожидать получить данную ошибку в ответ на любой запрос к серверу. Если мы получаем это сообщение, мы не говорим пользователю "неизвестная ошибка, все пропало, мы все скоро умрем", а сообщаем что у нас запланированные работы и они скоро должны закончится. 

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

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