【AICon】AI 基础设施、LLM运维、大模型训练与推理,一场会议,全方位涵盖! >>> 了解详情
写点什么

Uber 开源自动删除旧代码工具 Piranha,支持 Java、Swift 和 Objective-C 三种语言

  • 2020-03-18
  • 本文字数:3807 字

    阅读完需:约 12 分钟

Uber开源自动删除旧代码工具Piranha,支持Java、Swift和Objective-C三种语言

近日,Uber 通过官方博客宣布开源了一款可自动删除旧代码的工具 Piranha,该工具已经支持 Objective-C、Swift 和 Java 三种编程语言。

开源 Piranha:自动删除旧代码

长期以来,Uber 会为不同用户提供不同的功能选择,也就是定制化开发。但是,如果某项功能经过验证后证明并不成功,这些代码放在代码库里就造成了技术负担,可能使应用程序变得臃肿、冗杂。一些陈旧的代码还可能会带来不必要的风险,影响终端用户体验,对工程师而言,这些技术债的消除耗时耗力,还会影响他们开发新功能。


为了使删除旧代码的过程自动化,Uber 开源了一款可以扫描源代码并删除其中过时旧代码的工具 Piranha(食人鱼)。Piranha 可以在 Uber Android 和 iOS 代码库中运行,Uber 已使用它删除了大约 2000 个过时代码。据介绍,该工具目前支持 Objective-C、Swift 和 Java 三种编程语言。


项目地址:https://github.com/uber/piranha

如何定位需要删除的代码?

为了方便定位,Uber 开发的程序中存在各种各样的标志,开发人员在 Uber 的标志管理系统中创建一个条目,并输入属性,例如标志的名称、类型、目标推出百分比、目标平台以及标志可操作的地理位置。此外,该标志是人工引入到源代码中的,所以实验平台上的标志可与移动应用程序之间建立一致关联。随后,此标志就可以用来管理应用程序的行为。


从正在运行的应用程序的角度来看,功能标志是单个键,映射到两个或多个条件,例如开/关、颜色值、大小和复制文本。在启动时,应用程序先查询标志管理系统,并为应用的每个标志检索特定处理条件,返回的值决定了应用程序中功能的存在和行为。


当逐步推出单个功能时,我们有一个控制条件(未启用该功能)和一个处理条件(已启用该功能)。我们倾向于首先将处理条件应用于小部分用户,如果推广成功,则逐渐将应用扩展到所有相关用户(例如,每个在特定地理位置上的人)。如果在发布期间出现问题,我们可以停止并收回该功能,尽可能减小对用户的影响。


该系统还可以处理同一功能的各种不同实现,例如尝试在不同的用户组上测试不同的接口(例如 A / B 测试)。


最终,我们希望向全球所有用户推广这些功能。有时,我们希望保留某些功能标记使代码中的功能可以正常使用,一旦应用出现问题,我们可以迅速通过功能标记控制应用状态,这样就不会造成整个应用程序瘫痪。但是,由于大多数功能嵌套在其他功能下,这种预留的切断开关还是无法终止大多数功能标志。

自动删除与过时标志相关的代码

当标志过时,我们需要在功能标志管理系统中将其禁用,并从源代码中删除与该标志有关的所有代码,包括目前无法实现的该功能的替代版本,这样能在很大程度上避免技术负担。


但是,这么简单的清理步骤往往会被很多开发者忽略,从而留下技术负担,这些不必要的代码会在多个维度上影响软件开发。


为了解决技术债务问题,Uber 设计并实现了 Piranha。Piranha 原意为“食人鱼”,这个名字是根据工具本身特征而得来的。Piranha 分析了抽象语法数(AST)的程序以生成适当的重构,并将其打包到 diff 中。将 diff 分配给标志的作者以供进一步检查,作者可以按原版进行实施(提交至 master),或在实施之前执行任何其他重构。我们还围绕 Piranha 构建了工作流程,以使其能以可配置的方式定期删除过时代码。

功能标记示例

让我们来看一个简单的示例,该示例说明了 Uber 源代码中功能标志的基本用法。


最初,我们在 RidesExpName 中的标志列表中定义一个名为 RIDES_NEW_FEATURE 的新标志,并将其注册到标志管理系统中。随后,我们使用功能标志 API isTreated 将标志写入代码,并分别在 if 和 else 分支下提供处理/控制行为的实现:


public enum RidesExpName implements ExpName {   RIDES_NEW_FEATURE,}if (experiments.isTreated(RIDES_NEW_FEATURE)) {     // implementation for treatment (on) behavior} else {     // implementation for control (off) behavior}
复制代码


为了使用各种标志值测试代码,对于每个单元测试,我们可以添加注释以指定功能标志的值。下面,当所选择的标志处于已处理状态时,运行 test_new_feature:


@Test@RidesExpTest(treated=RidesExpName.RIDES_NEW_FEATURE)public void test_new_feature() {}
复制代码


当 RIDES_NEW_FEATURE 失效时,所有与之相关的代码都需要从代码库中删除。这包括:


  1. RidesExpName 中的定义;

  2. isTreated API 中的使用;

  3. @RidesExpTest.注释


此外,else-branch 的内容、目前无法实现的控制行为的实现都必须删除。我们还希望删除与那些已经删除行为相关的所有测试代码。不删除这些代码会逐渐增加源代码的复杂性,使整体系统更难维护。

自动化挑战

自动检测过时标志并删除关联代码,这项技术目前还存在一定困难,这一过程中需要确定这些标志是否被人使用了以及哪些人拥有标志,再到其代码编写的细节都是很复杂的问题。因此,克服这些挑战是 Piranha 发展的关键。

使用静态分析构建 Piranha

考虑到 Piranha 的应用背景,我们设想可以通过应用静态分析来删除因过时标志遗留下来的废旧代码。


我们确定了清理的三个关键维度:


  • 删除紧邻功能标志 API 的代码。

  • 删除由于执行上一步而无法访问的代码,我们将此称为深度清洁。

  • 删除与功能标志有关的测试代码。


我们根据在代码库中观察到的编码模式,选择了一种迭代设计技术的实用方法。


我们观察到了三种标志 API:


  • 返回布尔值的布尔型 API ,用于确定执行所采用的控制路径。

  • 更新 API ,用于更新正在运行的系统中的功能标志值。

  • 返回非布尔值原始值(整数、双精度等)的参数 API ,该值与从后端控制的实验值相对应。


重构技术解析输入源代码的 AST,以检测使用功能标志 API 的存在。对于布尔 API,我们简化布尔表达式。如果结果值是布尔常量,我们将适当地重构代码。例如,如果布尔 API 作为 if 语句的一部分出现并返回为 true,我们将通过删除整个 if 语句,然后将其替换为 then 语句来重构代码。


如果更新 API,我们只需删除相应的语句。我们不处理参数 API,因为解决它们所需的工程工作量很大,而它们在代码库中出现的频率却低得多。


由于我们观察到布尔 API 不一定要在条件语句中使用,因此我们为重构设计了第二条路径。我们确定右侧是布尔型 API(Piranha 已将其简化为常量)的分配,并跟踪被分配值的变量。同样,我们跟踪返回一个布尔 API 的 wrapper 方法,该 API 简化为常量。随后,我们确定使用被分配值变量或条件语句中的 wrapper 方法,以执行重构。


最后,如果标记注释与输入处理行为匹配,我们只需删除测试的注释,如果不匹配,则要丢弃整个测试来处理标记注释测试。

Piranha 在 Uber 的应用实践

我们实现了 Piranha 在 Objective-C、Swift 和 Java 程序中的重构。PiranhaJava 能重构 Java 应用程序中与过时的功能标志相关的代码,尤其是针对 Android 平台的代码。它在 Java 的 Error Error Prone 上作为 Error Error Prone 插件实现。PiranhaSwift 使用 SwiftSyntax 在 Swift 中实现,用于重构 Swift 代码。PiranhaObjC 用于清理 Objective-C 程序中的代码,并在 C ++中作为 Clang 插件实现,内部使用 AST 匹配器和重写器来解析和重写 AST。


尽管 Piranha 作为独立工具执行代码重构任务,但是开发人员总是想不起及时清理代码,因此它的使用频率并不算高。正如 Piranha 自动化标记清除一样,我们需要一个系统来自动启动这些清除。


在 Uber,我们建立了工作流 pipeline,该 pipeline 定期生成差异和任务以清除陈旧的功能标志。Piranha pipeline 在标志管理系统中查询陈旧标志列表,并且对于这些标志中的每个标志,分别启用 Piranha,输入陈旧标志的名称、其所有人以及预期的输出行为(处理或控制)。



图注:在我们的 Piranha 工作流中,标志 pipeline 系统定期将可能过时的标志列表发送给 Piranha,Piranha 会生成一个差异并将其发送给原始标志作者。然后作者可以确定是否要放置差异。


上图展示了 Piranha 工作流 pipeline 架构图。Piranha 生成一个 diff (即拉取请求),并将其放入代码审阅系统中,该标志的原始作者为默认审阅者。作者可以接受 diff ,或者根据需要对其进行修改,也可以拒绝修改并将该标志标记为不过期。pipeline 还在任务管理系统中生成了一个清理任务,以跟踪每个生成 diff 的状态。由于开发人员可能无法及时发现问题,因此我们还引入了一个名为 PiranhaTidy 的提醒机器人,定期添加打开 Piranha 相关任务的提醒。我们观察到,目前使用 Piranha 自动生成 diff 的时间不超过 3 分钟。

使用 Piranha 删除代码

我们很高兴地宣布,Piranha 支持三种语言,包括 Java、Swift 和 Objective-C。如想要使用 Piranha,代码需满足以下条件:


  • 广泛使用功能标志

  • 具有特定的 API 以控制功能标志的行为

  • 用 Java、Swift 或 Objective-C 实现


项目地址:


https://github.com/uber/piranha


原文链接:


https://eng.uber.com/piranha/


作者介绍


Murali Krishna Ramanathan


Murali Krishna Ramanathan 是 Uber 的编程系统研究科学家。他目前致力于构建程序分析工具,以提高开发人员的生产率。


Lazaro Clapp


Lazaro Clapp 是 Uber 编程系统团队的高级工程师,他主要在为 Java 应用程序开发静态分析工具。


Rajkishore Barik


Rajkishore Barik 是 Uber 编程系统团队的编程系统研究科学家和技术经理。他目前致力于构建工具来理解数据中心的性能异常,包括为 Swift 和 Go 开发静态分析和转换工具。


Manu Sridharan


Manu Sridharan 曾是 Uber 的一名工程师,现在是加利福尼亚大学河滨分校计算机科学与工程副教授。


公众号推荐:

跳进 AI 的奇妙世界,一起探索未来工作的新风貌!想要深入了解 AI 如何成为产业创新的新引擎?好奇哪些城市正成为 AI 人才的新磁场?《中国生成式 AI 开发者洞察 2024》由 InfoQ 研究中心精心打造,为你深度解锁生成式 AI 领域的最新开发者动态。无论你是资深研发者,还是对生成式 AI 充满好奇的新手,这份报告都是你不可错过的知识宝典。欢迎大家扫码关注「AI前线」公众号,回复「开发者洞察」领取。

2020-03-18 13:403077

评论

发布
暂无评论
发现更多内容

SAP Emarsys 和 SAP Spartacus 的集成

Jerry Wang

SAP Spartacus 思爱普 三周年连更 Emarsys

2023-04-18:ffmpeg中的hw_decode.c的功能是通过使用显卡硬件加速器(如 NVIDIA CUDA、Intel Quick Sync Video 等)对视频进行解码,从而提高解码效

福大大架构师每日一题

golang 音视频 ffmpeg 福大大

“程序员”未来会失业吗 | 社区征文

BROKEN

三周年征文

华为云:网络安全愈发重要,企业该如何保障自身业务安全?

YG科技

一文读懂 Spring Bean 的生命周期

老周聊架构

三周年连更

项目讲解之常见安全漏洞

越长大越悲伤

Java Web 安全

动态资源技术JSP|Java与Html的美好相遇

浅羽技术

Java html 服务端 jsp 三周年连更

跨平台应用开发进阶(五十)uni-app ios web-view嵌套H5项目白屏问题分析及解决

No Silver Bullet

uni-app ios 跨平台应用开发 三周年连更 web-view

Java线程中的wait、notify和notifyAll解析

共饮一杯无

Java 多线程 三周年连更

基于阿里云物联网平台设计的实时图传系统_采用MQTT协议传输图像

DS小龙哥

三周年连更

通过小程序容器技术让App实现灰度发布

没有用户名丶

中小企业如何保障网络安全?用了这么多项目华为云其实还不错!

YG科技

IT分享丨我是如何利用华为云网站安全解决方案帮助中小型企业实现IT安全

YG科技

Django笔记十之values_list指定字段取值及distinct去重处理

Hunter熊

Python django distinct values

使用 docker manifest 构建跨平台镜像

江湖十年

Docker Desktop docker image docker build Docker 镜像

尚能饭否|技术越来越新,我对老朋友jQuery还是一如既往热爱

浅羽技术

jquery 前端 Web 框架 三周年连更

DAYU200关闭自动息屏的几种方式

坚果

OpenHarmony 三周年连更

Spring Boot整合多数据源实践

做梦都在改BUG

Java Spring Boot

华为云网站安全解决方案:守护您的网站,让安全无忧

YG科技

华为云网站安全解决方案:全面保障企业网络安全,助力业务稳定高效运行

YG科技

灵活应用Nginx Map:实战经验与实用方法

小毛驴的烂笔头

nginx linux运维 Nginx实践

华为云网站安全解决方案助力客户——构建风险全面可控的网站安全架构

YG科技

华为云网站安全解决方案:中小型企业的云上云下安全守护专家

YG科技

全栈开发实战|Spring Boot文件上传与下载

TiAmo

Spring Boot 三周年连更 Apache Commons 文件上传下载

Springboot如何手动连接库并获取指定表结构|超级详细,建议收藏

bug菌

springboot 三周年连更

华为云网站安全解决方案:守护企业数字化转型之路,提升业务效率与安全

YG科技

数据库、

IPv6域名软件

穿过生命散发芬芳

ipv6 三周年连更

在Mac上快速体验AI作画

IT蜗壳-Tango

三周年连更

灵活应用Nginx Rewrite:实战经验与实用方法

小毛驴的烂笔头

nginx linux运维

开源趣事~记给OpenHarmony提PR的那些事

Bob

开源 Open Harmony

热爱所有热爱

海风极客

三周年连更

Uber开源自动删除旧代码工具Piranha,支持Java、Swift和Objective-C三种语言_文化 & 方法_Manu Sridharan_InfoQ精选文章