Мы все были там, последний рывок, завершение спринта, много вещей, которые нужно сделать, но не хватает времени. Часы тикают, и мы едва доберемся до финиша. Пора начинать приносить жертвы.

Да начнется игра в шахматы

Программирование похоже на игру в шахматы. Вы должны защитить самые важные части: результаты вашего кода. Как и в шахматах, первая жертва — это пешки. Конечно, они играют важную роль на доске, но давайте же, вам нужно защитить короля и выиграть игру!

Время уходит, пора жертвовать пешки или терять короля. Кто твоя самая слабая пешка? Документы конечно! Да, хорошо документировать API, чтобы тот, кто придет дальше, точно понимал, чего ожидать и что ему нужно, но давайте, время вышло, а спецификации есть в заявке Jira, Google Doc или где-то еще, где мы уже определили требования и типа написал какой-то пример Json того, как это будет правильно? Этого должно быть достаточно на данный момент, верно? Если у кого-то есть сомнения или вопросы, он/она может просто пропинговать меня, не беспокойтесь!

Теперь, если нам каким-то образом удастся не пожертвовать пешку, с ней произойдет нечто столь же ужасное. Он будет перемещаться по доске, а затем окажется перед вражеской фигурой и застрянет. Хотите знать, кто этот враг? Да, вы поняли: технический долг.

Жертвы

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

Поскольку крайний срок приближается к горизонту, следующая вещь, которой вы жертвуете, — это, конечно же, покрытие кода для этого ужасного врага, называемого Tech Debt. И в отличие от документации, этот имеет тенденцию быстрее кусать вас, поэтому сначала вам нужно разобраться с ним.

И теперь мы находимся в порочном круге, когда документация по этим невероятно сложным швейцарским карманным часам, которые мы построили, находится в нашем постоянно угасающем тайнике, называемом кратковременной памятью, и быстро заменяется постоянно растущей сложностью этого подлинного произведения искусства, которое мы постоянно релиз, потому что мы разрабатываем в AGILE. Через пару спринтов уже и не вспомнишь, что делает эта свеча зажигания в швейцарских часах! Вы, должно быть, поместили его туда по какой-то причине, верно? Ну ладно, потом разберешься. Вот для чего нужен технический долг.

О, я забыл упомянуть все время спринта, которое мы должны посвятить передаче знаний в следующих спринтах для людей, которые будут использовать API?

Реальная цена жертвы пешки

Так почему же мы должны жертвовать документацией ради общего блага своевременной доставки? Это потому что тяжело? Нет! Существует множество инструментов, которые облегчают нам задачу, например Swagger или Apiary.

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

Хуже всего то, что это выходит за рамки кода нашего приложения, поэтому мы теряем контроль над тем, что делаем, чтобы написать это объяснение, и это замедляет наш процесс. Вот почему мы жертвуем первой фигурой на доске! Потому что это замедляет нас.

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

Представьте, сколько неприятностей мы можем предотвратить, сколько времени сэкономим, если у нас будет полностью документированный API.

Но как мы это делаем? Легкий! Мы делаем это частью кода.

Я покажу вам, как просто это делается во фреймворке Hapi для NodeJS.

Сделать документацию частью кода

Hapi — довольно удивительный фреймворк, разработанный лабораториями Walmart. Он следует первому подходу к конфигурации. Из-за этого API легко документировать в коде, в Swagger, используя плагин под названием hapi-swagger и Joi.

Joi — это библиотека определения схемы и проверки для Hapi. По сути, мы можем определить и описать схему объекта, и всякий раз, когда мы получаем ее в полезной нагрузке, мы можем ее проверить. Прелесть этого в том, что мы можем полностью описать схему и ее свойства.

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

Позвольте мне показать вам, как мы строим схему с Джой:

'use strict';

const Joi = require('joi');

exports.User = {
  Joi.object().keys({
    id: Joi.number().integer().description('User   id').example(1).label('Id'),
    fullName: Joi.string().required().min(5).max(255).description('User\'s full name').example('John Doe').label('Full Name'),
    email: Joi.string().required().email().description('User\'s email address').example('[email protected]').label('Email')
  }).label('User');
};

exports.InternalServerError = {
  Joi.object().keys({
    statusCode: Joi.number().required().integer().description('HTTP Status Code').example(500).label('Status Code'),
    message: Joi.string().required().description('Error description').example('An internal error has occurred').label('Message')
  }).label('InternalServerError');
};

exports.ValidationError = Joi.object().keys({
  statusCode: Joi.number().required().description('HTTP status code').example('400'),
  error: Joi.string().required().description('Error name').example('Bad Request'),
  message: Joi.string().required().description('Description of the error').example('child "fullName" fails because ["fullName" is required]'),
  validation: Joi.object().required().description('Object describing    the validation failure')
}).label('ValidationError');

Как видите, когда мы определяем схему, мы можем указать такие значения, как описание, пример и метка, которые hapi-swagger подбирает и строит документацию. Это не замедляет нас, и, что еще лучше, это заставляет нас использовать передовой опыт!

Итак, схема — это первая часть. У нас есть полностью документированные объекты. Теперь нам нужно задокументировать действия. С Hapi мы делаем это в маршрутах, где мы пишем логику контроллера (или обработчик, как известно в Hapi).

'use strict';

const Joi = require('joi');
const SCHEMAS = require('../lib/schemas');
const routes = [];

// POST /api/users
routes.push({
  method: 'POST',
  path: '/api/users',
  config: {
    auth: 'jwt',
    handler: function(req, reply) {
    },
    description: 'Create a user',
    notes: 'Creates and returns a user in the system',
    plugins: {
      'hapi-swagger': {
        responses: {
          '201': {
            description: 'Success',
            schema: SCHEMAS.User
          },
          '400': {
            description: 'Missing/Invalid arguments',
            schema: SCHEMAS.ValidationError
          },
          '500': {
            description: 'Unknown/Unhandled error',
            schema: SCHEMAS.InternalServerError
          }
        }
      }
    },
    tags: ['api'],
    validate: {
      payload: SCHEMAS.User,
      headers: Joi.object({
        'Authorization': Joi.string().description('JWT authentication token')
      }).unknown()
    }
  }
});

module.exports = routes;

Как видите, в нашем коде много документации, объясняющей, что делает маршрут, что он ожидает в качестве полезной нагрузки и что он возвращает.

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

Внизу мы проверяем полезную нагрузку по нашей пользовательской схеме и проверяем, что заголовки аутентификации отправлены. Результаты? Посмотреть на себя:

А так как это Swagger, то на самом деле это рабочий клиент, с помощью которого мы можем тестировать наш API вживую, а не просто какие-то фиктивные значения!

Конечно, здесь есть еще код, но в основном это шаблонный код, который выходит за рамки этого поста (вы можете посмотреть пример кода здесь).

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

И это, мой друг, как Пешка стала Королевой!

Автор: Фернандо Де Вега
https://pa.linkedin.com/in/fernandodvj/en

Первоначально опубликовано на www.admios.com.