1. Wamba Open JSON API
Разработка и сопровождение API
в большом проекте
2. Сегодня в программе:
●
Авто-документация. Генерация HTTP-роутинга.
●
Архитектура основных компонентов API.
●
Гибкое построение форм на клиенте: FormBuilder.
●
Тестирование.
●
Версионность.
4. Документация. Поиск решения
Документация может вестись отдельно, но тогда она быстро
устаревает.
Для открытого API важнее актуальность документации.
Решение: документация должна быть в коде (phpdoc).
5. Документация в коде. Поиск решения.
NelmioApiDocBundle
<?php
/**
* @ApiDoc(
*
description="CreateanewObject",
*
input="YourType",
*
output="YourClass"
• Используется
нестандратный
phpdoc (99% не
поддерживается IDE)
*)
*/
public function postAction() {
}
• Названия классов вшиты
в строки (автоматический
рефакториг затруднен)
6. Документация в коде. Поиск решения.
Restler-API-Explorer
<?php
require_once '../../../vendor/restler.php';
use LuracastRestlerRestler;
$r = new Restler();
$r->addAPIClass('Say');
$r->handle();
• Название классов API
задается динамически (рефакторинг)
7. Документация в коде. Решение: ООП!
/**
* Возращаем список пользователей
* @http_method get
● Генерируется
автоматически IDE
(PHPStorm)
* @uri /users/:userId/
* @param FiltersBrokerAuthorized $fb
* @param RequestUserDetails $req
* @param ResponseUserDetails $rsp
* @return ResponseUserDetails
*/
public function getUserDetails(
FiltersBrokerAuthorized $fb,
RequestUserDetails $req,
ResponseUserDetails $rsp) { ...
● Имена классов (при
сборке документации)
берутся из типов
атрибутов.
19. Архитектура. Брокер Фильтров (FiltersBroker)
Проверяет доступ к сервису.
class FiltersBrokerAuthorized {
● Настоящее предсобытие
без “магических” конфигов.
public function __construct() {
if (!Profile::isAuthrorized()) {
throw new AccessDeniedException();
}
...
}
}
● Передается в сервис как
аттрибут (не потеряется).
20. Архитектура. Сервис (Service)
Бизнес-слой
class ServiceUser {
public function getUserDetails(
Защищен брокером
FiltersBrokerAuthorized $fb,
RequestUserDetails $req,
Работает с конкретной структурой
входных данных
ResponseUserDetails $rsp
) {
Отдает ответ в соотвествии с конкретной
структурой
// бизнес-логика. Использует только объекты API
// Весь код работы со сторонними библиотеками спрятан в DAO слой
}
}
22. Архитектура. Запрос (Request)
Контроль типа через методы-аксессоры
/**
* @return int
*/
public function getUserId() { return (int)$userId; }
/**
* Применяется при unit-тестировании
* @return void
*/
public function setUserId($userId) {
$this->userId = (int)$userId;
}
25. Архитектура. Ответ (Response)
Контроль выходных данных через методы-аксессоры
public function getUser() {
if (!($this->user instanceof User::getClass())) {
throw new InvalidTypeException();
}
return $this->user;
}
26. Архитектура. Ответ (Response)
Сам себя превращает в JSON
class ResponseUserDetails implements JsonSerializable
{
public function jsonSerialize() {
return [
'user' => $this->getUser(),
];
}
}
31. Функциональное тестирование. Behat
Scenario: Возвращает форму авторизации.
When I am on "/login/builder/?lang_id=ru"
Then I should see FormBuilder:
| block | field
| type
| enable |
| login | login
| Text
| true
|
| password
| Password
| true
|
|
32. Функциональное тестирование. Behat
Behat = Cucumber на PHP
Весь сложный код тестирования прячется за простым
выражением
Расширяем до +∞
•
•
•
/**
* @Then /^I should see FormBuilder:$/
*/
public function iShouldSeeFormBuilder(Table $table) {
...
}
34. Unit-тестирование. PHPUnit
•
Проверка мелких узлов системы без данных
•
Удаление зависимостей в коде
•
Помогает делать код более простым
Рецепт: Отключите автозагрузку сторонних библиотек при unitтестировании.
36. Версионность. Внешняя
Доступ к API: http://<домен-партнера>/mobile/api/v5.1.0/...
v5.1.0..1..2..
Мажорная версия API
Версия релиза клиента
Идентификатор платформы
(iOS, Android)
37. Версионность. Внутренняя
•
Нет подверсий API
•
Подверсии у стуктур данных
•
•
Переход на подверсию API связан с изучением changelog,
неодобряется бизнесом
Переход на подверсию структуры быстр и касается только
какого-то кокретного вызова API