带有 AsciiDoc 和 Knitr 的 Ruby 算法文档
已发表: 2022-03-11每个重要的项目都需要文档,并且需要有很好的解释,甚至是插图,这样才能真正被阅读和使用。 工程师制作软件是为了解决业务问题,通常在特定业务中没有丰富的经验,因此记录业务与记录软件一样重要。
事后可以添加文档,但我发现在编码之前编写功能规范很有帮助。 功能规范是跨学科团队中每个成员的真实来源,并在实施之前强制进行高级设计,防止浪费精力。 在这篇文章中,我将介绍一个示例项目,从原型设计到为示例 Ruby on Rails 项目编写功能规范,以描述应用程序应该做什么,并在开发过程中作为参考。 我的目标是展示 Ruby 项目可以使用 AsciiDoc 和 R 来:
- 使用 R 轻松制作新计算、算法等的原型
- 在您的功能规范和其他书面 AsciiDoc 文档中轻松显示 R 的结果
- 将其与构建过程联系起来,以便始终使用最新数据和算法更新文档
功能规范不能替代使用 RDoc 或 YARD 记录 API ——它是一个重要的补充,可以用作项目中所有利益相关者(程序员和非程序员等)的参考。
原型
我喜欢钓鲑鱼,我希望自己和其他人能够跟踪并分享他们所捕获的鱼的详细信息。 它还需要一个记分牌来展示顶级用户。 现在有用于此目的的论坛,但带有记分牌的结构化数据更酷。
我可以在 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 可以做到这一点并显示带有香草安装的绘图,而 Ruby 或 Python 等语言将需要安装更多代码和额外的包。
记录算法
完成评分系统后,我可以直接编写代码。 事实上,我本可以跳过 R 中的原型设计,直接在我的 Ruby on Rails 应用程序中进行原型设计。 然而,R 中的原型制作速度很快,并且非常接近底层数学。 以下是我将如何设置文档:
-
kingfisher/
-
Rakefile
-
doc/
-
func_spec.Radoc
-
-
我的示例 Rails 项目名为 kingfisher,我将文档放入“doc”文件夹。 我不打算讨论 AsciiDoc 语法,因为 Asciidoctor 网站有很多很棒的文档,但是这里是如何使用 knitr 将图表粘贴到 AsciiDoc 中的方法:
//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
现在我可以运行“rake docs”并构建文档并始终保持最新状态,即使我更改了基础数据或评分计算。
其他解决方案
对于任何涉及 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 存储库中找到。 截至发布时,该 repo 并没有一个“真正的”项目,但它可能在未来!
如果您想进一步了解 Ruby,我建议您学习使用Ruby 进行元编程 元编程比听起来更酷。