代码找不到,硬件陈旧,文档丢失……几十年前的代码可不是那么容易复现的。“你敢把十年前写的代码拿出来,看看还能不能用?”在最近的一篇社论文章中,《Nature》介绍了两位法国科学家发起的一项挑战。这项名为“十年再现性挑战”的挑战由法国国家数字科学技术研究所的计算机神经科学家NicolasRougier和法国国家科学研究中心的理论生物物理学家KonradHinsen共同发起,旨在鼓励研究各个领域或者找出自己十年前(或者更早)的代码,看代码还能不能运行,研究能不能复现。Rougier认为,尽管计算在科学研究中的重要性与日俱增,但研究人员很少披露其底层代码。即使他们给出了代码,其他人也很难实现,甚至作者自己有时也会遇到麻烦。而且,随着编程语言和计算环境的演进,现在还能运行的代码,过一段时间可能就不行了。因此,“10年代码恢复挑战的目的是确定那些在10年后仍然有效的代码编写和发布技术,”Hinsen说。比赛共吸引了35名参赛者。他们提议重现43篇论文,其中28篇产生了重现性报告。这些论文涉及的语言包括C、R、Mathematica、Pascal等,其中一位参赛者复现的不是代码,而是用SBML(系统生物学标记语言)编写的分子模型。当然,这条复出之路并没有想象中那么简单。有的人找不到代码,有的人找到代码后不知道怎么运行。最后,通过本次比赛,他们总结了一些提高代码复现性的技巧,可以为当前的工作提供参考。旧代码不是那么容易工作。你的代码还在吗?要完成这个挑战,首先你得找到自己的代码,有人卡在了这一步。法国国家信息学与自动化研究所的计算机科学家RobertoDiCosmo在1998年的一篇论文中提到了一个名为“OcamlP3l”的并行编程系统。但是在搜索了他和他的合著者的硬盘驱动器和备份之后,他找不到OcamlP3l系统的代码。幸运的是,一个名为“SoftwareHeritage”的源代码存档站点为他提供了备份。SoftwareHeritage会定期抓取GitHub等开源网站,有点像定期抓取Web的InternetArchive。开发人员还可以要求SoftwareHeritage获取他们自己的库以供存档。起初,DiCosmo并没有考虑去SoftwareHeritage中寻找他的代码,因为当他开发OcamlP3l时,SoftwareHeritage还不存在。他猜测一定是有人将他的代码上传到了Gitorious托管平台,该平台在该平台关闭前被SoftwareHeritage抢走了。你的证件还在吗?“在一个组织良好的项目中,文档行数超过代码行数的情况并不少见,”加州大学伯克利分校的一位计算再现性倡导者说。“你要保留尽可能多的信息。对分析的结构有更广泛的描述,比如数据从哪里来,数据的一些元信息,代码等。这些是复现的关键。“梅兰妮·斯特凡(MelanieStefan)是爱丁堡大学的神经科学家。用SBML编写的计算模型。虽然模型在那里,但她找不到当年使用的参数值(比如分子浓度),数据归一化的关键细节也没有很好的记录。结果,Stefen无法重现她的一些研究。“令人惊讶的是,有多少在十几年前显而易见的模型细节现在并不明显,即使是同一个人!”她面无表情地说。你有运行代码的硬件吗?作为比赛的组织者,Rougier也参加了这次挑战赛。他复制的代码用于AppleII中的图像放大镜,这是整个挑战中最古老的代码。这段代码写于32年前,当时Rougier16岁,并发表在一本名为《Tremplin Micro》的(已停刊)杂志上。今天,即使有了神秘的AppleSoftBASIC语言的说明,他也记不起代码是如何工作的。“见鬼,这是我自己写的,”鲁吉尔若有所思地说。不过,他能够在网上找到这段代码,并让它在基于网络的AppleII模拟器上运行。Rougier说,这并不难,最难的部分是让它在真正的AppleII上运行。硬件对Rougier来说不是问题,因为他的办公室里有一台AppleII,是一位同事在打扫办公室时捡起来的。但由于这款AppleII比USB数据线和互联网还旧,而且当前的计算机无法连接到它的旧磁盘驱动器。因此,在运行代码之前,Rougier需要某种定制硬件,以及一盒老式磁盘。他在亚马逊上发现了一些上面有“新”字样的磁盘,但日期是1993年。在写入了三次数据以确保位稳定之后,磁盘启动并运行了。该活动的发起人Hinsen在硬件方面也遇到了麻烦。他有条不紊地把90年代写的代码保存在磁带上,但现在,他已经没有读取磁带的工具了。您的计算环境是否过时?落后的计算环境也是压垮参赛者的一根稻草。意大利的计算机物理学家SabinoMaggi于1996年在Fortran中建立了一个超导设备的模型,并在MicrosoftVisualBasic中处理了结果。二十多年过去了,Fortran并没有太大变化,因此Maggi只进行了一些小的调整,以使代码顺利编译。但出乎意料的是,VisualBasic给他出了一道难题。Maggi在报告中写道,“VisualBasic是一门死语言,早已被VisualBasic.NET所取代。”因此,为了运行二十多年前的VisualBasic代码,Maggi不得不在我的Mac电脑上重建了一个十年前的Windows虚拟机。在安装之前,Maggi遇到了一个问题:他不记得他在96年使用的是哪个版本。多年来,Microsoft发布了该语言的多个版本,但它们并不总是向后兼容。运行MicrosoftVisualBasic的Mac模拟1994年的Windows计算机。同样受到计算环境问题困扰的还有法国国家信息学和自动化研究所的研究工程师LudovicCourtes。为了应对这一挑战,他复制了一篇2006年用C语言编写的比较数据压缩策略的论文。由于API更改,他的代码无法与现有软件库一起编译。为了解决这个问题,他不得不将6个计算组件回滚到非常旧的版本。如今,研究人员可以使用Docker和Conda虚拟环境来打包计算环境,以备不时之需。但一些参赛者选择了其他方法,例如Guix(Linux包管理器)。它保证了环境的可重现性,构建环境的代码版本是透明的。“可以从源头检查和构建环境和整篇论文,”Courtes说。根据Hinsen的说法,Guix可能是本次比赛“可用的最佳可重现研究工具”。与直觉相反,许多参赛者发现用旧语言编写的代码最容易重现。新语言快速变化的API和对第三方库的依赖使得它们难以重现。从这个意义上说,今年刚刚停止支持的Python2.7是一个很好的机会。它既是一种高级编程语言,也不会再更新了。如何提高代码的复现性?经历过复现代码的艰辛,相信每位选手在编写代码时都意识到了代码中埋藏的一些“隐患”,比如存储介质、选择的语言、备份平台等。那么,如何改进呢?纸质代码的可重复性?《Nature》文章作者在文中给出了一个checklist:1.代码。基于点击式界面(如Excel)的工作流程不可重现。您想在代码中保存计算和数据操作;2.文件。使用注释、计算笔记本、README文件等来解释你的代码如何运行,定义预期的参数和所需的计算环境;3.记录。记下关键参数,例如用于启动随机数生成器的“种子”值。此类记录可以帮助您重新运行代码、跟踪错误和意外结果;4.测试。创建一套测试功能。使用正负对照数据集确保得到预期的结果,并在开发过程中运行这些测试,出现bug时及时清理;5.保存。GitHub是一个流行但不是永久性的在线存储库。从长远来看,Zenodo、Figshare和SoftwareHeritage等归档服务可能会更稳定;6.追踪。使用Git等版本控制工具记录你的项目历史,记录每一个结果产生的版本;7.包装。使用容器化工具(Docker、Singularity等)、Web服务(CodeOcean、Gigantum、Binder)、虚拟环境管理器(Conda)等创建即用型计算环境;8.自动化。使用TravisCI等持续集成服务,在不同的计算环境中定期自动测试你的代码;9.简化。避免使用使后续利用复杂化的利基或难以安装的第三方代码库;10.检查。通过在一系列计算环境中运行代码来检查代码的可移植性。此外,曼彻斯特大学的计算机科学家CaroleGoble指出,将你的代码开源也是一种提高可复现性的方式,让其他人有机会根据你的代码进行更改,以保持它的生命力。如果你也有十几二十年前写的代码,你可以拿出来试试还能不能运行。
