在研究中追求可靠性:代码测试能有所作为吗?
在研究中追求可靠性:代码测试能有所作为吗?
确保研究结果的可靠性一直是研究人员的首要任务之一。它是让我们一砖一瓦地构建世界知识的基础。当不满足可靠性条件时,我们对这个系统的信任会遭受可怕的后果。由于从数据操纵到诚实错误的原因( retractionwatch.com ),由于缺乏可靠性,数十亿美元和数年的工作被浪费了。
“直接的、明显的损害是浪费 NIH 的资金和在该领域浪费思维,因为人们将这些结果作为自己实验的起点。”
托马斯·苏德霍夫 |斯坦福大学
迄今为止的解决方案是通过执行小迭代来依赖结果的可重复性。为了验证新假设,研究人员首先需要确认他们的同行发表的结果。然而,研究中臭名昭著的“发表或灭亡”趋势正在阻止这种健康方法的实践。研究人员被迫仓促提出新的结果,否则他们可能会失去资金。这场争相发表也意味着在确保结果质量方面做得很少。
为了增加研究世界的惨淡画像,研究的复杂性显着增加,研究人员获得更多的知识和技能,同时学习和改进的时间最少。正如我在上一篇文章中提到的,已经为数据收集构建了更多工具;实验变得更加复杂,但在促进产生可靠结果方面几乎没有做任何事情。由于当前的实验室结构缺乏监督,研究人员会在代码中积累小错误来收集和分析数据。他们的代码没有经过编程测试、同行评审或记录。
因此,作为研究核心的数据变得越来越不可靠。
虽然其他部门(产品管理、人力资源、软件工程等)已制定规则并努力优化其工作技术和流程,但公共研究并未加快步伐。尽管当代形式的研究已经存在了半个多世纪,但它缺乏共识的方法是显而易见的。很少有实验室对讨论人力资源管理、数据采集、分析或项目管理表示兴趣。因此,没有达成共识。
我们可以开发哪种方法来提高结果的可靠性?我们可以借鉴其他领域的想法吗?让我们来看看软件工程如何提供可靠性和健壮性。
测试代码
手动测试是每个软件开发人员都学会做的事情。这意味着运行您刚刚编写的代码,并通过调试器、日志或输出检查代码是否满足所需的功能。例如,检查您刚刚添加到图形用户界面的按钮是否正在启动实验,或者数据是否以正确的格式保存在正确的位置。随着代码的发展,开发人员必须手动确保他们的新代码不会破坏以前开发的功能。
开发人员决定以编程方式测试他们的代码,而不是手动重新测试每一位代码,这将浪费大量时间。这意味着他们编写代码来测试先前编写的代码的功能。当他们添加新代码时,他们可以因此验证它不会破坏以前开发的功能。这个概念是首先编写功能代码,然后是测试代码。随着代码库复杂性和规模的增加,测试变得越来越少,因为开发人员需要快速切换到开发下一个功能。因此,编写测试变得越来越困难(我强烈推荐 有效地使用 Michael Feathers 的遗留代码 )。
测试驱动开发 (TDD) 是一种软件开发方法,包括三个主要步骤:首先编写测试,编写足够的代码以使测试通过,以及清理代码。开发人员应重复这三个小步骤以获得一致且可靠的结果。
虽然这项技术似乎是解决世界上所有研究问题的神奇工具,但它依赖于强大的隐含假设来实现效率。
第一个假设是它有详细的要求。开发团队接收客户或产品经理定义的功能需求。随着时间的推移会有一些修改,但开发人员有一个明确的方向。
第二个假设是代码将比编写或编辑的代码更多地使用。这对所有开发人员来说都是显而易见的,因为这是在公司中编写代码的主要原因。
第三个假设是编写的代码将有很长的生命周期。 TDD 的开发考虑了可持续性。随着时间的推移,代码将由几代开发人员更新和升级。
拥有可靠、经过测试和健壮的代码是每个研究人员都应该努力实现的目标。研究在可重复的实验中蓬勃发展,并且由于愚蠢的错误而获得损坏的结果不是任何研究人员都希望遇到的情况。所以,你是否应该强迫自己遵循如此严格的方法并花费两倍的时间来开发相同的数量功能代码?
简短的回答是肯定的,但实施可能取决于您要实现的目标。
在研究中应用 TDD
研究中的软件开发与公司中所做的工作不同。它只是研究工作的一小部分,可能不构成优先事项。如果未满足 TDD 的基本假设,则应用 TDD 方法将花费在编码上的时间加倍,可能不会提高研究质量。让我们探讨两种类型的代码库研究人员的目标、要求和条件: 数据采集 和 数据分析(清理、处理和报告) .
数据收集或实验
正如引言中提到的,研究人员通常自己从事他们的研究项目。因此,他们几乎没有可重用的代码来帮助他们进行数据收集,因为他们必须定义他们想要记录什么样的数据以及在什么条件下记录。虽然有些人可以使用他们的录音设备公司提供的无代码工具,但许多人需要自己开发整个实验。涉及多个传感器记录、闭环实验等的实验就是这种情况。在这个过程中,他们编写的代码需要 100% 没有错误,因为他们的整个研究都依赖于它。如果数据被转移或部分损坏,整个项目都处于危险之中!
在开始实验之前,研究人员正确定义一个或多个假设和实验协议,这些假设由同行或研究人员自己验证。与软件工程行业类似,研究人员在开始编写实验代码之前遵循需求和规范。这些要求的存在验证了 TDD 的第一个假设。有了这些,研究人员-开发人员将拥有遵循测试驱动开发方法的所有必要信息。
研究的一个关键方面是结果的可重复性,这需要记录足够的数据来推断所获得结果的统计能力。从纵向研究到队列研究,为收集数据而开发的代码的使用/运行次数将超过其编写次数。因此,它满足 TDD 的第二个假设。
与公司软件的预期寿命相比,数据收集代码的寿命通常很短。它的范围从单个实验(1 个月)到整个博士学位。 (约 4 年)。如果实验室认为使用一个共享代码来收集数据对团队更有利,则可以突然延长数据收集代码的生命周期。然后,该过程更接近公司的软件开发方法。
为获得可靠和可重复的结果而开发的代码必须通过密集测试证明没有错误。正如我们所看到的,在这种情况下,TDD 的所有三个假设都得到了满足。因此,研究人员将 TDD 应用于他们的数据收集代码将是非常有益的。
数据清洗、处理和分析
在许多情况下,研究人员会编写代码来清理、处理和分析收集到的数据 后 他们收集了它。他们将用新的假设和数据处理技术“探索”数据。数据分析开发是一种独特的软件工程形式,与普通软件工程相比,它更接近于脚本,并且明显缺乏需求和目标。绘图和图形是在数据分析过程中制作的。代码编写并运行一次。大多数时候,它是单个数据科学家(开发人员)的工作,其代码库通常不会增长。由于代码仅用于分析一项实验,因此其生命周期相对较短。因此,TDD 在这里似乎不相关,因为它的假设没有得到满足。
那么,我们是否应该停止依赖可靠的研究结果呢?为了回答这些问题,我们研究人员应该讨论可以开发什么样的方法来确保我们结果的可靠性。
让我给你一个我作为数据科学家的职业生涯中的真实经历,我可以自豪地声称我的代码没有错误。
我在一个实验室工作,该实验室需要为一个复杂的神经科学项目提供高级可视化。在那里,我的任务是开发一些数据处理和分析工具。几天后,我完成了所有的绘图和后处理代码。考虑到大量的工作和数据,我如何向客户证明我的代码是可靠的?他们怎么能相信它来验证他们的假设?该实验没有先例,因此无法根据之前的实验和结果验证我的代码的可靠性。我也不能相信这些数据,因为在录制过程中可能出现任何问题。因此,我必须创建验证合作者假设的模拟数据,有效地将假设转化为软件需求。
从结论(定义明确的要求)开始,我能够编写一个经过测试的第一个生成理想数据的代码。因此,验证我的分析代码没有错误变得很容易,因为图表显示了预期的结果。
我称这种方法为 测试驱动研究 (TDR)
为了开发上述工具,我还必须深入研究文献以找到估计的分布类型(高斯分布、泊松分布等)及其相关参数。这也使我能够估计要记录的受试者(动物/集群/神经元)的数量,以获得出色的统计能力(验证或拒绝默认假设)。
以下是 TDR 为我带来了什么的快速总结:
- 在开始实验之前正确定义假设
- 为实验定义统计上足够的受试者数量(统计功效)
- 获取有关神经元模式的所有信息(特定领域的知识)
- 编写开发一个经过高度测试、可重现和可重用的理想数据生成器
- 创建更可靠的数据处理管道、绘图和图形
结论
我们已经看到了如何将测试驱动开发(一种软件工程方法)应用于研究,以从数据采集和分析中获得可靠的结果。尽管结构和目标存在差异,但 TDD 的高可靠性显然使其成为所有研究人员的必备品。
当我们并行编写代码和调查相关数据时,数据分析很难测试,我建议采用测试驱动研究 (TDR),这将减少数据分析管道中的错误。通过注入使用经过良好测试的生成器(使用 TDD)人工生成的理想可信数据,数据分析的可靠性大大提高。
这篇文章表明,研究人员不应该停止寻找他们的领域之外来解决他们自己的问题。正是通过每个人的不懈努力,研究才能带来知识和不断的创新。
Test-driven research pipeline. The artificial experiment is a data generator that can be used to test the code of the data analysis pipeline.
您有哪些解决方案来确保研究结果的可靠性?你有没有遇到过类似的经历?请分享您对这种新方法的想法!
推荐阅读
清洁代码 罗伯特·C·马丁。这本书涵盖了所有语言的现代软件工程良好实践的基础——每个编写代码的人都必须拥有。
适合您的代码 马克西曼。这本书提供了有关如何优化编码方式的提示和技巧。它比 Robert C. Martin 的 Clean Code 需要更多的软件工程知识。
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明