作为优步2018年暑期实习生之一,我每天都在为我的朋友和家人在优步平台上使用的技术工作,我感到无比兴奋。因为攻读计算机科学学位,我申请了一个Uber暑期实习作为获得实际实践经验的一种方式。
把我引向计算机科学的道路——以及我在优步的实习——是独一无二的。我在高中玩音乐,我认为为音乐家构建应用程序会很有趣。当我大约15岁的时候,我写了第一行代码,并开始学习JavaScript和Python。2008年苹果推出应用程序商店后,我当时的音乐老师决定开发一款教育音乐应用程序,并邀请我加入团队。为音乐编写程序是我开始编程的首要原因,所以这是一个完美的机会。我开发这个应用程序的经历让我获得了计算机科学的学士学位,目前我正在爱丁堡大学完成这个学位,之前我在德克萨斯大学奥斯汀分校(University of Texas at Austin)交换了一年。
在优步实习尤其让我感兴趣,因为就像在我高中老师的音乐应用程序上工作一样,我知道我将有机会解决复杂的技术挑战,并对现实世界产生持久的影响。然而,我将不在制作音乐软件,而是在Uber Eats餐厅管理工程团队工作,这与我对使用代码解决物理问题(在这种情况下是食品配送)的热情非常契合。
本着这种精神,我实习的重点是为我们的优步外卖运营团队构建一个解决方案,使优步外卖应用程序上的餐厅菜单无缝更新。我们的员工驻扎在世界各地的城市,管理与食客、外卖合作伙伴和餐厅合作伙伴的关系。创建这一功能将使运营团队成员不必在我们的平台上手动更新餐厅菜单,从而节省他们的时间和资源,可以更好地为我们的客户服务。
功能设计过程
考虑到我的项目目标,我和我的导师、Uber软件工程师卡比尔·马哈尔(Kabir Mahal)起草了初始设计。我们计划使用依赖关系构建一个服务来存储预定的菜单更改、安排更改并执行菜单更新,在预定的时间在平台上实时发布它。
该计划需要Menu Scheduler,我们的新服务,获取上传的菜单数据电子表格,存储它,并使用内部cron服务在指定时间更新餐厅的菜单。UI将是Operations根据餐厅合作伙伴的请求更改信息的内部工具。乍一看,这个方案看起来很可靠,我相信工程评审人员会给我开绿灯,让我继续前进并开始构建。
设计迭代
我不知道我的项目范围在短短几天内会发生如此大的变化。当我们收集关于架构的反馈时,我们收到的评论指出,Uber Eats计划安排所有类型的活动,而不仅仅是在餐厅插入菜单功能。与我在高中时开发音乐应用程序的经历不同,为一个拥有数百万用户的全球不断发展的产品设计一个单一功能需要广泛的合作、研究,当然还有迭代。雷竞技是骗人的
应用程序的设计过程向我展示了Uber在整个工程部门共享技术项目的文化,这种做法是为了确保工程师们正在构建独特的工具并提高效率。这种协作文化让我了解了一些同时进行的工作,这些工作可以使我们的工作更可重用,构建得更快。例如,Uber Eats工程团队的另一个团队已经在通过一个新的菜单转换工具更新我们的菜单格式,并建立一个新的自助服务工具,以帮助餐厅合作伙伴在Uber平台上编辑与其业务相关的信息。
这些关于优步外卖的更大工程计划的披露,让我意识到有许多工程师参与改善服务,并促使我重新思考我的整个项目设计。
举例二:重新设计
我们的重新设计将调度逻辑转移到批量操作中,这是一种现有的服务,用于更改城市级别的商店营业时间和增值税(VAT)税率以及其他信息。对该服务的依赖使我们不再担心存储问题,因为操作也会持久化菜单数据。当我们宣布更新后的设计时,运维团队热情地回复了一份基于调度组件的其他功能请求列表。我的项目范围从服务一个特定的用例发展到包括对我们的客户有更大影响的通用特性。
在第二轮迭代中,菜单调度器已经成为一个轻量级服务,连接了Uber Eats的许多部分:UI、菜单转换器和批量操作。
尽管规划过程比最初预期的要长,但重新设计导致了更多的跨团队协作和学习。事实证明,我们计划的改动足以推出两个rfc这一举动澄清了我们的目标,同时将通用调度及其第一个用例(调度菜单)分离到两个文档中。重新设计还为如何在团队之间划分即将到来的工作建立了明确的界限。
在Go中编程
菜单调度器涉及许多不同的服务,涉及广泛的前端和后端工作。当开发开始时,我的第一个任务是在调度程序中构建通过批量操作服务调度菜单更新的功能。然而,要做到这一点,我需要用Go编程,这是Uber Eats使用的编程语言,我以前没有学过。幸运的是,我发现很多我的新同事之前没有使用围棋的经验在加入优步之前,这让我觉得在工作中学习它更舒服。我总是喜欢学习新的编程语言,但在这种情况下,它不只是构建模拟应用程序和玩它们;我有产品要发布!
在Uber实习之前,我主要使用Python工作,所以我很喜欢Go这种强类型语言所带来的开发速度的提高。在Uber学习Go让我专注于编写强大的代码,而不是思考构建web应用程序的基础知识。在这个过程中,我编写的软件满足了项目的技术要求,同时还受益于一次令人难以置信的学习经历。只要有时间,我就会深入研究Uber使用的一些库,以了解Go的基本原理。虽然在加入Uber之前,我从未写过一行Go代码,但我很快就学会了,在团队的帮助下,我在几天内就写好了代码。
除了学习一门新语言,我的整个实习项目都是在现有的代码库中工作。令我惊讶的是,项目负责人如此关心工艺的质量和发展——他们确保了高质量的代码标准,同时让我尝试不同的方法。虽然编写良好的代码对我在高中的最初努力很重要,但在大型组织中编写良好的代码也需要易于理解的文档和代码审查。在Uber,我可以快速失败,从错误中吸取教训,并在几个小时内纠正自己,这要归功于我们高效的代码审查流程。
实习外卖
演示日是一个全公司范围的活动,我们向整个工程组织展示了我们的项目,对我们所有实习生来说都是激动人心的一天。我们终于向办公室里的每个人展示了我们一直在做的工作。看到我们的项目完成是值得的,它鼓励我反思我的实习经历作为一个整体。我从没想过能在一家大公司获得这么大的自主权和支持,来推动和监督这样一个有趣而重要的项目的完成。
我在Uber的这个夏天给了我一个难得的机会,让我成长为一名工程师和一名团队合作者。我了解到软件工程不仅仅是编写好的软件:工程师们需要注意他们可能认为的编写代码的核心工作,例如代码审查、文档编制和有效的沟通。
以下是我从实习中学到的一些额外经验:
不要低估强大的支持网络的价值:我的团队,以及和我一起工作的其他Uber工程师,都非常支持我,我觉得我可以问他们任何问题。这种支持促使我一有机会就帮助其他工程师的工作。我通过提出较小的分歧和清楚地传达我的目标、问题和失败来提高我的效率。通过RFC流程,我提高了我的写作技巧和按时完成任务的能力。根据我的经验,学校的工作很少关注这些类型的现实世界的考虑,但这次实习让我有机会在整个夏天发展它们。
没有什么比大规模开发更好的了:Uber Eats的运营规模是吸引我最初担任这个职位的原因。在学校或小公司中,规模通常不是您如何进行系统设计的决定因素。在优步,我了解到衡量你所做的一切的重要性。当您编写的代码具有许多依赖关系,并且需要随着业务的增长而扩展时,密切关注代码是否按预期工作是至关重要的。
广度和深度并不相互排斥:也许我在Uber实习最令人惊讶的部分是我与之合作构建菜单调度器的技术堆栈的广度。首先,我第一次使用Go,并且对JavaScript更加精通。我也学会了权衡DOSA医生以及优步内部二进制数据存储Terrablob。我使用Fusion.js而且反应来构建UI。我不希望有更好的全栈工作和提高软技能的组合,比如创建RFC和跨团队协作。
合作是关键:在这个项目上的工作是一个很好的例子,说明协作和沟通对于快速发布功能是多么重要,考虑到业务的速度和规模,Uber的工程师们非常熟悉这项技能。也许最让我惊讶和高兴的是优步的开放和自愿文化,这种文化使我超越了我以为一个夏天就能建立起来的东西。
有兴趣在Uber实习?2019年学期的申请已经结束,但请查看我们的网页网站明年夏天会有新的机会。
订阅我们的通讯以跟上优步工程公司的最新创新。
标题图片来源:Lip Kee的小熊在玩耍,在创作共用协议下获得许可相似属性共享2.0通用许可.






