Сегодня мы хотим поговорить о сокровенном — у нас есть API.
Мы писали, а затем переписывали его заново на протяжении четырех лет. И за это время прошли почти все классические стадии “принятия неизбежного”. Кроме одной — четвертой. И хотим поделиться нажитыми непосильным трудом выводами, что делать и не делать, если вы решите делать свой “мощный эпиай”.
Процесс создания API uCoz иногда напоминал сюжет сериала The Knick («Больница Никербокер») — с неудачными операциями, кишками и экспериментами на живых людях.
Стадия первая – Отрицание
Вообще, API для конструкторов сайтов — редкость и сейчас. А в 2010-м такого инструмента не было еще ни у кого на рынке.
С одной стороны, определенная потребность в API была: мы видели, что люди активно гуглили “скрипты для uCoz”, получали запросы напрямую — часть пользователей хотела создавать свои дополнения и модификации. С другой стороны — и это была проблема, — в те времена все ресурсы были брошены на другие проекты.
Вопрос «быть или не быть» решился просто. API потребовалось нам самим — для запуска функции поддержки PHP в конструкторе. Мы выделили одного разработчика, и он за полгода сделал наше “начальное API” — это был get-only интерфейс, к которым можно было получать данные страниц из 11 модулей. Данные отдавались только в XML. К моменту запланированного анонса PHP мы не успевали наладить еще хотя бы добавление контента, но у API были и плюсы: с ним можно было запускать пхп-скрипты в бесплатном варианте юкоза.
В общем, мы вышли к пользователям. Получилось прям по классике:
Нас не очень-то приняли… Точнее, в основном хвалили. Но за PHP. А в самом “эпиай” люди не увидели того, что представлялось им при этом волшебном слове. В техподдержку посыпались вопросы: «Как добавлять материалы? Как редактировать? Как получить в json?» А этого всего не было.
Стадия вторая – Гнев
К вопросу, что API нужно развивать, в компании вернулись где-то через год. В приоритетах были мобильные клиенты — и мы решили писать все заново с учетом требований ребят, делавших клиенты для iOS и Android. Начальная версия осталась жить сама по себе (и даже до сих пор жива, потому что некоторые ей все же пользуются), а мы стали подбирать исполнителя на новый проект.
“Сам себе менеджер”. В ростовский офис как раз пришел толковый парень Илья: он знал Perl, на котором была написана часть старого uCoz, а когда ему по традиции предложили несколько задач, он выбрал из них работу над API. Проблема была в том, что на время парню пришлось стать самому себе менеджером.
Тут наступил гнев: «Как выяснилось в процессе, синтаксис Perl я понимал, а вот дух — нет.
Потому я долго пытался не работу, а мир лучше сделать: думал все переписать, объекты-классы-паттерны внедрить. Очень много времени ушло, чтобы освоиться с идеологией языка. И вот тогда то, что мне поначалу казалось страшным и хотелось переписать, стало казаться нормой».
К моменту просветления появился менеджер и стал требовать отчет. А была готова только отдача контента по нескольким модулям… В общем, еще раз гнев, теперь с другой стороны, — и Илью перевели на новый проект. Его версии API так и не суждено было увидеть свет.
… Между стадий …
“Идеальная обучающая задача”. К тому моменту компания пробовала открыть офис R&D в Казани. На месте нужен был носитель знания о всей системе — и появилась идея “вырастить” его через работу над API, которое затронет основные модули системы.
Так в этой истории появился Ринат:
С одной стороны, он был в меру азартен, чтобы взяться за проект (он у нас вообще немного экстремал). С другой — в работе спокоен и рассудителен: все же за плечами не только 700+ прыжков с парашютом, но и 20 лет опыта в ИТ.
Он также был знаком с Perl и имел свежий опыт работы с чужими API — интегрировал «Метрику» и GA в панель веб-мастера.
Первое, что нам пригодилось, так это его рассудительность. Ринат попросил паузу, чтобы детальнее поразбираться в запутанных “кишках” системы, — и только затем озвучить сроки и план реализации. Спустя месяц он вышел с таким предложением:
* Переписываем и дублируем часть функций чисто под API — за время создания системы в ней скопилось много старого кода. И некоторые функции, попробуй ты туда еще что-нибудь засунуть, получились бы «километровыми». Значит, нужны подчищенные двойники чисто под API.
* Используем REST — для упрощения архитектуры запроса, что поможет увеличить производительность.
* Используем Oauth 1.0a — аутентификацию, показавшуюся самой защищенной на тот момент.
* Отдаем в разных форматах — JSON, XML, Text Plain.
* Ну и: get, post, put, delete, мир, труд, май…
Третья стадия – Торг
К общему пониманию, как сделать удобно, мы вроде пришли. Но дьявол крылся в деталях и спорах.
Принципиальным вопросом стала область видимости токенов. Наша серверная система, как говорит Ринат, «это законченная инкапсулированная фиговина»: на каждом сервере крутится N юзеров, а когда место на нем кончается, берется новое железо.
Ринат хотел использовать один токен, чтобы получить доступ ко всем сайтам. “Ок, давай поговорим об этом”, — и мы позвали в скайп-чат еще коллег. Как это бывает в коллективных чатах, спорили-спорили, но к коллективному решению не пришли. А в угаре разработки тема подзабылась и вновь всплыла, когда была готова интеграция для половины модулей.
Иного варианта, как тиражировать токен, у нас не было: так появилась архитектура с одним основным авторизационным сервером — получив один токен там, его можно использовать везде.
Оформить как массив или объект? Для нас это была не проблема разряда “что правильно, а что нет”. Это была проблема деталей.
Например, мы отдаем данные в JSON — и возникает проблема с типизированными языками. Не все структуры, полученные от API, удобно распарсить — потому что увеличивается количество кода на клиентской стороне.
А ведь API ориентировано на веб-приблуды, поэтому мы прислушались к мнению разработчиков на Java и C++ и пришли к стандарту: поля отдаем в любом случае, именованные параметры дополняем кодом.
Поля и параметры. Тут торги и обсуждения шли все время реализации. Например, стоит ли выдавать пустой параметр? Поскольку мы ориентировались и под мобильную разработку с использованием API, Ринат в процессе доказал — не нужно: ведь в мобильных приложениях важен трафик.
А какие поля нужны? Тут уже мне, менеджеру проекта, нужно было искать и приводить примеры из реальной практики. Часто я брал помощь зала — опрашивал будущих пользователей API. Если присланный случай стороннего разработчика казался ценными, мы реализовывали нужные поля в самом API, чтобы люди потом не делали через костыли. А позже придумали более элегантное решение — о нем еще расскажем ниже.
Четвертая стадия –… (и о сроках)
Работа, запланированная на год, заняла почти два. В процессе возникали совсем непредвиденные сложности. Мы быстро поняли, что:
Проблемы со вторым разработчиком. По плану, после того как Ринат сделает авторизацию, к интеграции API с модулям должен был подключиться второй разработчик.
Мы расписали гугл-док, поставив модули в алфавитном порядке. Работу по ним разделили между исполнителями пополам. Определили график — один модуль в месяц от каждого. Когда пора было приступать, второй человек ушел. А мы уже делали новый проект — конструктор uKit, на который бросили основные ресурсы. С потерей второго программиста, к сроку реализации добавились почти 7 месяцев.
Проблемы с тестированием. В теории процесс задумывался таким: после сервера разработчика все уходит на альфа-сервер, а если тестер говорит “давай дальше”, то проходит бета-тестирование и обновление разливается по сотне серверов.
Но оказалось, что наши обычные тестировщики не очень подходили для работы с API — ведь они “заточены” под тестинг веб-страниц. API же — тонкая вещь. Например, когда происходило изменение внутри модуля, с которым мы интегрировались, что-то могло отвалиться — но тестировщики сначала этого не замечали (потом мы их научили).
Тогда мы открыли 4 тестовых сервера и пригласили продвинутых пользователей на самых ранних этапах. Такое крауд, а потому не очень контролируемое (ты не уверен, когда человек что-то сделает и не бросит ли), тестирование тоже сказалось на увеличении сроков.
Пятая стадия – Смирение (и выводы)
В конце концов, мы смирились с неизбежным — API, как и ремонт, можно начать, но не так-то просто закончить. Вот несколько рецептов, как организовать процесс, чтобы вам было проще.
1. Наладьте обратную связь. Больше связи.
Помимо ветки на форуме и постов в блог, т.е. публичных средств обмена комментариями, я завел на сайте с новой документацией раздел “Лаборатория”. По сути, это была форма обратной связи, где можно было обсудить свой случай в личной переписке.
О новом API мы сообщили ранним пользователям в феврале 2015-го, а процесс выкатки всех модулей на сервера завершили лишь в текущем году. Все это время мы получали через “Лабораторию” репорты, предложения и интересные случаи от пользователей (которые я в том числе использовал в «торгах» с Ринатом).
Поток обращений снизился лишь в последние два месяца
Каждый раз, получив обращение «как сделать вот это или как тут поступить», мы выделяли время и садились смотреть, а как же лучше? Иногда из этого рождались интересные истории.
2. Лично помогите тем, кто не разобрался или [Скрипт в подарок].
Бывало, сообщение из “Лаборатории” заинтересовывало настолько, что мы начинали писать скрипт сами. А затем дарили готовое решение пользователю,
В чем профит? Как говорится, «хочешь найти баг – будь багом». А если хочешь погрузиться в проект – сделай на нем как можно больше всего, чтобы проверить работоспособность и удобство. Заодно так на бирже uScript появились первые решения с использованием uAPI — авторизация через соцсети и неглючный вывод картинок в блоке рекомендованных материалов.
3. Проведите внутренний хакатон.
Как вы помните, мы испытывали недостаток в тестировщиках. Так появилась идея внутреннего хакатона для проверки продукта. Для части наших разработчиков работа с API была совершенно новой и непривычной задачей, так что мы имели возможность пристально наблюдать, как действую люди с разными скиллами.
Ринат обычно не общался напрямую с пользователями, но на хакатон к ростовским разработчикам приехал из Казани. Говорит, “за исключением троллинга, остался доволен собранными в процессе данными и критикой”.
4. Попробуйте что-нибудь автоматизировать.
Моей любимой фишкой для работы с API стало полуавтоматическое создание приложения и токена.
Изначально эта система появились из моих личных потребностей — в один момент устал тратить время на подписывание запросов при создании приложения. Тогда решил написать режим полуавтомата — чтобы ни о чем не думать, а скопировал данные — и приложение готово. Как оказалось, сейчас люди в основном пользуются полуавтоматическим решением.
5. Советуйтесь и меняйте документацию.
Изначально мы расписывали пример запроса в PHP и CURL.
Так было. Как выяснилось в процессе, CURL никто не пользовался.
Но люди спрашивали, например, в каком формате и по какому пути отправлять запрос. Стало понятно, что первая реализация была не очевидна для всех.
Мы решили, что должен быть дополнительный модуль (написан по современному, ООП), где будет автоматически генерироваться подпись для oauth. Один раз вызвал этот модуль – и далее просто пишешь путь и метод запроса.
Параллельно я прошелся по нашим программистам и спросил – документацию к каким API они считают достойным примером для подражания? Посмотрел рекомендованные примеры и с их учетом составил новую версию документации:
А в качестве теста перед публикацией, попросил коллегу из второго нашего офиса проверить соответствие работы API описаниям в документации для всех методов.
6. Реализуйте мобильность.
Во-первых, это поможет получать хорошие отзывы и расширит вашу аудиторию:
Давно была мечта о создании мобильного приложения для своего сайта. Буду изучать uAPI, чтобы наконец-таки воплотить ее в жизнь
Во-вторых, может стать ценным и новым опытом для внутренней команды. Например, на хакатоне несколько наших ребят запилили вот такое приложение:
Тут можно посмотреть код приложения
7. Не ограничивайте желания пользователей.
Вернемся к вопросу полей. Так как все случаи не предусмотришь, в итоге мы сделали конструктор запросов, с которым можно реализовать любые смелые фантазии на эту тему:
Наконец, мы пришли к тому, что API — это двустороннее движение. Сегодня с помощью uAPI можно сделать авторизацию для любого сайта, переносить материалы с uCoz и наоборот, использовать только нашу БД, но выводить данные на стороннем сайте. Чем больше юзкейсов вы вбираете в инструмент, тем дольше реализация. Но одновременно растет и область его применения.
P.S.
Весь процесс выкатки и боевого тестирования новой версии занял у нас 14 месяцев и 20 обновлений. Вот визуализация.
Бывает, после очередного обновления нам пишут: “Когда же вы его уже допишете?” Но процесс и правда очень сложно остановить (мы не шутили про ремонт). Иногда — по техническим причинам: скажем, когда апдейт системы требует изменений в API. А иногда — по творческим. Например, сейчас мы думаем: когда все интеграции с модулями закончены, почему бы не проработать темы изменения дизайна и настроек сайта по API?
ссылка на оригинал статьи https://habrahabr.ru/post/282385/
Добавить комментарий