爲何咱們決定重構 Uber 司機端

Why We Decided to Rewrite Uber's Driver App
Driver App Rewrite: Why - feature image

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

2017年初,咱們決定對司機端進行重構。這就是 StackOverflow 的 CEO Joel Spolsky 曾經 說過的「任何一家軟件公司均可能犯下的一個巨大的錯誤」的決定。github

重構風險極高,須要集中大量資源,花費大量時間才能給用戶帶來收益。此次重要的重構,除了設計師、PM、數據分析師、運營、法務和市場以外,有幾百名工程師參與。實際上,咱們花費了一年半的時間才完成並推廣到全球。網絡

咱們的狀況是一個全部部門的工程師都面臨的一個極端問題。若是你是一個正在準備編寫或者準備重構某些代碼或者一個功能的工程師,你或許會問:「咱們有多少開發的時間?」,若是你在一個大的部門下面的一個小團隊裏面,你或許會問:「對一個沒有開發的一個功能,是否值得作這麼大的改變?」,一個出色的的工程師和一個出色的團隊在準備接受重構的挑戰的以前將會認真的研究一下這些普遍的問題。架構

所以,雖然重構過程當中會涉及一些重要的技術決策(後續文章會有涉及),但須要綜合技術考慮和普遍的業務問題來決定。雖然這些問題很難回答,但針對上述問題仍是須要一個好的答案來向你的團隊或者部門證實重構是合理的。app

最後,這些決策不是憑空而來的。咱們之因此決定重構 APP,並非基於理論架構思惟(「咱們的代碼可能會更好,若是咱們……」),而是須要長達三個月的集中研究數百頁的文檔和普遍的跨組織的支持。在下面的章節中,咱們將探討重構 Uber 司機端的決定和咱們在這個過程當中發現了什麼。框架

奠基基礎

重構的須要並不老是天然而然地來自於對新體系結構的簡單認識。重構的代價是巨大的,雖然工程組織常常想要重構代碼,可是工程師的時間還須要作新需求,而不是一遍又一遍的重構同一個功能。對於司機端來講,有如下三個趨勢有助於推進重構的決定:ide

技術債務

首先,司機端自己存在技術債務。這些債務是優步快速增加的結果,也是產品需求變化的結果(下一節討論)。不只如此, 技術債務還來自於修復之前的技術債務:應用自己陷入了屢次持續遷移,使得功能看起來愈來愈複雜。設計

值得指出的是司機端存在的技術債務不僅是理論上的。因爲持續的中斷和維護成本致使開發人員生產力降低,咱們看到了真正的業務影響。2016 年末,咱們不得不暫停 APP 的開發,以修復多個功能退化。在咱們解決這些問題以前,開發和啓動新功能都變得很是困難。code

任何中斷對於咱們司機端來講都是一個巨大的問題,由於用戶依賴它謀生。咱們認爲,任何事都不能讓可用時長低於 99.99% ,然而咱們常常發佈在應用核心流程中出現嚴重問題的版本。cdn

產品挑戰

咱們面臨一個最大的問題就是司機端以前的版本沒法很好地適用新的業務場景。早期只是簡單的按照優選轎車去設計和迭代的司機端,可是如今咱們的業務已經發展到還包含拼車、特價車和服務於市場線下現金交易體驗等等。

咱們發現除了打車業務,司機還須要其餘的功能來管理他們的資產和私人業務。例如,收入和透明的評分對司機的體驗相當重要,而在優步司機端的早期版本中這方面投資不足。咱們須要提供相似這樣功能的可擴展性,來提高產品體驗。

Two screenshots of the previous driver app

圖一:司機端以前的版本中,底部的功能標籤超出了以前的預期(左)。地圖超負荷的承載了許多業務大頭針和線路圖(右)也超出了以前的預期。

咱們在 2015年 和 2016年 採起了一些初步的步驟來減小這些痛點,發佈了一個更新版本。不幸的是,咱們爲不一樣的團隊設計了一些 UI ,而不是圍繞司機的需求和工做流程設計。若是你在這段時間仔細看了咱們的 UI ,你就會發現主頁下面有四個標籤:收入、評分、設置和首頁。每一個功能標籤都變得愈來愈臃腫,而且收入和評分標籤常常爲了需求改變意圖,而違背了設計初衷。

咱們從 APP 的迭代中獲得的教訓,以及向着咱們長期的產品規劃,實際上已經促使咱們完全從新思考司機端應該如何尋找咱們的司機合做夥伴。即便重構不是必然的,也須要從新設計。

工程對齊

咱們的研發團隊預先在新的方向作了一些投入。特別是,伴隨着 2016年 乘客端的重構 咱們引進了一個新的移動端架構,咱們叫作 RIBsVIPER 架構的一個演進),來幫助咱們處理日益增加的規模。它可以解決在司機端的大多數問題:框架的可擴展性、強大的應用架構和有說服力的內存管理模塊。咱們在 2017年 開源了 RIBs 架構。

隨着 RIBs 架構確實改進了咱們的乘客端,同時它也表明了咱們移動端組織一個新的方向。將來咱們的核心平臺將會主要投入在 RIBs 架構上。相比使用標準化的 RIBs 架構而言,每一個應用都使用本身的架構將會花費更多的資金。

決策過程

拿到新的 UI 設計和一個新的架構,咱們本質上有三個不一樣的作法:不使用 RIBs 架構從新設計司機端、讓現有的司機端去適配 RIBs 架構和基於 RIBs 架構徹底對司機端重構。

不使用 RIBs 架構

第一個方法就是咱們不使用 RIBs 架構從新設計。緣由是咱們考慮到遷移 RIBs 架構是資源密集型。雖然 RIBs 引入了大量新的代碼庫,但也是構建應用的一種新方式:將業務邏輯和顯示邏輯解耦。RIBs 架構頗有說服力,但浸入性很是強。

首先,咱們考慮現有的應用是否可以處理咱們正在考慮的主要的產品變動。咱們發現,因爲一部分邏輯在視圖控制器裏,致使許多業務邏輯和視圖展現層是強耦合的。這也就意味着 UI 層面的從新設計必然會牽扯到許多業務邏輯的修改。

其次,正如前面所說,現有的司機端架構一些問題須要解決。這些問題部分正好與 app 的邏輯有關,有一些地方(特別是 Android )都用一個模式開發是移動開發者的一個通病:不一樣版本的 MVC,都存在臃腫的視圖控制器問題,咱們大部分的核心代碼都寫在一個幾千行的控制器文件裏。所以,咱們不肯意把現有架構變得更糟,變得愈來愈複雜和難以維護。

最後,雖然舊版本司機端的架構曾經是完美的,可是長遠戰略考慮適配 RIBs 架構可以避免在優步不一樣 app 的架構分歧。一種強有力的架構,可以給咱們的平臺帶來雙倍的收益,在一個團隊(好比乘客端)寫的代碼還能在另外一個團隊(好比司機端)複用。

若是適配 RIBs,咱們該怎麼作呢?

適配

許多團隊喜歡當心翼翼地遷移,這樣可以容許他們在系統的架構變動的時候繼續開發新功能。在大多數狀況下這種方法是完美有效的,在這裏咱們討論下優步這樣作出現的一些問題。

首先,咱們分析了過去幾年在優步實施的十個主要的適配,發現它們的失敗率很高。正如他們所說,咱們將要開始適配一個基礎庫,可是完全失敗了。新功能是基於新的庫開發的,一些舊的功能也適配了,可是基礎庫裏面仍然有一些遺留代碼在運行。

在進一步調查研究以後,咱們發現司機端的許多技術債務的根本緣由是這樣的適配引發的。例如,咱們有競爭條件由於咱們的應用程序的發佈訂閱模式在安卓上是一分爲二的。咱們核心的應用架構最初是利用安卓的fragments,後來部分適配了內部框架。這種不完整的適配致使適配層和通常開發者的困惑。這些不完整的架構推動將會最後致使運行中斷直接影響到咱們的用戶。

其次,咱們常常發如今適配時形成大量的不穩定。咱們有許屢次宕機都是因爲打算改善底層應用框架,例如網絡協議。從技術上講,這些不會對咱們的用戶形成直接的影響,可是最終會影響 app 的核心功能。

最後,在咱們的經驗中,甚至連繼續開發功能的承諾都沒有實現。若是一個團隊依賴一個正在進行的適配,則常常會被阻塞直到適配工做完成。它還致使:回滾適配一般意味着咱們還必須回滾大量的功能。

所以,當咱們對是否進行完整的產品從新設計和採用 RIBs 架構評估後,不完整的適配或無止境的適配層極大的增長了應用程序的不穩定性的風險過高了。

重構

在某種程度上,咱們做出這個決定是經過否認(其餘選項,不使用 RIBs 架構和適配,是不合理的),可是重構有決定的好處,它提升了咱們作最後決定的信心。

第一,重構可以提升咱們對從新設計 app 的生產力,而不須要受先理解之前是怎麼工做的。也就意味着它的設計能夠更加通用。

第二,選擇重構也意味着咱們的架構將會更加清晰,由於它將從一開始就會有一個使人信服的策略方向。若是咱們選擇適配,咱們可能會被出於方便重用或者便利的遺留代碼所卡住。

第三,對 app 的重構會促使咱們走到畫板面前更加完整的思考咱們想要的產品方向。結果,app 中的某些主要框架將被重構。

對於一個工程師來講,重構是一個挑戰自個人機會,咱們火燒眉毛的要開始了。

結論

值得強調的是重構司機端的決定並非基於「若是咱們能重作就會更好」這樣的想法。事實上,一些工程師肯能會驚訝的聽到,即便在重構以後,咱們發佈的 app 不只使用了新的功能和新的架構,甚至還有一點新的技術債務。

也就是說,你不可能把事情處理的很是完美。閱讀了這篇文章的工程師應該對「適配不合理,重構才能寫出完美的代碼」這個結論質疑。相反,重要的是要意識到重構應該是在很是具體的組織,業務和技術需求下決定的。

若是咱們沒有在數月以前產出一個新的手機架構,或許不會重構。若是咱們沒有一個產品團隊來調研的話,或許不會重構。若是優步以前的適配工做很是成功的話,咱們或許不會重構。固然,促使咱們重構的緣由不是說重構必定是很是好的,甚至不是一個好主意。

反而,司機端的重構來自於想要爲咱們的用戶建立一個更可靠和更強的產品體驗,同時,在這個版本也加強了咱們團隊的能力。在作這個決定的過程當中或許沒有建立一個最佳抽象層那麼興奮,但它是成功的、徹底的改進了手機應用。

相關文章
相關標籤/搜索