Документация по алгоритму Ruby с AsciiDoc и Knitr
Опубликовано: 2022-03-11Каждому нетривиальному проекту нужна документация, и она должна быть интересной, с отличными пояснениями и даже иллюстрациями, чтобы ее действительно читали и использовали. Инженеры создают программное обеспечение для решения бизнес-задач, как правило, не имея большого опыта в этом конкретном бизнесе, поэтому документирование бизнеса так же важно, как и документирование программного обеспечения.
Документацию можно прикрутить постфактум, но я считаю, что написание функциональной спецификации перед кодированием очень помогает. Функциональная спецификация является источником достоверной информации для каждого члена команды в различных дисциплинах и требует высокоуровневого проектирования перед реализацией, предотвращая напрасные усилия. В этом посте я собираюсь пройти пример проекта от прототипирования до написания функциональной спецификации для примера проекта Ruby on Rails, чтобы описать, что приложение должно делать, и послужить ориентиром во время разработки. Моя цель — показать, что проекты Ruby могут использовать AsciiDoc и R для:
- С легкостью создавайте прототипы новых вычислений, алгоритмов и т. д. с помощью R
- Легко отображайте результаты R в вашей функциональной спецификации и другой письменной документации AsciiDoc.
- Свяжите его с процессом сборки, чтобы документация всегда обновлялась с учетом последних данных и алгоритмов.
Функциональная спецификация не заменяет документирование вашего API с помощью RDoc или YARD — это жизненно важное дополнение, которое можно использовать в качестве справочного материала для всех заинтересованных сторон (программистов и непрограммистов) в проекте.
Прототип
Мне нравится ловить лосося, и я хочу, чтобы я и другие могли отслеживать и делиться информацией о рыбе, которую они ловят. Ему также нужно табло, чтобы продемонстрировать лучших пользователей. Сейчас для этого используются форумы, но структурированные данные с табло намного круче.
Я мог бы сделать прототип на Ruby, но в Ruby нет наилучшей поддержки для построения графиков, поэтому я собираюсь использовать R. Использование R дает мне множество простых способов играть с математикой и визуализацией, и это перекрестно. Платформа.
# Read in some example data data <- read.csv("func_spec/example_user_data.csv") # Compute the score, weighted by base-10 log of number of reports score <- mean(data$Fish.Caught) * log(length(data$Date)) / log(10)
Всего в двух строках я прочитал несколько примеров данных и вычислил оценку, используя собственную оценку. R может сделать это и показать график с установкой vanilla, в то время как такие языки, как Ruby или Python, потребуют установки большего количества кода и дополнительных пакетов.
Документирование алгоритма
После создания моей системы подсчета очков я мог сразу перейти к кодированию. На самом деле, я мог бы пропустить прототипирование в R и просто создать прототип прямо в своем приложении Ruby on Rails. Однако прототипирование в R было быстрым и очень близким к базовой математике. Вот как я настрою документацию:
-
kingfisher/
-
Rakefile
-
doc/
-
func_spec.Radoc
-
-
Мой пример проекта Rails называется kingfisher, и я помещаю документацию в папку «doc». Я не буду вдаваться в синтаксис AsciiDoc, так как на сайте Asciidoctor есть куча отличной документации по этому вопросу, но вот как вставить диаграмму в AsciiDoc с помощью Knitr:
//begin.rcode freq_change, fig.asp=0.618, fig.width=12, fig.align="center" times_fished <- 1:50 plot(times_fished, 5 * log(times_fished) / log(10), ylab="User score when average 5 catches per trip", xlab="Number of fishing trips in the past 12 months") //end.rcode
Вставьте это в func_spec.Radoc
, запустите Knitr и AsciiDoc, и вы получите что-то вроде этого в своей документации:

Будем надеяться, что большинство разработчиков интуитивно понимают, что счет будет расти логарифмически с количеством раз, когда рыбу поймали; тем не менее, это отличный способ показать это, просто чтобы убедиться. Вокруг этой диаграммы у меня был бы текст, объясняющий, почему это желательно, чтобы разработчики, которые не ловят рыбу, могли понять, что здесь происходит. Этот пример надуман, но я использовал этот тип прототипирования и документации в прошлом для других проектов (например, финансов, оценки строительства), где результаты расчетов не всегда могут быть очевидны.
Теперь, когда партитура прототипирована и у нас есть сюжет для документации, все, что осталось, — это преобразовать входной AsciiDoc в какой-то выходной формат. Я использую несколько правил в своем Rakefile для преобразования в HTML:
require 'asciidoctor' require 'pathname' task docs: %w[doc/func_spec.html] rule '.adoc' => '.Radoc' do |t| Dir.chdir(Pathname.new(t.name).dirname) do sh "R -e 'library(knitr);knit(\"#{Pathname.new(t.source).basename}\", " + "\"#{Pathname.new(t.name).basename}\")'" end end rule '.html' => '.adoc' do |t| Dir.chdir(Pathname.new(t.name).dirname) do Asciidoctor.convert_file Pathname.new(t.source).basename, backend: :html5, to_file: true, safe: :safe end end
Теперь я могу запускать «рейк-документы» и получать документацию для создания и всегда в актуальном состоянии, даже если я изменю базовые данные или расчет оценки.
Другие решения
Для всего, что связано с Ruby on Rails, документирование с помощью AsciiDoc — отличный выбор, независимо от того, есть ли в документации пользовательская графика или нет. AsciiDoc дает вам родной для Ruby способ писать в прекрасном формате разметки. Тем не менее, есть и другие замечательные инструменты для документирования, которыми будет немного сложнее управлять и привязывать к процессу сборки для проекта Rails.
Sphinx обрабатывает reStructuredText (тоже хороший формат разметки) и может включать вывод из Matplotlib. Для проекта Python это идеально: Sphinx + Matplotlib дает вам нативный для Python способ создания красивой документации с пользовательской графикой. Однако, если вы работаете над проектом Rails, нежелательно управлять несколькими наборами зависимостей для отдельной среды только для создания вашей документации.
Существует множество других решений для создания документации, включая такие программы, как doxygen и LaTeX, которым может потребоваться больше или меньше клея, чтобы вписаться в вашу систему сборки. Если вам нужна система наподобие LaTeX, используйте ее; если у вас довольно стандартный проект Rails и у вас есть немного математики, которую нужно задокументировать, используйте AsciiDoc и R.
Заключение
Ruby и AsciiDoc составляют отличную команду, и легко добавить R в микс, чтобы сделать приятную визуализацию в вашей документации. Вы можете добавить любой пакет из экосистемы R, например ggplot2, чтобы получить красивые диаграммы в своей документации.
Исходный материал для этого поста можно найти в репозитории GitHub. На момент публикации в этом репозитории нет «настоящего» проекта, но он может появиться в будущем!
Если вы хотите продвинуться в Ruby на шаг вперед, я рекомендую изучить «Метапрограммирование с Ruby». «Метапрограммирование даже круче, чем кажется» .