Facebook 开发了一款名为 Getafix 的工具,可以自动查找出 bug 的修复方案,并提供给工程师审批,这极大提高了工程师的工作效率和整体代码质量。Getafix 不仅能够为工程师提供直观的修复方案,还能利用更强大的聚类算法,分析问题代码的上下文找到更合适的修复方案。Getafix 是第一款被大规模部署到 Facebook 生产环境中的自动修复工具,它进一步提升了 Facebook 拥有数十亿用户的应用程序的稳定性和性能。
现代的生产环境代码库非常复杂,并且一直持续不断地更新。为了创建一个可以自动查找 bug 修复方案的系统——在没有工程师帮助的情况下——我们构建了一个工具,可以从工程师之前对代码库的更改中学习如何修复 bug。它找到了一些隐藏的模式,并用这些模式来识别最有可能修复新 bug 的补救措施。
这个工具叫作 Getafix,已经被部署到 Facebook 的生产环境中,进一步提升数十亿人使用的应用程序的稳定性。Getafix 一般与 Facebook 其他两个工具结合使用,不过这项技术也可以用于其他地方。它目前能够为 Infer 发现的 bug 提供修复建议,Infer 是我们的静态分析工具,可识别 Android 和 Java 代码中的 null 指针异常等问题。它还通过 SapFix 提供修复建议——针对我们的智能自动化测试系统 Sapienz 检测到的 bug。现在,我们将深入了解 Getafix 是如何学习修复 bug(指任意代码问题,而不仅仅是导致应用程序崩溃的问题)的。
Getafix 的目标是让计算机处理日常工作,不过是在人类的监督之下,因为一个 bug 是否需要复杂的修复仍然需要由人类做出决定。这个工具将一种新的层次聚类方法应用于之前的数千个代码变更上,同时检查代码变更本身及其上下文。它可以检测 bug 的基础模式,并提供之前的自动修复工具无法检测到的修复方案。
Getafix 还能够在 bug 修复过程当中,显著缩小程序当中可能需要更改的具体空间,从而更快地选择适当的修复手段 ; 此外,其不再像以往暴力破解及基于逻辑型技术那样对计算时间提出极高的要求。这种更为高效的方法使得 Getafix 被成功部署至生产环境当中。与此同时,由于 Getafix 能够以以往代码变化为基础进行学习,因此足以产生让人类工程师更容易理解的修复结论。
Getafix 目前已经在 Facebook 生产环境中部署完成,负责自动对 Infer 报告提供 null 解引用 bug 进行修复,同时亦可为 Sapienz 标记的与 null 解引用相关的崩溃错误提供修复建议。此外,Getafix 还被用于解决在较新版本 Infer 重新访问现有代码时所发现的代码质量问题。
Getafix 与传统简单自动修复工具有何不同在目前的行业实践当中,自动修复功能主要用于各类基础性问题,而代码修复则更为简单。举例来说,分析器可能会提出“致命异常”警告,强调开发人员可能忘记在新的 Exception(…) 之前添加一个 throw。自动修复工具能够直接完成调整,而具体调整方式则可通过 lint 规则进行定义——换言之,其并不需要了解操作应用的特定情景。
Getafix 则完全不同,它提供更多通用性功能,并可结合上下文相关因素来解决问题。在以下代码示例当中,对应第 22 行中的 Infer 错误,Getafix 给出了下列修复结论:
需要注意的是,此修复方法不仅取决于变量 ctx,同时也与方法的返回类型相关。与简单的 lint 修复方法不同,此类修复程序无法被纳入 Infer 本身。
下图所示为 Getafix 为 Infer bug 提供的修复方法 ; 尽管来自 Infer 的 bug 总是相同的(null 方法调用,有可能引发 NullPointerException 风险),但每一项具体修复操作仍然独一无二。另外需要强调一点,Getafix 的修复方法与人类开发者的常见操作完全一致。