玩完美的游戏:在Android上建立Uber用餐

玩完美的游戏:在Android上建立Uber用餐

2018年1月两周年纪念日在Android上的Uber Eats应用程序。考虑到这一点,软件工程师希拉里·卡尔斯(Hilary Karls)反映了她的团队在2016年启动此应用程序的经验,并讨论了他们对“构建您可以居住的代码库”的承诺如何导致Uber最成功的产品之一。

当您想到运动时,运输应用程序可能不是第一件事。但是,当您将其煮沸时,成功的发射是由相同的力量塑造的,这些力量有助于完美游戏:视觉,决心,驱动器和团队合作的最终保持一致。

从左到右:队友Padmini Pyapali,Jesus Medrano,Paulina Ramos和Hilary Karls首次在多伦多推出了Uber Eats Android。他们通过饮用Paulina最喜欢的果汁点的冰沙来庆祝自己的发射。

在许多方面,Uber Eats Android应用程序是我们团队的完美游戏。

2015年8月,我们正在整理Uber Rider应用程序中的Instant Uber Eats(Uber Eats Platform的首次迭代)建造新的房屋。具体来说,我们正在通过在应用程序的标题中添加一个切口来测试食物交付,该拨动力使骑手从请求乘车转移到可以订购的餐厅。通过这些测试,我们发现用户更喜欢立即交货的种类繁多的种类范围更大 - 来自更多餐厅的菜单。尽管他们想要快速食物,但10分钟的交货时间并不那么神奇,选择有限。

图1:在Uber Rider应用程序中对即时饮食的早期测试期间,我们通过在顶级栏中敲击图标来添加了用户在骑手和即时饮食功能之间切换功能的能力。

为了创建一种可以更好地满足饥饿的Android用户偏好的产品,我们决定构建一个新的应用程序 - Uber Eats。最初的挑战:花六个星期构建一个可行版本的应用程序,该应用程序易于播放,有用,最重要的是,使食品交付体验尽可能方便和愉快。

雄心勃勃?当然,但是它设定了基调。正如我们团队的设计师所说的那样,Android的Uber Eaters的首次迭代是“纸杯蛋糕版本”-功能性和缩小,但仍然令人愉悦。

热身:建立粉底

我们设计的初稿已经准备好到8月底。到9月初,更广泛的工程团队已经汇编了一个计划,并详细概述了在iOS和Android上为我们的应用程序供电的东西。

在本月的剩余时间里,我们完成了其他任务,并开始认真计划和执行。在查看了该项目的范围之后,我们中那些从事该行业的人知道这将在12月底之前完全专注和奉献精神。

除了迅速运输外,我们还决心发展未来的增长。我们从Uber工程中其他地方的最佳实践中自由地借用了内部和外部图书馆的发展。我们使用了驱动程序应用程序中的MVC框架并集成了rxjava就像我们为Rider应用程序所拥有的方式一样。

为了建立一个可靠的坚实基础,我们对这些技术进行了资源的研究;这个应用程序是我们将居住很长时间的代码。我们利用了Uber Android平台团队的网络框架,该框架建立在OKHTTP,,,,改造,,,,匕首和我们自己的实验框架。我们在代码审查期间互相挑战,衡量我们的基础代码简单或有充分记录,以至于我们的未来自我能够理解它。

使用产品,设计和其他团队,我们开发了用户故事更好地了解我们需要构建哪些功能。这些规格范围从“用户应该能够登录”的基本考虑到“用户应该能够与餐厅下订单”。考虑到这些准则,我们与后端和iOS团队合作,尽可能清楚地定义Uber Eats API。

即使我们知道我们的API会进行调整,我们也开始实施,在团队之间有共同的理解,使我们能够将执行力解散。此外,同意我们如何建模系统中的对象使我们更容易在两个移动操作系统上构建应用程序的可持续和统一版本。根据我们的计划和策略,我们开始构建快乐的道路

上半场:理论上的快乐道路

10月中旬,我们的一位团队成员建议我们将工作分为两周的检查站,这是我们很容易采用的练习,我们大步向前。我们为每组功能分配了所有者,并开始将其贴上,并首先积极地挖掘最风险,最关键的工作。

为了使该应用程序完美工作,我们需要我们的快乐道路来检查几个盒子。首先,用户需要轻松注册并添加其付款信息。接下来,用户必须能够输入其地址条目。然后,一旦一个人进入送货地点,该应用就需要在特定区域露出所有餐馆,并允许用户查看其菜单。到达那里后,用户需要能够查看碟形页面并在其购物车中添加菜肴。最后,必须易于结帐,并从用户通过交付按“订单”按钮的那一刻的订单跟踪订单。为了确保我们的快乐道路在理论上和实践中一样“快乐”,我们都投入了代码审查,测试新功能和修复错误。

我们每天都在努力,互相信任做好工作,提供了建设性的反馈,并对我们各自的贡献负责。11月下旬的某个时候,我坐在一个团队中,环顾每个人。足球场,奔跑和传球的球员的图像,互相欢呼(玩完美的比赛)涌入了我的脑海,我意识到我们如何无缝地流在一起。即使比赛变得越来越艰难,我们的耐心磨损,情绪越来越高,而且我们没有一个人一直处于最佳状态,但我们互相信任,可以通过终点线获得该应用程序。

下半场:现实世界中的快乐之路

到12月初,iOS和后端团队正面临我们最大的整合地狱。现在是时候看到我们的共同理解是如何“分享”的,以及在实践中实际上有效的。就像经常这样做一样,这个过程进行了一些迭代。在解决挥之不去的问题之后,两支球队飞往多伦多,于2015年12月9日飞往Uber Eats IOS。

同时,我们的Android团队在我们的应用程序版本上结束了最后一个功能。同时,我们必须注意iOS和后端集成的任​​何变化。此后不久,我们能够通过该应用程序下达第一批订单,并实际上交付了食物(尽管我们尚未建立交货跟踪,因此等待我们的订单比现在更加压力)。我最喜欢订购的物品总是来自霍姆斯·贝克斯先生- 我实际上可以吃我的测试饼干!

查看我们在多伦多iOS发布的数据,我们可以看到,我们的一些简化假设所产生的一些比最佳的用户体验少。例如,我们希望所有餐厅基本上都可以同时上网。取而代之的是,这里到处都是几个,然后是很多,然后是更多,鉴于我们的清单在封闭的餐厅上方订购了开放餐厅,因此每隔几秒钟的可用选项列表就会发生巨大变化。感觉就像是地震的应用程序一样,我们知道我们必须在Android发射之前对其进行修复。

图2:在发布时,Uber Eats Android App Home Page Incorpated部分可以通过该部分轻松从即时饮食和全餐厅菜单中订购。

为了解决这个问题,我们添加了代码来检测开放餐厅和关闭餐厅数量的更改,并在仅发生几次更改的情况下进行刷新,并提示用户在刷新一定的阈值之前应用刷新之前。

我们还意识到,在没有搜索功能的情况下,有太多的餐厅可以在单个列表中导航。因此,我们在48小时内构建了第一个客户端版本的搜索版本,甚至包括使用咒语检查和建议Levenshtein距离计算。

良好的饰面

在12月下旬,我们仍在努力冻结代码。虽然iOS和后端团队庆祝他们发射的成功,但我们留下来,订购了披萨,固定挥之不去的问题,审查了代码,并降落了所有剩下的错误。在我们的友情中,我们达到了终点线,辐射骄傲和兴奋,通过精疲力尽地放大了很多。我们将所有这些都放在田野上,带着拥抱和高弹性的人走开了我们的工作。

图3:在启动时,我们的结帐和订单跟踪屏幕是最简单的版本。

由于在假期内运输应用程序有些冒险(而大多数工程师都关心支持除夕交通),我们决定在新年之后飞往多伦多参加我们的发布。

在假期中,我利用了机会工作在洪都拉斯的罗扬的项目。我知道我会很高兴的晒日光浴,潜水和实施顶嘴应用程序中的可访问性。因此,我最终与我的同事埃里克(Erik)在洪都拉斯的海滩上合作,耶稣支持我们从湾区的代码评论。因此,我们通过使Uber用户更容易为Android用户使用,在除夕与鲨鱼一起游泳,并变得非常晒太阳,并及时赶上我们于2016年1月6日在Chilly Toronto推出,我们对2015年的再见告别。

两年零200个城市

两年后来,Uber Eats Android应用已扩大到全球200多个城市,拥有80,000多个餐厅合作伙伴。我们的辛勤工作获得了回报:该应用程序在2016年获得了Google Play商店的编辑选择奖,并已由全球数百万用户下载。尽管我们在启动了新功能时已慢慢重写应用程序的部分,但今天仍在使用一些原始代码。

图4:随着时间的流逝,我们已经添加了最喜欢的餐厅,并在Uber Eats应用程序中的旋转木马中看到一群餐馆。我们还提高了应用程序的搜索和浏览功能。

图5:我们还大量投资了优化Uber Eats结帐和交付体验。

耶稣和我仍然在Uber Eats团队中,Paulina和Padmini将他们的企业家精神带到优步货运。与他们一起玩完美的游戏,教会了我几次关于成功构建和启动新应用所需的课程的课程:

与您的运营团队合作以实现增长

没有我们的运营团队,我们在Uber Eats中看到的增长不可能是不可能的。他们在洛杉矶的早期测试以及对Uber Inters进行实验的少数市场证明了业务会坚持下去,以便我们可以自信地扩展。此外,多伦多团队与我们及其当地合作伙伴紧密合作,启动了完整应用程序和市场的第一个版本,并倾注了他们的精力使其正常工作。

练习:早期和经常进行实验

在承诺构建一个单独的应用程序之前,我们进行了几个实验。我们通过早期进行相对较低的投资实验获得的见解使我们有信心构建一个新的应用程序,并知道我们会找到有用的途径。

杠杆框架

在Uber,Square,Google和更广泛的工程社区的框架和图书馆的基础上,为我们节省了很多时间和精力。除非您必须从头开始,否则请勿重新发明轮子。

优先考虑关键/风险功能

将功能分解为“必须拥有”(P0),“重要”(P1),“ nice-to-to-to-to-to)(P2)等是一个好习惯。对于此推出,我们几乎只专注于P0。即使在P0中,重要的是要了解哪些功能是最危险的,最可能需要的时间超过预期。如果可以将它们撞到P1,那就去做。如果没有,请在开发时间表中较早地插入。如果时间表发生变化,灵活性将通过更改项目的其余部分或与利益相关者的新发布日期达成共识来更容易发货。

留出时间进行集成

即使有最佳计划,任何项目的最后时刻也可能揭示出不太准确的理解或假设的不一致之处。为集成,测试和错误修复的预算时间提供了一些时间,使您有机会解决压力较小的任何问题。

朝着相同的方向运行:对齐和价值很重要

尽管这是广为人知的,但对需要做的事情的一致性对于执行至关重要。围绕正在建造的东西,由谁以及何时浪费宝贵的时间的混乱。沿着这些线条,对您和您的团队选择如何建立保持一致也很重要。我们所有人都希望构建一个我们可以居住至少一年的应用程序,而无需在发布时不得不重写。如果某些成员非常重视代码质量和一些有价值的运输,以后再清理一切,那么不可避免的紧张局势将大大减慢我们的速度。

互相照顾

我们的团队共同努力,因为我们互相信任既可以执行并在任何人陷入困境的情况下帮助每个人。更广泛的Uber Eats工程团队也重视同样的信任感和支持感。我们知道,如果我们需要任何帮助(从代码评论到修复错误到功能协作)的任何帮助 - 我们拥有彼此的背部,使我们能够产生远比我们一个人更大的东西。

如果您在Android兴趣上提供美味的东西,请考虑申请职务在我们的团队中!

注释