Documentación del algoritmo Ruby con AsciiDoc y Knitr
Publicado: 2022-03-11Cada proyecto no trivial necesita documentación, y debe ser atractivo con excelentes explicaciones e incluso ilustraciones, para que realmente se lea y se use. Los ingenieros crean software para resolver problemas comerciales, generalmente sin tener una amplia experiencia en ese negocio en particular, por lo que documentar el negocio es tan importante como documentar el software.
La documentación se puede agregar después del hecho, pero creo que escribir una especificación funcional antes de codificar es de gran ayuda. Una especificación funcional es una fuente de verdad para cada miembro del equipo en todas las disciplinas y obliga a un diseño de alto nivel antes de la implementación, lo que evita el desperdicio de esfuerzos. En esta publicación, repasaré un proyecto de ejemplo, desde la creación de prototipos hasta la escritura de una especificación funcional para un proyecto de Ruby on Rails de ejemplo, para describir lo que se supone que debe hacer la aplicación y ser una referencia durante el desarrollo. Mi objetivo es mostrar que los proyectos de Ruby pueden usar AsciiDoc y R para:
- Crea fácilmente prototipos de nuevos cálculos, algoritmos, etc. usando R
- Muestre fácilmente los resultados de R en su especificación funcional y otra documentación escrita de AsciiDoc
- Vincúlelo al proceso de compilación para que la documentación esté siempre actualizada con los últimos datos y algoritmos.
Una especificación funcional no es un reemplazo para documentar su API con RDoc o YARD, es una adición vital que puede usarse como referencia para todas las partes interesadas (programadores y no programadores por igual) en un proyecto.
Prototipo
Me gusta la pesca del salmón, y quiero una manera para mí y para otros de realizar un seguimiento y compartir detalles sobre los peces que están pescando. También necesita un marcador para mostrar a los mejores usuarios. En este momento, hay foros que se usan para este propósito, pero los datos estructurados con un marcador son mucho más geniales.
Podría hacer un prototipo en Ruby, pero Ruby no tiene el mejor soporte para gráficos, así que voy a usar R. Usar R me brinda muchas maneras fáciles de jugar con las matemáticas y la visualización, y es transversal. plataforma.
# 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)
En solo dos líneas, leí algunos datos de ejemplo y calculé una puntuación utilizando mi puntuación patentada. R puede hacer esto y mostrar un gráfico con una instalación básica, mientras que lenguajes como Ruby o Python requerirán más código y paquetes adicionales para instalar.
Documentando el Algoritmo
Después de hacer mi sistema de puntuación, pude pasar directamente al código. De hecho, podría haberme saltado la creación de prototipos en R y simplemente crear prototipos directamente en mi aplicación Ruby on Rails. Sin embargo, la creación de prototipos en R fue rápida y muy cercana a las matemáticas subyacentes. Así es como configuraré la documentación:
-
kingfisher/
-
Rakefile
-
doc/
-
func_spec.Radoc
-
-
Mi proyecto Rails de ejemplo se llama kingfisher, y estoy colocando la documentación en una carpeta "doc". No voy a repasar la sintaxis de AsciiDoc ya que el sitio de Asciidoctor tiene una gran cantidad de documentación excelente para eso, pero aquí le mostramos cómo insertar un gráfico en AsciiDoc con 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
Pegue eso en func_spec.Radoc
, ejecute knitr y AsciiDoc, y obtendrá algo como esto en su documentación:

Es de esperar que la mayoría de los desarrolladores entiendan intuitivamente que la puntuación aumentaría logarítmicamente con el número de veces que se pesca; aun así, esta es una excelente manera de mostrar eso solo para asegurarse. Alrededor de este gráfico, tendría algún texto explicando por qué esto es deseable para que los desarrolladores que no pescan puedan entender lo que está pasando aquí. Este ejemplo es artificial, pero he usado este tipo de creación de prototipos y documentación en el pasado para otros proyectos (por ejemplo, finanzas, estimación de construcción) donde los resultados de los cálculos pueden no ser siempre obvios.
Ahora que la partitura está prototipada y tenemos un gráfico para incluir en la documentación, todo lo que queda es transformar la entrada de AsciiDoc en algún tipo de formato de salida. Uso algunas reglas en mi Rakefile para transformar a 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
Ahora puedo ejecutar "rake docs" y obtener la documentación para construir y estar siempre actualizado, incluso si cambio los datos subyacentes o el cálculo de puntuación.
Otras soluciones
Para cualquier cosa relacionada con Ruby on Rails, la documentación con AsciiDoc es una excelente opción, ya sea que haya gráficos personalizados en la documentación o no. AsciiDoc le brinda una forma nativa de Ruby para escribir en un maravilloso formato de marcado. Dicho esto, existen otras excelentes herramientas de documentación que serán un poco más difíciles de administrar y vincular a su proceso de compilación para un proyecto de Rails.
Sphinx procesa reStructuredText (también un buen formato de marcado) y puede incorporar la salida de Matplotlib. Para un proyecto de Python, esto es perfecto: Sphinx + Matplotlib le brindan una forma nativa de Python de producir buena documentación con gráficos personalizados. Sin embargo, si está trabajando en un proyecto de Rails, es menos que deseable tener que administrar múltiples conjuntos de dependencias para un entorno separado solo para producir su documentación.
Hay toneladas de otras soluciones para producir documentación, incluidos programas como doxygen y LaTeX, que pueden requerir más o menos pegamento para adaptarse a su sistema de compilación. Si necesita un sistema como LaTeX, utilícelo; si tiene un proyecto de Rails bastante estándar y solo tiene un poco de matemática que debe documentarse, use AsciiDoc y R.
Conclusión
Ruby y AsciiDoc forman un gran equipo, y es fácil incluir R en la mezcla para hacer buenas visualizaciones en su documentación. Puede agregar cualquier paquete en el ecosistema R, como ggplot2, para obtener hermosos gráficos en su documentación.
El material de origen de esta publicación se puede encontrar en su repositorio de GitHub. A partir de la publicación, ese repositorio no contiene un proyecto "real", ¡pero puede que lo tenga en el futuro!
Si quieres hablar un paso más con Ruby, te recomiendo aprender Metaprogramming con Ruby Metaprogramming Is Even Cooler Than It Sounds .