阿里、蚂蚁、晟腾、中科加禾精彩分享 AI 基础设施洞见,现购票可享受 9 折优惠 |AICon 了解详情
写点什么

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 的一名工程师,现在是加利福尼亚大学河滨分校计算机科学与工程副教授。


公众号推荐:

2024 年 1 月,InfoQ 研究中心重磅发布《大语言模型综合能力测评报告 2024》,揭示了 10 个大模型在语义理解、文学创作、知识问答等领域的卓越表现。ChatGPT-4、文心一言等领先模型在编程、逻辑推理等方面展现出惊人的进步,预示着大模型将在 2024 年迎来更广泛的应用和创新。关注公众号「AI 前线」,回复「大模型报告」免费获取电子版研究报告。

AI 前线公众号
2020-03-18 13:403070

评论

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

教学实训模块升级,助力应用型数据科学人才培养|ModelWhale 版本更新

ModelWhale

数据分析 大模型 教学实训 在线编程 云课堂

零基础自学:2023年的今天,请谨慎进入网络安全行业

网络安全学海

黑客 网络安全 信息安全 计算机 渗透测试

最佳实践|亚马逊可持续发展的架构模型

亚马逊云科技 (Amazon Web Services)

JavaScript

STC89C52+DHT20设计的环境温湿度检测仪

DS小龙哥

6 月 优质更文活动

完全自动驾驶车辆何时才能成为现实

来自四九城儿

接口测试|Fiddler会话栏中添加IP列

霍格沃兹测试开发学社

唯一入选中国厂商!灵雀云获Gartner® 首份《DevOps平台魔力象限报告》“荣誉提及”

York

容器 DevOps 云原生 Gartner 平台工程

es笔记一之es安装与介绍

Hunter熊

elasticsearch Kibana 安装Kibana

强化学习从基础到进阶-常见问题和面试必知必答[6]:演员-评论员算法(advantage actor-critic,A2C),异步A2C、与生成对抗网络的联系等详解

汀丶人工智能

人工智能 深度学习 强化学习 6 月 优质更文活动

Vue插槽详解

高端章鱼哥

Vue 插槽

面向对象设计的逆向建模方法和开源工具

高鹏

Java 开源 架构 DDD 架构设计

接口测试|Fiddler抓包设置及证书配置

霍格沃兹测试开发学社

接口测试|Fiddler弱网测试

霍格沃兹测试开发学社

如何通过场景规划帮助企业实现全面预算管理?

智达方通

智达方通 全面预算管理 财务规划和分析 财务规划与预测 全面预算管理系统

2024深圳电子展,中国国际电子信息博览会(CITE电博会)

AIOTE智博会

电子展

【领域驱动设计专题】一文带领你透视DDD领域驱动模型的本质和设计原理分析指南(通用语言体系)

洛神灬殇

领域驱动设计 DDD 领域驱动设计思想 领域驱动模型

解决QT QGraphicsView提升到QChartView报错的问题

二哈侠

接口测试|Fiddler界面工具栏介绍(三)

霍格沃兹测试开发学社

接口测试|Fiddler设置手机抓包

霍格沃兹测试开发学社

何时使用Kafka而不是RabbitMQ

越长大越悲伤

Kafk Rabbit MQ 消息列队

强化学习从基础到进阶-案例与实践[6]:演员-评论员算法(advantage actor-critic,A2C),异步A2C、与生成对抗网络的联系等详解

汀丶人工智能

人工智能 深度学习 强化学习 6 月 优质更文活动 A3C算法

SQL 优化(一):慎用 SQL 函数

hungxy

Java MySQL 后端

探索支付宝云开发,开启一段100ms的神奇旅程!

TRaaS

支付宝小程序 云开发

Selenium 中并行测试的重要性

FunTester

Scrum看板工具在项目管理中的作用

顿顿顿

敏捷工具 scrum工具 scrum敏捷工具

StarRocks & Friends 上海站活动回顾(含 PPT 下载链接)

StarRocks

数据库 OLAP MPP 大数据 开源

复旦大学智能计算平台与世界科学智能大赛启动仪式

新云力量

智能 计算 复旦大学

小程序容器技术在移动警务中的业务价值

FinFish

小程序容器 移动警务 警务app

什么是区块链?

TiAmo

区块链 去中心化 6 月 优质更文活动

浅析 Jetty 中的线程优化思路

vivo互联网技术

jetty EatWhatYouKill 线程策略

机遇与挑战——超级自动化产品的国产化替代已成为大势所趋

九科Ninetech

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