Автодокументація мобільних веб-сервісів на прикладі Yii

    Думаю, що багато хто, особливо невеликі, компанії, при роботі з одним і тим же фреймоворком постійно пишуть якісь речі / розширення і т.п., які вирішують саме ті завдання, з якими вони стикаються найбільш часто.
 
У нашому випадку цим фреймворком є ​​Yii, а однією з найпопулярніших проблем була одночасна розробка web-сервісу для додатків iOS / Android.
 
Спочатку, як і завжди, просто розробники домовлялися між собою що і як, але якщо розробник раптом змінювався — починалися проблеми. Далі — опис вхідних / вихідних даних в wiki. При великій кількості дрібних змін виникала проблема синхронізації коду і форматів, описаних в wiki.
 
Як ми вирішили проблему — нижче.
 
 
Розробка контролера web-сервісу
Як правило, мобільний сервіс — це окремий модуль проекту. Зробили базовий модуль і базовий контролер для роботи з web-сервісом.
 
Ключові речі — нижче.
 
class VMJsonServiceController extends CController
{
   public $documentationMode = false;
   protected $request = null;

   ...
   public function init()
    {
        if ($this->documentationMode) {
            return;
        }

        if (Yii::app()->request->isPostRequest) {
            $json = CJSON::decode(file_get_contents("php://input"), false);
            if (isset($json->request)) {
                $this->request = $json->request;
            } else {
                $this->respondWithError(VMServiceResponseCode::SERVICE_ERROR, 'There is no request node');
            }
        } else {
           ...
        }
    }
   ...
    public function checkInputParameters($params = array())
    {
        if ($this->documentationMode) {
            $exception = new VMDocumentationException();
            $exception->parameters = VMObjectUtils::fromArray($params);
            throw $exception;
        }
        $this->checkObjectParameter($params, $this->request);
    } 
   ...
}

 
Сама «сіль» полягає саме в параметрі
$documentationMode
, але про це пізніше.
Тепер розглянемо приклад контролера вже з реального проекту, а не із загальної бібліотеки.
 
class UsersController extends VMJsonServiceController
{
   ...
   public function actionSignUp()
	{
		$this->checkInputParameters(array(
			'user' => array(
				'email' => 'test@test.com',
				'password' => '12345',
				'phone' => array('optional', 'value' => '+7 999 998 76 54'),
				'photos' => array('array', 'value' => array(
					'file' => base64_encode('Image'),
				)
			)
		));
		$email = $this->request->user->email;
		...
       }
	...
}

Метод checkInputParameters перевіряє, що дані прийшли в потрібному для цього методу форматі (email та password — обов'язкові, phone — необов'язковий, а photos — масив даних. Далі ми впевнені, що всі необхідні дані у нас є і з ними можна працювати.
 
Тепер, власне, про що йшла мова на початку статті — про документації. В принципі, масив в методі checkInputPаrameters — і є формат вхідних даних, і, власне, на основі нього ми й генеруємо документацію, але постійно генерувати її ручками — нецікаво і довго. Тому, змусимо модуль генерувати документацію про себе самому.
 
1. Робимо ще один контролер
За допомогою розширення
Metadata
він обходить всі контролери і Action'и, а далі рендерить наочне уявлення параметрів методу і відповіді сервісу. Зроблено це за допомогою згадуваного методу
checkInputParameters

 
class VMDocumentationController extends CController
{
   ...
   //Полный код можете посмотреть в репозитории, здесь покажу лишь один метод
   //На вход он принимает объект "контроллер" и название метода
   private function getDefinition($class, $method)
	{
		try {
			$class->{$method}();
		} catch (VMDocumentationException $e) {
			return (object) array(
				'parameters' => $e->parameters
			);
		}
	}
   ...
}

 
2. Правимо код базового модуля
 
class VMJsonServiceModule extends CWebModule {
	public function init() {
                ...
		$this->controllerMap = array(
			'documentation' => array(
				'class' => 'VMDocumentationController'
			)
		);
	}
} 

 
Що нам це дає? А те, що з одного й того ж url програміст iOS / Android має документацію для будь-якого проекту, міняється тільки baseUrl.
Як виглядає документація?
Пара скріншотів нижче.
 
У верхньому навбаре — список всіх контролерів модулів, у лівому — список всіх екшнів контролера. Необов'язкові параметри можна видалити з запиту, кнопка Call — відправить запит і покаже відповідь сервера. Тобто ви можете не писати жодного рядка коду, але протестувати роботу веб-сервісу на будь-яких вхідних даних.
 
 
 
 
 
Ну і наостанок — всі вихідні коди можете знайти тут . Місцями код жахливий, місцями дуже жахливий, багато чого з того, що є в нашій бібліотеці окрім мобільного сервісу — нафіг нікому не треба, але якщо буде що раптом запропонувати — pull-request вам на допомогу.
 
Спасибі за увагу
    
Джерело: Хабрахабр

0 коментарів

Тільки зареєстровані та авторизовані користувачі можуть залишати коментарі.