Ankit Agrawal是Uber开发者体验团队的2019年夏季实习生,专注于为Android Java工程师构建开发工具。在这篇文章中,他向我们鸟瞰了他在Uber的实习经历。
2019年2月12日是充满感情的一天。我欣喜若狂地得知自己将在不到四个月的时间里开始在优步(Uber)的工程实习,一想到能与经验丰富的开发人员一起工作,我就兴奋不已。
然而,我也经历了恐惧和不确定性。我刚上完大学一年级,只上过几门计算机科学课程,我将面临一个陡峭的学习曲线,并且必须在生产环境中工作——结果真正重要。
在优步暑期实习期间,作为优步Android/Java开发者体验团队的一员,我亲身解决了最前沿的技术问题,帮助我克服了这些恐惧。开发通过编辑器内联显示自定义错误的功能为我提供了宝贵的机会来解决问题、协作并与该领域的专业人员进行技术讨论。
我在Uber的实习让我获得了新的技术技能,让我了解了在生产环境中与团队合作的感觉,并让我对自己能做出的贡献充满信心。这段经历将决定我如何对待明年的大学生活,以及我最终的职业生涯。
加大
2019年5月28日,我实习的第一天,当我进入优步旧金山办公室时,我的紧张情绪开始平静下来。我见过其他实习生,有只比我大一两岁的,也有在项目最后几年读博士的。我不断地问自己,我能否在这里表现出色。然而,我的第一周致力于实习社交活动和优步现有技术的讲座。在这个过程中,我与其他实习生建立了联系,并了解了公司使用的关键术语和架构。当我意识到我们都在同一条船上,有着相同的目标:学习并成为更好的工程师时,我感到很欣慰。
当我遇到我的团队时,我的归属感不断增强。整个夏天,我和一位导师兼经理搭档。我的导师将与我密切合作,在我完成暑期项目时提供建议和投入,帮助指导我;我的经理会监督我的工作,促进跨团队合作,确保工作顺利进行,并解决团队中出现的任何问题。
在我加入Uber的第一周,我的导师找到了我,邀请我和他以及团队的其他成员共进午餐。我正在熟悉我们的团队氛围和办公空间,并渴望在未来几周内与每个人合作。
在我的入职经历之后,我立即沉浸在常规的工作周期中,准备学习。作为Android/Java开发者体验团队的一员,我意识到这个团队在更大的开发者平台和基础设施团队中所扮演的角色的广泛性和重要性。参加开发人员平台全员会议,参加以技术和非技术讨论为标志的团队午餐,参加全球团队同步和双周会议,我开始理解我的团队的角色:构建加快开发人员时间线的工具,并改善公司所有软件工程师的编程体验。
然而,在我开始我的实习项目之前,我必须让自己跟上关键技术和框架的速度。之类的术语巴克而且monorepo我觉得很陌生,所以我向我的导师寻求他所拥有的资源,很快,我开始毫不犹豫地输入Git和Buck命令。
随着我的工具知识的增长,我和我的经理和导师坐下来讨论我的暑期项目:开发一个特性来内联显示自定义Buck构建错误IntelliJ IDEA.在我实习之前,团队已经创建了工具,允许在使用我们的Buck构建系统时对Uber的Android应用程序代码库中的代码进行编译时检查。开源静态分析工具,比如ErrorProne而且NullAway已经被合并来检测额外的构建错误,我的团队利用了像他们自己的Buck Log Analyzer (BLA)这样的工具来有效地捕获此类错误。下一步是在IntelliJ IDEA编辑器中实际可视化这些错误,以便充分利用这个已有的工具,并允许开发人员更有效地纠正代码中的错误。
能够开发一个能够增强开发人员工作流程的特性是一种授权,但我之前缺乏经验和害怕失败仍然困扰着我。我很担心自己能否实现团队对这个项目的愿景。然而,仅仅几天之后,我就有信心在团队的支持和指导下执行这个项目。
爬升曲线
2019年6月10日,在我实习不到三周的时候,我已经在深入研究该公司的Android monorepo和雷竞技是骗人的IntelliJ IDEA社区版的代码库.通过梳理大量的代码层来了解存在哪些解析和显示错误的选项是非常有趣的。我正在分解代码,逐条分析,并在文件之间建立连接,以建立在开发人员的工作区中收集和显示注释的协议。尽管有必要,但试错的过程可能会很乏味;不断地遇到障碍或编写看似没有功能的代码,让我接触到不太出名但非常重要的工程元素。
尽管如此,我还是很看重我们工作的实验性。我所在的团队对Uber的软件开发过程至关重要,我知道我的项目最终会提高工程效率和工作流程。通过迭代潜在的解决方案,我可以找到一个可持续的、有效的和高效的解决方案。仅仅过了四周,我就通过在IntelliJ中显示注释取得了重大进展。预见到这样的概念验证将在我的实习中进一步出现,我很高兴看到一个可以扩展我的项目的初始模型。
随着这一进步,人们越来越有信心。我在项目中投入得越多,我在团队中的感觉就越舒服。随着时间的推移,当我感到受阻时,我开始提出问题,而不用担心自己会觉得愚蠢;与我的导师和经理进行建筑和设计讨论;让团队了解我的项目;处理与导师的意见分歧,以提高项目的代码结构和质量。
然而,最令人振奋的是有机会与全球团队成员合作。早些时候,我被介绍到优步的文化规范之一:“我们重视想法而不是等级制度。”虽然我听过这句话,但我不确定我是否真的能够与我更有经验的团队成员进行技术对话。幸运的是,由于我新获得的BLA知识,我能够开始与位于阿姆斯特丹的Android/Java Developer Experience团队的工程师进行技术讨论和合作。
在使用了他们的工具之后,我就如何改进BLA以成功地输出我所需要的错误,畅所欲言地表达了自己的意见和建议,阿姆斯特丹的工程师们也很乐意倾听。全球团队对我的项目的功能很好奇,工程师们真正投入到增强他们的工具来改善开发人员的工作流程中。
现在,我终于觉得自己是团队中有价值的一员,这让我有能力克服挑战,完成我的项目。
到达顶峰
2019年7月18日又是激动的一天,因为我在一天之内写了几百行代码。我松了一口气,知道我的项目Uber Error Parser正在进入代码库,并且该项目可以成功地在IntelliJ中内联注释自定义构建错误,这正是我的团队所希望的。我以前只登陆过一次代码,老实说,当时我并没有想太多。开发人员每天都有差异,而这只是庞大代码库中的一小部分。我很快意识到,成千上万加入这个代码库的工程师现在能够看到我开发的代码,这些代码旨在通过集中工作流程和提高纠正项目错误的警惕性来帮助他们完成日常任务。这种感觉既令人欣慰,又令人恐惧。
亲眼目睹我的劳动成果汇聚在一起是一件很有意义的事情。当我刚加入优步时,这个项目感觉像是一个不可逾越的庞然大物。然而,现在我可以自豪地向我的同行们详细介绍我的最终产品背后的功能和组件,这是我在开发者平台技术演讲的最后30分钟演讲中成功做到的。
Uber错误解析器架构
Uber的BLA已经被整个公司用来捕捉自定义构建错误,并在运行构建时将其打印到特定的文件中。我的项目,优步错误解析器,使用这些打印错误包含的信息,以便以后访问详细信息,如行号和错误消息。
存储构建错误
假设BLA将捕获的错误格式化为jsonobject,它们是这样收集的。但是,只有JSONObjects是不够的,因为仅使用行号注释错误会导致只跟踪特定的行号,而不是错误的代码段本身。
因此,该工具利用这些jsonobject来定位它们对应的jsonobject程序结构接口(PSI)元素.PSI元素是由IntelliJ平台解释的文件中代码的内部表示形式。这些元素可用于跟踪带有错误的特定代码段,确保准确的错误跟踪。然后将PSI元素存储在ElementAndString类,该类同时包含元素和与其关联的错误消息。
转换和可视化错误
收集了PSI元素之后,将在编辑器中使用MarkupModel和一个RangeHighlighter.MarkupModel将所有注释(例如,代码高亮显示和文本颜色等)存储在一个给定的文件中,每个文件维护自己的MarkupModel。另一方面,RangeHighlighter是一个可定制的注释工具,开发人员可以使用它在文件中显示外部注释。
为了获得正确的注释样式,Uber错误解析器检索存储在AnnotationStyles类,它包含凹槽图标和错误条纹类型等特性。我们希望错误能够无缝地集成到IntelliJ的整体注释风格中,这就是为什么我们选择了一个常规的红色波浪下划线,在侧边栏上有一个红色错误条和一个错误沟槽图标。这种设计与IntelliJ已经产生的其他错误和警告的功能非常匹配。
给定文件的RangeHighlighters最终存储在ArrayList,这些数组列表被映射到HashMap到它们对应的文件名,简化了该特性在项目中必须跟踪的内容。
实时更新
运行构建后,该工具可以可视化发生的其他构建错误。为了确保注释对于将来的构建是准确的,我们实现了一个VirtualFileListener类,以便在创建、更改或删除文件时侦听。在这些情况下,将检查BLA生成的文件,并根据需要更新文件注释。
迭代我的项目
在编辑器中可视化注释——这是对我的项目概念的证明——是非常值得的。在此之前,Uber的Android开发人员在运行构建后必须从另一个终端检查错误,这最终分裂了他们的工作流程,降低了效率,增加了捕获和纠正错误所需的时间。现在,有了Uber错误解析器,开发人员可以更加警惕地维护他们的代码。
虽然我为自己的成就感到欣慰和自豪,但我不能满足于现有的成就。还有更多的工作要做,以确保工具尽可能无缝地运行,并及时处理用户反馈,使解决方案对Android开发人员更有用。在接下来的几周实习中,我主动修复了围绕注释、与现有插件的功能冲突、PSI元素更新等问题的bug。我单独解决了这些问题,随着时间的推移提高了代码质量。这个过程也意味着参与更多的实践讨论,并与我的导师配对编码,以确定更清晰的代码编写方法,同时还允许相同的功能。随着这些问题的解决,我可以使用5确保最佳的代码功能和结构。
即使有了这些更新,项目中仍然有很多可以扩展的地方。我的大学课程已经描述了软件开发的迭代本质,但这是我第一次看到我工作过的代码经历如此动态的变化。例如,我曾考虑使用aFileEditorManagerListener为开发人员提供在注释不再相关时禁用注释的选项(例如,在编辑了带有自定义构建错误注释的行之后)。通过进一步研究,我发现了一雷竞技是骗人的种可视化注释的替代方法,即创建和注册对象注释器(名为ErrorAnnotator),它作为后台进程运行,并在必要时注释PSI元素(图4)。利用这种技术产生了额外的功能,这些功能最终可以被合并到Uber Error Parser框架中,以实现与IntelliJ IDEA的完整错误可视化集成。
错误可视化只是第一部分——合并AnnotationStyles类意味着开发人员可以输入他们自己的错误类型和属性,以便在IDE中可视化。现在,死代码、静态分析信息和代码覆盖细节只是一些额外的代码质量指标,可以通过潜在地利用Uber错误解析器的基线框架来显示。
攀爬更高
回顾我在Uber的时光,我非常感激我在Android/Java开发者体验团队获得的机会。在这12个星期里,我在专业和技术上的成长超出了我的想象,这也是我在继续本科学业时可以随身携带的东西。不过,下次我面对这样的学习曲线时,我可以自信地利用我所学到的技能(也许我还可以多学几门课程)。






