Пишем документацию для Ruby on Rails проектов с помощью YARD

  • Tutorial
imageДобрый день, хабражители! Обнаружил, что на сайте нет статьи о том, как можно организовать процесс создания документации для Ruby on Rails проектов. Исправим эту проблему.

В статье будет рассказано, как с помощью гема YARDможно написать грамотную документацию к рельс проектам и автоматически сгенерировать документ, где эта документация будет представлена в презентативном виде. Пример документации можно посмотреть в коде сайта ВалиИзРашки.

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

Теория: зачем писать документацию?


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

Но лучший комментарий — это тот, который не нужно писать?

Действительно нужно писать такой понятный код, чтобы объем необходимых для понимания комментариев к нему был минимальным. Это достигается путем использования переменных с понятными названиями, предсказуемой и модульной структуры кода и так далее. Я сам раньше старался писать код, не прибегая к комментариям. Но вскоре понял, что потратить две секунды на чтение комментария к коду выгоднее, чем потратить 5-10 на чтение и понимание даже самого понятного кода. Как ни крути, а нормальным языком передать суть кода можно гораздо проще и эффективнее.

Но писать документацию — это же очень долго!

Ничего подобного. По тому методу, который тут описан, на написание документации к коду, который вы только что написали, вы будете тратить, в среднем, минуту. Эта минута с лихвой окупится, как только вы вернетесь к коду в следующий раз.

Если хотите еще аргументов в плюс документации, можете прочитать другие статьи умных людей на эту тему, например, просмотрите эту презентацию. А мы перейдем к практике.

Практика: структуризированные комментарии YARD


Сначала в своих Ruby on Rails проектах я писал комментарии без определенной структуры. Перед каждым методом вкратце писал, что там происходит. Потом понял, что было бы удобно описывать, например, параметры, который этот метод принимает; а также то, что он возвращает. Встал вопрос, почему бы везде не придерживаться единого шаблона комментариев?


Нашел гем YARD. Суть его в том, что вы пишите комментарии к своему коду, используя определенный простой синтаксис, чем-то отдаленно напоминающий xml/html. После чего вы запускаете команду, которая создаст html файлы, где будет расписан ваш код и документация к нему в удобном формате. Аналогом выступает гем RDOC, но его синтаксис показался мне более сложным.

Установим гем
$ gem install yard

либо добавим в Gemfile
 gem 'yard'

и запустим bundle install.

Возьмем примерный метод с сайта valiizrashki.ru
def try_to_evacuate(country_id)
  country = Country.find(country_id)
  if country.allows_immigrants?
    evacuate!
    true
  else
    false
  end
end

Метод определяет, можно ли иммигрировать в другую страну и эвакуируется. Так и запишем перед объявлением метода в виде комментария.
# Определяет, можно ли иммигрировать в другую страну и эвакуируется
def try_to_evacuate(country_id)
  country = Country.find(country_id)
...

Метод вызывается при нажатии по кнопке «валить». Запишем это с помощью YARD тега @note, который отвечает за различные дополнительные данные. Синтаксис выглядит так:
@имя_тега (пробел) содержимое тега

Если мы хотим несколько строк уместить в один тег, то используем табуляцию
@имя_тега
  первая строчка содержимого
  вторая строчка содержимого

Запишем информацию о месте вызова с тегом @note в том же месте, перед объявлением метода:
# Определяет, можно ли иммигрировать в другую страну и эвакуируется
# @note Вызывается при нажатии по кнопке "Валить"
def try_to_evacuate(country_id)
...

Запишем, что параметр принимает параметр с помощью тега @param. В квадратных скобках пишется тип данных этого параметра, после них — описание параметра.
# @param country_id [Integer] id страны

Запишем, что конкретно возвращает этот метод с помощью тега @return. Тут мы в квадратных скобках пишем тип данных, которые нам будут возвращены, после них — описание значения.
# @return [Boolean] получилось ли эвакуироваться

Для наглядности запишем пример использования этого метода. Сделаем это с помощью тега @example, в данном случае используя табуляцию.
# @example 
#   try_to_evacuate(2)

Также оставим ссылку на документацию модели стран с помощью тега @see, чтобы можно было туда быстро перескочить.
# @see Country

Итог получился таким:
# Определяет, можно ли иммигрировать в другую страну и эвакуируется
# @param country_id [Integer] id страны
# @note Вызывается при нажатии по кнопке "Валить"
# @example
#   try_to_evacuate(2)
# @return [Boolean] получилось ли эвакуироваться
# @see Country
def try_to_evacuate(country_id)
  country = Country.find(country_id)
  if country.allows_immigrants?
    evacuate!
    true
  else
    false
  end
end

В документации YARD есть и другие теги, которые можно изучить по этой ссылке.
Время документации!

Чтобы всё было невероятно математично, создадим файл настройки в проекте под названием .yardopts со следующим содержимым:
--private
--protected
-o doc/ruby

После этого перейдем в терминале в папку вашего проекта и запустим там команду
$ yard

Создалась папка doc/ruby. Откроем её в проводнике и откроем там _index.html. В браузере перейдем на наш метод и увидим это:

Выглядит неплохо. И ссылка на метод модели работает.

Зачем мы сделали файл настроек? Чтобы каждый раз можно было запускать генерацию документацию простой командой yard. Первые две строчки в файле отвечают за добавление приватных методов в документацию, а третья — назначает папку, в которой появится документация.

Бонус: документируем coffeescript


Для coffeescript сделали инструмент со схожим синтаксисом и функционалом под названием codo. Не вижу причин, чтобы ограничиваться документацией к руби коду и не писать её для скриптов.

Пример задокументированной функции, которая переводит число в радианы:
  # Перевод в радианы
  # @param x [Integer] число
  # @return [Integer] радианы
  rad:(x) ->
    x * Math.PI / 180

Создадим в корне проекта файл .codoopts и напишем там:
-o doc/coffee

После этого при запуске команды в корне проекта
$ codo

у нас создастся документация к coffeescript в папке doc/coffee.

Готово, вы восхитительны!

Заключение


В конце хочу отметить, что даже если вы не собирайтесь использовать автоматическую генерацию документации, то всё равно советую вам начать писать комментарии к коду в структурном виде. Это облегчит жизнь вам и вашим коллегам!

Только зарегистрированные пользователи могут участвовать в опросе. Войдите, пожалуйста.

Вы документируете свой код?
Поделиться публикацией
Комментарии 5
    +4
    Поросёнок Пётр эмигрирует из России, прихватив свой Ruby
    • НЛО прилетело и опубликовало эту надпись здесь
        –1
        не вижу ничего плохого в том, чтобы в полезной статье упомянуть свой проект [:
        0
        про рашку сайт доставил, респект и уважуха!
        Меня только до жд вокзала эвакуирует это так и надо?
          0
          Там устроено так, что он строит путь до ближайшей точки эвакуации в другие страны, руководствуясь данными маршрута с google maps. То есть, если рашка показывает, что ближе всего вокзал, значит, гугл тоже самое покажет (для автомобилей)

        Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.

        Самое читаемое