使用 RIBs 重構 Uber 司機端

Uber新司機端RIBs架構
Architecting Uber's New Driver App in RIBs feature image

本文是 Uber 的客戶端工程師團隊是如何開發最新版本司機端的系列文章中的第二篇,代號 Carbon ,是咱們拼車業務的一個核心組件。除了其餘新功能以外,司機端 APP 還爲超過 300萬 司機提供收入,引導他們掙錢。2017年咱們結合司機的反饋開始對司機端進行從新設計,並在2018年9月份啓動了該項目。java

從新編寫一個APP會引起關於新架構和新設計相關的許多問題。迄今爲止,大多數開發者只關注應用程序如何正常工做。雖然以用戶爲中心的設計理念已經成爲軟件開發中的一些主流,可是辨別真實有效的用戶需求並不容易。react

一旦決定 重構Uber司機端, 咱們必須以普遍多樣的用戶羣裏爲基準,尋找如何設計更適用的工做流和保留最適用的產品功能。 咱們收集全世界各個城市的Uber司機的反饋,將這些反饋做爲咱們用戶體驗的重要初衷。android

與此同時,咱們也必須考慮到,成百數千的工程師們,他們須要重構APP的同時也要功能迭代。一個通過深思熟慮的APP架構須要幫助工程師,在保證可靠性的同時高效、快速的工做。ios

幸運的是,Carbon 在知足這些服務時並無發生衝突,這些服務包括更實用的應用流程,改善司機體驗功能,爲開發者提供靈活穩定的架構,事實證實,它們結合的很是好。git

本篇文章,闡述了咱們是爲了適應新司機端(代碼Carbon)如何提出核心需求,而且討論使用RIBs架構和插件設計,來知足司機端應用邏輯。github

規模發展

自2013年發版以來,Uber司機端積累了須要功能。在將來的四年以後Uber司機端將成爲司機的核心工具。隨着應用程序的日益複雜,Uber確實作到組織化。上百個功能由橫跨公司40多個不一樣子團隊開發和維護。截止2017年1月,Android司機端已經擁有由近200個工程師編寫出428,685行代碼。iOS司機端由200多工程師貢獻720,273行代碼。更爲重要的是,咱們的APP安裝在超過300萬的設備中,天天超過100個國家中的100萬個司機使用。swift

對於Carbon的成功,咱們知道咱們須要及時更新全部現有功能(已經一些新功能)的同時,也須要並行更新架構。設計模式

一塊兒建設

產品開發須要時刻記住用戶。爲此,咱們想和Uber司機一塊兒建立構建咱們的應用。在開發的最初階段,咱們在用戶調研上投入大量資金。在11個國家,12個城市中採訪了500位司機。網絡

這些訪談對象幫咱們設計新司機端的用戶體驗,肯定最重要的功能。可是,除非司機在在真實條件下在實際道路中使用APP,不然沒法獲取完整的用戶體驗。咱們須要一種方法,它能夠允收集用戶反饋,快遞迭代並每週發佈新版本。架構

Uber司機App的三種設計

圖一:在測試期間,爲APP使用最初設計。

實現可靠性

最難而且最重要的挑戰是,在實際測試中的穩定性。當接觸一個新APP,在Alpha和Beta測試階段能夠接受錯誤和問題。Uber司機端在Beta階段,真實的司機已經能夠在實際道路中可使用它掙錢了。實現可靠性是Carbon的關鍵目標。因此,進入首次測試階段時,咱們必須確保Carbon像現有程序同樣可靠。

解耦規模化開發

闡述瞭如今工程的限制後,咱們採用了分段性方法,將項目分爲四個階段。每一個階段的目標是開啓下個階段的開發。

第一階段: 基礎設施

咱們擁有一個通用模板,來描述咱們的APP必須包含哪些因素。這個模板包括網絡庫,存儲庫,ReactiveX,分析追蹤,崩潰上報和咱們的自研的應用架構Ribs。利用這個模板,咱們構建了具有初始化架構的程序,包括存儲能力,網絡,崩潰上報和基礎組件。然兒,在這個階段。程序缺乏司機業務功能,這僅僅是咱們構建特性的框架。

第二階段: 應用層設施

使用RIBs框架的一個好處是,它如何將業務邏輯做爲應用程序體系結構的核心。在Carbon階段,一個好的起點是爲司機定義高標準的用戶狀態。這將致使咱們爲RIBs定義一些基礎:

  • Root: 當啓動應用時,Root啓動基於RIBs應用程序的全部必要文件。
  • Logged Out: 若是用戶沒有有效的會話時,咱們須要一個RIBs爲用戶建立一個帳戶,登陸而且獲取有效憑證。
  • Logged In: 一旦用戶身份驗證經過,分離註銷的RIBs,將登陸的RIBs添加到有效的會話中
  • Active: 有時一個司機用戶能夠登陸,可是不能作其餘操做(他們的帳戶因爲各類緣由被封鎖)。這個RIBs確保他們有一個有效的會話_而且_容許使用程序。

咱們利用RIBs樹圖,以下圖2所示,說明應用架構。這個簡單的樹形圖展現了,如何使用RIBs組件相互關聯。

RIBs數

圖二:RIBs樹圖向咱們展現了組件關聯的可視化方法。

在關注用戶階段,咱們能夠將UI分離出來。這個方法能夠促使從司機中吸收持續反饋建議,並將建議吸納到設計中。同時促使咱們維護用戶程序的基本。

第三階段: 功能框架

在一些基礎上,咱們重點轉移到協做中。在第三階段,咱們的目標是擴大規模,使大約40個團隊在同一個APP中可靠無縫的並行工做。基於用戶的反饋和設計、產品團隊的協做,咱們定義出更詳細的RIBs組件。

  • 任務: 當司機在線和工做時若是體驗APP (例如, 導航到乘客位置, 開始行程, 乘客下車, 接另外一個單, 等等.).
  • 行程 (行程規劃): 司機規劃行程的關鍵地區。在此,他們能夠清晰的看到他們須要作的:接駕乘客到送餐。若是它是空的,它會給司機從哪裏什麼時間提供服務的建議。
  • 我的中心: 這是司機管理業務的區域。它包含實際行程以外的全部內容:重要通知,評級,收入等等
  • 地圖: 在司機端中許多和地圖相關的功能,例如導航,熱力圖,和其餘使用新RIBs開發的地圖庫。這是一個在地圖框架上的抽象層。有趣的是,以下圖展現。這個地圖庫在APP中視爲非核心功能。這意味着,若是地圖功能遇到災難性問題(固然咱們但願永遠不要發生!),咱們能夠禁用它,容許司機繼續使用。

在合併了框架以後,RIBS樹結構變大了,以下面的圖三所示。

RIBs樹

圖三: 按照咱們的定義在RIBs樹中增長層級和新的功能框架。

在咱們細分以前, 咱們清晰下在使用的RIBs架構中的一些概念。

Worker

這是一個對象,它直接關聯到RIBs生命週期,具備啓動/中止生命週期功能方法。換句話說,添加到RIBs的工做者從RIB鏈接時啓動,RIB分離時中止。工做者確保交互(一個RIB的業務邏輯組件單元)不會太大,而且容許更好的分離關注點。(在咱們的倉庫中能夠找到 AndroidiOS)

插件

插件是一種設計模式,插件容許咱們用靈活的方式進行特徵標記。(進一步瞭解Uber若是利用插件 上一篇文章)。首先咱們爲集成的核心代碼定義一個公用的API,而後開發者能夠實現本身的API實例。這是由於他們瞭解代碼由遵照這個架構的特徵標記隱形保護。把每一個插件點想象成微服務體系中一個服務,而後插件工廠做爲該服務的消費者,這樣將使得插件和API或者他們之間的契約類似。

結合RIBs,插件和工做者,能夠定義出架構中的核心和非核心部分。核心組件是必須的組件,而且不能被標記成禁用。另外一方面,若是非核心組件引入了重大問題或者致使迴歸,能夠被禁用。在上面的圖四種,Map和MyHub是非核心組件,他們能夠在不關閉應用程序功能的基礎上被禁用。

進一步查看圖 4 中 RIBs 樹圖的細節功能,咱們就能看到:如何使用核心 RIBs,Plugins,Workers, 以 worker/plugin 模式去實現 Agenda 的所有功能。Agenda 功能暴露了兩個不一樣的插件點(plugin points): Agenda Worker 和 Agenda Section。 使用 Worker plugin point 集成非用戶體驗功能,Section plugin point 去擴展用戶體驗功能。

RIBs樹細節

圖四:仔細觀察RIBs樹的一部分,能夠發現集成的多個領域,它容許在靈活添加特性,也容許並行開發。

使用這個設計模式,咱們能夠理解許多領域APP。例如一些工程師構建登陸和註冊界面,其餘工程師重點開發非核心RIBs的地圖架構。

第四階段: 全員

第四階段,其餘團隊加入咱們開放了Carbon的開發。因爲想要確保每一個功能彼此獨立,咱們建立到了插件框架,所以特性合併是一個相對順暢的過程。若有必要,一些小RIBs上升爲核心組件,可是咱們大部分代碼仍然包含在插件中,因此咱們的架構中一些部分是可選性的(咱們計劃在後續章節中討論一些使人興奮的新特性)。

RIBs架構到應用接口鏈接圖

圖五: 如動畫所示,RIBs生命週期與他們的各自單元相關

結束語

軟件工程的架構是一個一般是在犧牲別的資源條件下去優化團隊更爲重要的一些指標。雖然咱們的方法容許咱們優化可靠性、可擴展性和模塊化,可是其餘方面咱們必須妥協。在一個嚴謹的流程中,咱們只容許少許的組件是核心組件。爲了維護核心組件的質量,咱們擁有一個內部審查團隊,他們審查修改核心代碼中每一個代碼。這個流程要求一些工程師投入一些時間去作核心代碼審查,這也減慢了其餘工程師的提交頻率。

大多數應用開發者熟悉MVP或MVC模型。和他們相比,RIBs好像更冗長。RIBs有更多的組件,須要更多的前期規劃。較小的軟件開發團隊也許不須要採用相似的流程。以前咱們已經作完一個重構重寫咱們的乘客端APP,所以我對如何構建Carbon更清晰,咱們將咱們的學習總結以下:

  • 按規模工做: 在Uber, 規模 既是最高限制也是最有價值資源. 300萬司機在使用咱們的APP,因此咱們不能讓他們失望。 同時, Uber做爲一個技術組件公司,咱們已經發展到數百萬工程師一塊兒構建應用程序。規模 是咱們從規劃到推廣決策的關鍵。

  • RIBs to the rescue: Carbon經過使用RIBs和插件,咱們在如下方面得到成績:

    • 模塊化: 每一個功能的開發不依賴於其餘功能,除非它是核心RIBs。這個架構使得工程師們並行開發更便捷,不比擔憂影響其餘RIBs。
    • 可擴展性: 樹形結構能夠經過添加子節點縱向擴展,能夠經過添加兄弟節點橫向擴展,也能夠經過不一樣works將業務分離橫向擴展。
    • 可靠性: 使用插件完成的核心和非核心概念容許咱們禁用非核心代碼,因此咱們以最小損失代價進行快速轉移。
  • 共同構建: 若是沒有司機的幫助,以及他們在用戶調研和測試階段給咱們的建議,咱們不可能作到這一點。

Index of articles in Uber driver app series

  1. Why We Decided to Rewrite Uber’s Driver App
  2. Architecting Uber’s New Driver App in RIBs
  3. How Uber’s New Driver App Overcomes Network Lag
  4. Scaling Cash Payments in Uber Eats
  5. How to Ship an App Rewrite Without Risking Your Entire Business
  6. Building a Scalable and Reliable Map Interface for Drivers
相關文章
相關標籤/搜索