科学软件十条简单编程原则


科学,尤其是生物学,越来越依赖软件工具来实现研究。但是,如果您是生物学家,则可能未接受过软件开发最佳实践方面的培训。由于缺乏培训,科学软件通常只有极少甚至不存在的文档,使得研究人员的生活比他们需要的更加困难。
我提出了这10条简单的规则,希望通过将软件工程最佳实践应用于研究工具文档,您可以创建最具可用性和影响力的软件。

规则1:在编码时编写注释
注释是软件文档中最重要的一个方面。在一天结束时,人们(包括您自己)需要能够阅读和理解您的源代码。好的变量和函数名称可以极大地提高可读性,尽管它们不能完全替代注释。虽然你的代码在没有评论的情况下可能会很明显,但其他读者可能不会那么幸运。实际上,在您转移到另一个项目之后,您自己可能甚至无法理解您自己的代码。将注释解释视为您的实验室笔记本:它们可以帮助您在事后很久就记住您的思路。
编写注释的最佳方法是在编写代码时执行此操作。这样你永远不会忘记你的思维过程是什么,你永远不会忘记回去写你自己承诺的评论(我们都对此感到内疚)。现代集成开发环境(IDE)通常会在您编写代码时自动生成文档字符串,从而消除了必须记住编写注释的负担。反对彻底的代码评论的一个常见论点是它会减慢你的速度。事实上,良好的评论可以帮助您更快地编写代码,因为您可以更好地了解您的软件。当您遇到错误时,这种理解特别有用,因为您可以将您的代码正在做的事情与您的评论所说的应该做的事情进行比较。
正确的代码评论既是一门艺术,也是一门科学。如果您写的评论太少,人们将无法弄清楚您的代码在做什么。写得太多,读者会在评论的海洋中迷失。作为指导原则,旨在编写读者可以通过阅读您的评论来理解的代码。


规则2:包含示例(以及大量示例)
说到软件文档,示例优先于说明。除简单说明外,在文档中包含示例有几个重要原因。
Keras是一个机器学习框架,截至撰写本文时,它有35个完整的示例脚本(github.com/keras-team/keras/tree/master/examples),带有自述文件(详见规则4),解释每个示例演示。尽管您没有义务提供这么多示例,但请花时间至少编写一些示例来展示您软件的主要功能。您甚至可以使您的示例作为单元测试执行双重任务(反之亦然),从而在提供指令时验证功能。

规则3:包括快速入门指南
尽快实现从想法到实验再到结果,可以促进科学的进步。如果人们花了很长时间来弄清楚如何使用你的软件,他们可能会放弃。相反,如果人们可以立即开始使用您的工具,他们就更有可能将其作为研究的一部分。因此,必须包含一个快速入门指南,旨在帮助人们尽快开始使用您的软件。

例如,让我们看一下TPOT机器学习工具的快速入门指南:它有一个显示软件功能的动画图形图像文件(GIF),解释它如何工作的图表,以及一个最小的代码存根,非常适合复制粘贴到你自己的项目。要判断您的快速入门指南是否按预期工作,请将其显示给未使用过您软件的人,看看他们是否可以找出如何开始使用它。考虑一下你的快速入门指南,作为你项目的约会档案:它应该展示它的优势,给人一种感觉,并诱使人们选择它。

规则4:包含带有基本信息的README文件
您的README文件就像是项目的主页。在GitHub,Bitbucket和GitLab等代码共享站点上,您的README文件显示在项目的主页面上。README文件应该可以从原始源轻松读取,因此人类可读的标记语言(如Markdown或reStructuredText(或纯文本))比不太可读的格式(如超文本标记语言(HTML))更可取。事实上,代码共享站点通常会在您的存储库页面上呈现您的标记语言,为您提供两全其美的优势。利用这种免费托管是很难得到的,而且托管的README页面在您的存储库中,这使得安排更加甜蜜。

一个好的经验法则是假设README中包含的信息将是用户阅读的唯一文档。因此,您的自述文件应包括如何安装和配置软件,在何处查找完整文档,在何处发布许可证,如何测试以确保功能以及确认。此外,您应该在自述文件中包含快速入门指南(如规则3中所述)。

通常,自述文件顶部会包含徽章,这些徽章在呈现时会显示软件的状态。徽章的一个常见来源是shields.io,它可以为您的项目动态生成徽章。常见徽章包括显示自动化测试是否正在传递的徽章(例如来自travis-ci.org的徽章),测试覆盖的代码百分比,文档是否是最新的等等。虽然没有必要,但这些徽章会使您对项目质量充满信心,并且一目了然地传达重要信息,因此强烈建议使用。

规则5:包含命令行界面的帮助命令
许多科学软件工具都有命令行界面(CLI)。没有图形界面可以节省开发时间并使软件更加灵活。然而,CLI软件面临的一个挑战是很难弄清楚如何使用。记录CLI的最佳方法是使用“帮助”命令打印出如何使用该软件。这样,用户无需尝试查找文档即可完成基本任务。它应该包括用法(如何使用命令),子命令(如果适用),选项和/或参数,环境变量(如果适用),甚至可能包括一些示例(规则2再次发生!)。
帮助命令可能很难制作并且难以维护,但幸运的是有许多软件包可以为您完成。在Python中,click(click.pocoo.org)等软件不仅可以提供帮助命令,还可以帮助您创建界面,从而节省您的时间和精力。
良好的CLI的一个例子是Magic-BLAST中包含的CLI。它有一个简短的帮助命令“-h”,它提供有关工具是什么以及如何使用它的基本信息。它还包括有关如何访问完整帮助文档的说明,其中包括每个选项的列表以及选项参数的说明及其作用。这样的安排特别好,因为它只需要很少的努力就可以通过简短的帮助页面找到最有用的信息,从而减少信息过载并通过提供如何访问完整CLI参考的提醒来减少使用软件的认知负担。

规则6:版本控制您的文档
首先,您应该将文档与其他文件一起保存在Git存储库中。这使您可以在项目历史中的任何位置查看文档。Read the Docs(readthedocs.org)和Zenodo(zenodo.org)等服务使这一过程变得更加容易,因为每次制作软件的新版本时,它们都会存档文档的完整渲染版本。
为了说明为什么这是一个如此重要的规则,请考虑如果更改软件新版本中的默认设置会发生什么。当以前版本的用户查看您的文档时,他们将看到与他们已安装的版本不兼容的文档。更糟糕的是,因为您更改了默认设置,软件可能会莫名其妙地失败。这可能会让用户感到非常恼火(如果软件适用于任务关键型应用程序,甚至会很危险),因此对文档使用版本控制尤为重要。文档中的更改日志可以使此任务更容易。如果您正在使用提供信息的提交消息,那么创建更改日志在最坏的情况下是一项简单的任务,而且最多也是一项微不足道的任务。

作为生物信息学库的一个例子,它在控制文档的版本方面做得特别好,请查看khmer,它有一个包含新功能的彻底更改日志,修复了错误(由它们是否与用户或开发人员相关),已知问题,以及发布的贡献者列表。此外,文档网站的早期版本可以轻松访问并标记清楚。通过提供此信息,作者确保任何版本软件的用户都可以获得正确版本的文档,查看项目中发生的情况,并确保他们了解其版本的任何问题。
如果您对此规则不以为然,请清楚说明您的文档适用于哪个版本的软件,并保留以前版本的文档 - 您的用户将会感谢您。

规则7:完整记录您的应用程序编程接口
您的应用程序编程接口(API)是使用您的软件的人与您的代码交互的方式。它必须在源代码中完整记录。老实说,可能没人会读你的整个API文档,这很好。API文档的目标是防止用户不得不深入挖掘您的源代码以使用您的API。至少,每个函数都应记录其输入和输入类型,记录其输出和输出类型,以及记录的任何错误。对象应该描述它们的方法和属性。最好为API文档使用一致的样式。

Google风格指南(google.github.io/styleguide)有许多语言的API文档建议,如Python,Java,R,C ++和Shell。您花了很多时间开发API; 不要告诉用户如何使用它,不要浪费时间。

规则8:使用自动化文档工具
最好的文档类型是自己编写的文档。虽然没有任何软件包可以为您完成所有文档,但有些工具可以解决大部分问题,例如建立网站,使其与代码保持同步,以及将其呈现为可移植文档文件( PDF)。

R的Sphinx(sphinx-doc.org),perldoc,Javadoc和Roxygen(https://github.com/klutometis/roxygen)等软件可以生成文档,甚至可以阅读您的注释并使用它们生成详细的API文档。

尽管Sphinx是为了托管Python的文档而开发的,但它与语言无关,这意味着它可以适用于您的项目所使用的任何语言。同样,Doxygen(doxygen.nl)和MkDocs(mkdocs.org))是与语言无关的文档工具。阅读规则6中介绍的文档是一个与语言无关的文档托管平台,可以在每次推送到存储库时重建文档,确保您的文档始终是最新的。

自动化还有许多其他方法可以使您的文档变得更加智能:在Python中,像doctest这样的软件(sphinx-doc.org/en/stable/ext/doctest.html)可以自动从您的文档中提取示例并确保您的代码能够完成您的工作。

为了帮助您遵循规则7,有一些工具,如Napoleon(github.com/sphinx-contrib/napoleon),可以为您生成API文档。甚至可以使用诸如Swagger(swagger.io)之类的免费工具自动生成交互式代表性状态转移(REST)API文档。此时,几乎没有理由不使用自动化文档工具。

规则9:编写提供解决方案或指向文档的错误消息
在开发软件时,错误消息是生活的一部分。作为开发人员,您应该尽力使您的错误消息尽可能提供信息。好的错误消息应该包含三个部分:它们应该说明错误是什么,产生错误时软件的状态是什么,以及如何修复错误或在哪里找到与修复错误相关的信息。

通过显示出现了什么问题并提出修复方法,您的用户将花费更少的时间进行调试并花更多时间进行科学研究。由于您比其他任何人都更了解您的软件,因此在错误消息中提供指导非常宝贵。如果没有其他原因,那么为了避免为用户提供技术支持(大多数人几乎没有阅读过您的文档,如果有的话),他们遇到了容易修复的使用错误。

此外,重要的是要说明生成错误时软件的状态,特别是如果运行需要很长时间或默认情况下不保存日志。如果您的软件失败,看似随机,在执行12小时后,您的用户将会感谢知道错误被抛出时发生了什么,而不是必须再等待12个小时才能在启用日志记录的情况下重现错误。

规则10:告诉人们如何引用您的软件
在本指南中的所有规则中,可能性是您需要的最少的规则。但是,必须要说的是,如果您发布科学软件,则需要包含正确提供工作归属所需的信息。我建议在README中为您的出版物提供数字对象标识符(DOI),BibTeX条目和书面参考,以及使用引文文件格式(CFF)格式的“CITATION”文件,这是一种人类和机器可读的文件格式,用于指定科学软件的引用信息。

在您的文档中包含引文信息对于尚未在传统学术期刊上发表的软件尤其重要,因为该期刊会为其分配DOI。仅仅因为您的软件未发布并不意味着您无法获得DOI - 您的工作值得信赖。如果您使用Zenodo存档您的版本(参见规则6),它将为每个版本以及整个项目的DOI制作新的DOI。为您的项目获取DOI的另一个好的,

免费的方法是将其提交给开源软件期刊(joss.theoj.org),这是一个为软件开发人员设计的同行评审的开放式学术期刊。两者都为您的自述文件提供徽章(参见规则4),以便整个世界可以一目了然地告诉您如何引用您的软件。