通过示例教授软件库

目前还没有读者喜欢这篇文章。
An open card catalog

Opensource.com

如今,几乎每种场合都有软件库。其中许多库设计良好且实现完善。不幸的是,几乎没有一个库的文档以允许新用户快速理解基础知识并有效地投入使用的方式呈现。

许多库使用 Doxygen 或类似的工具将其代码中的注释转换为 HTML 文档。这里的目标是解释每个函数和类是什么以及做什么。在某些情况下,这就是用户获得的全部内容。这相当于说“这是一个锤子。它用于敲钉子。这是一个钉子,它用于将木头固定在一起。”,然后期望用户能够建造房屋。对于用户学习如何根据自己的需求使用该工具而言,这根本不是正确类型的信息。

如果您幸运的话,您尝试使用的库将提供教程。教程通常解释一个类或库的某部分的基本工作原理。教程很棒,当然应该是用户学习库的整套方法的一部分,但它们有两个主要缺点。首先,创建它们非常耗时。它们通常包括大量描述性文本,每几行代码就配有图像、图表等,所有这些都需要付出巨大的努力才能制作出来。其次,教程仅涵盖单个用例。也就是说,它们演示了一个非常基本的用法,并将数十种可能的变体留给想象。

那么,如果文档和教程都不够,我建议什么呢?示例!示例和教程之间有什么区别?示例是库特定用例的快速而简单的演示。它不需要冗长的文本来描述每行代码,而只需要几句话来解释示例做什么如何做留给读者查看代码,并参考相关的教程和文档。您可能会认为涵盖每个用例是不可能的。当然,您是对的。但是,涵盖足够多的用例,让用户能够弄清楚他们想做什么,实际上是完全可以实现的。

生成这些示例的程序非常简单 - 实际上大部分工作已经完成!关键是收集它并将其存储在易于查找、易于使用的格式中。理想的过程如下。用户遇到了他们不知道如何解决的问题。这就是将演变成示例的用例。用户通过论坛、邮件列表、IRC 频道或任何其他通信方式向社区提出问题。与其简单地问一个问题(“您如何做 XYZ?”),他们应该创建一个他们尝试过的最小示例,并解释他们的代码当前做什么,以及这与他们想要做的有什么不同。在这一点上,一个示例几乎诞生了!甚至在问题解决之前,就应该将示例添加到“愿望清单”部分中的示例集合中。贡献者绝不应该回答不在愿望清单中的问题。这样做有两件事。首先,它确保问题的提出方式将有助于未来的用户以及当前的提问者。其次,它(几乎)确保答案将被整合到问题中,为社区中的每个人留下一个漂亮、整洁、可编译的示例,供大家享用。

根据我的经验,这样做在几个方面有所帮助。提问者有时会自己解决问题,因为以这种方式提出问题迫使问题被简化为关于库的一个小的、特定部分的问题。回答问题的人已经完成了大部分工作,可以花更少的时间解释问题的解决方案。邮件列表流量显着减少,因为在一段时间内(当人们仍在学习自己使用/搜索示例时),大多数问题可以通过简单地回复示例链接来回答。最终,当人们学会自己检查示例时,大多数问题都会完全消失,所有新问题都应表明需要添加示例。最后,结果是一个惊人的示例集合,用户可以使用这些示例来学习如何做他们需要做的事情。当然,如果他们不能,那么就该添加另一个示例了!

这个过程的美妙之处在于工作是众包的。更棒的是,大众有参与其中的既得利益,因为收益直接归他们所有!

我已在多个软件库中应用了这项技术。最成功的是 VTK 示例 和 ITK 示例 。在 PCL (pointclouds.org) 中,示例现在直接添加到存储库中。我创建了一个专门用于其他库(在维护者被这个想法说服期间!)甚至编程语言本身的网站。几个 Qt 示例C++ 示例Boost 示例 可用。Boost 图形库 (BGL) 一直乐于接受,我们现在正在将 BGL 示例 移至 Boost 存储库的过程中。

您还在等什么?走出去,开始示例化吧!

标签
User profile image.
我目前正在伦斯勒理工学院攻读电气工程博士学位。我的研究领域是计算机视觉和图像处理。我的研究涉及 3D 数据分析,特别是来自 LiDAR 扫描仪的数据。我从开源实践中受益匪浅,并努力继续尽我所能继续这种互惠互利!

9 条评论

David,
好主意...但为什么不将这些示例变成测试用例呢?
您当然知道测试方面至关重要,尤其是在开源产品中应用得不太好的情况下。在我提出的建议中,我看到了实现有效面向用户需求的测试方法的一种可能途径。
谢谢,我会尝试实施您的方法。

干杯,
Davide

Davide,

测试必须比示例复杂得多。示例应涵盖“正常路径”(http://en.wikipedia.org/wiki/Happy_path) 以演示代码应该如何工作。另一方面,测试必须涵盖所有路径。这意味着您将设置案例来有意引发异常、设置每个可能的参数等等。

部分原因在于,我几乎从未见过可以作为示例使用的测试。不幸的是,大多数开发人员没有看到这种巨大的区别。我会在邮件列表中看到一些问题,这些问题通过“查看测试”来回答。当您查看测试时,您会看到一段 2000 行混乱的代码,其中可能埋藏着您正在寻找的东西。示例的概念正是将演示的那一部分提取到一个独立的、可编译的代码片段中。

祝你好运!

我同意...当我发表评论时,我想到的是所有那些不习惯进行太多测试的项目。他们可以从最终用户驱动的示例的贡献中获益匪浅。

再见,
Davide

如果您将示例链接到项目的 Doxygen 配置中,您的文档甚至最终会获得指向适用类参考文档的漂亮链接。

我们为 Qt 加密架构 (QCA) 做了这件事。它具有每个方法的参考资料、示例应用程序和一些高级解释。

测试不是如何应用代码的示例。它们需要涵盖各种奇怪的输入(确保如果 API 的用户犯了错误,不会发生破坏性事件),这会掩盖使用 API 的“正确方法”。

Brad,

这是一个非常好的做法!快速 Google 搜索后,我没有找到 QCA 的示例 - 您可以发布链接吗?

我们在 ITK 项目中也做了同样的交叉链接(例如,请参阅 http://www.itk.org/Doxygen/html/classitk_1_1AddImageFilter.html)。有一个“Wiki Examples”部分。我们也反向链接 - 从示例链接到 Doxygen:http://www.itk.org/Wiki/ITK/Examples#Trigonometric_Filters(ITK 类演示列)。

我们正在开发一个完整的系统,专门用于示例显示和编辑。它比标准 wiki 更适合这项工作。敬请期待...!

概述页面位于
http://delta.affinix.com/docs/qca/

那里示例链接在页面顶部的选项卡中,但一个直接示例位于
http://delta.affinix.com/docs/qca/aes-cmac_8cpp-example.html

请注意,这种链接不需要在 doxygen 中进行任何实际工作。您只需告诉 doxygen 示例在哪里,并为选项编写一个简短的介绍,如下所示
http://websvn.kde.org/trunk/kdesupport/qca/examples/examples.doco?view=markup

这种方法的一个重要方面是,您可以将示例代码保留在主构建系统中,并确保它保持构建。也就是说,编译器将有助于确保每个示例对于 API 的当前状态都是 OK 的。当示例不起作用时,这很烦人....

非常好!正如您所提到的,定期编译示例当然至关重要。

我唯一的设计目标是这项技术无法满足普通用户添加、更新或修复示例的能力。由于这些示例位于主存储库中,因此我假设只有“开发人员”(那些已获得提交访问权限的人)才能接触它们。我想可能会有一种论点认为“只有已经证明他们了解最佳实践等的开发人员才应该编写示例。”但是,根据我的经验,编写最多示例的人是“中间人” - 那些非常擅长使用库,但没有必要对开发感兴趣,因此没有提交访问权限的人。通过真正“众包”示例,它将更多负担放在整个社区身上,并让开发人员保持关注,而无需花费大量精力编写示例。

我很高兴看到其他项目认真对待这一点,感谢 Brad 提供的链接!

我不知道这是否是 Python 社区独有的,但 Sphinx 文档工具(它与 LaTeX 的共同点比 Doxygen 更多)的普及似乎已将事情推向了另一个方向。

会有一些教程,甚至可能是一些示例(如果您真的很幸运...),但很少(如果有的话)可用的 API 文档。我经常发现自己最希望的是找到一种替代方案,而不是阅读源代码来深入了解某些文件、函数、类或方法,这些文件、函数、类或方法甚至没有获得明确的“让 autodoc 处理此问题”指令之一。

我希望 20 年前左右就有人向 man page 的作者提出这个建议...

知识共享许可协议本作品采用知识共享署名-相同方式共享 3.0 未本地化版本许可协议进行许可。
© 2025 open-source.net.cn. All rights reserved.