成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

美團外賣Android平臺化架構演進實踐

移動開發 Android
美團外賣自 2013 年創建以來,業務一直高速發展。目前美團外賣日完成訂單量已突破 1800 萬,成為美團點評最重要的業務之一。

美團外賣自 2013 年創建以來,業務一直高速發展。目前美團外賣日完成訂單量已突破 1800 萬,成為美團點評最重要的業務之一。

[[224117]]

美團外賣的用戶端入口,從單一的外賣獨立 App,拓展為外賣、美團、點評等多個 App 入口。

美團外賣所承載的業務,也從單一的餐飲業務,發展到餐飲、超市、生鮮、果蔬、藥品、鮮花、蛋糕、跑腿等十多個大品類業務。業務的快速發展對客戶端架構不斷提出新的挑戰。

平臺化背景

很早之前,外賣作為孵化中的項目只有美團外賣 App(下文簡稱外賣 App)一個入口,后來外賣作為一個子頻道接入到美團 App(下文簡稱外賣頻道),兩端業務并行迭代開發。

早期為了快速上線,開發同學直接將外賣 App 的代碼拷貝一份到外賣頻道,做了簡單的適配就很快接入到美團 App 了。

早期的外賣 App 和外賣頻道由兩個團隊分別維護,而在隨后一段時間里,兩端代碼體系差異越來越大。

最后演變成了從網絡、圖片等基礎庫到 UI 控件、類的命名等都不盡相同的兩套代碼。

盡管后來兩個團隊合并到一起,但歷史的差異已經形成,為了優先滿足業務需求,很長一段時間內,我們只能在兩套代碼的基礎上不斷堆積更多的功能。

維護兩套代碼的成本可想而知,而業務的迅猛發展又使得這一問題越發不可忍受。

在我們探索解決兩端代碼復用的同時,業務的發展又對我們提出新的挑戰。隨著團隊成員擴充了數倍,商超生鮮等垂直品類的拆分,以及異地研發團隊的建立,外賣客戶端的平臺化被提上日程。

而在此之前,外賣 App 和外賣頻道基本保持單工程開發,這樣的模式顯然是無法支持多團隊協作開發的。

因此,我們需要快速將代碼重構為支持平臺化的多工程模式,同時還要考慮業務模塊的解耦,使得新業務可以拷貝現有的代碼快速上線。

此外,在實施平臺化的過程中,兩端代碼復用的問題還沒有解決,如果兩端的代碼沒有統一而直接做平臺化業務拆庫,必然會導致問題的復雜化。

在這樣的背景下,可以看出我們面臨的問題相較于其他平臺型 App 更為特殊和復雜:既要解決外賣業務平臺化的問題,又要解決外賣 App 和外賣頻道兩端代碼復用的問題。

屢次探索

在實施平臺化和兩端代碼復用的道路上并非一帆風順,很多方案只有在嘗試之后才知道問題所在。

我們多次遇到這樣的情況:設計方案完成后,團隊已經全身心投入到開發之中,但是由于業務形態發生變化,原有的設計也被迫更改。

在不斷的探索和實踐過程中,我們經歷了多個中間階段。雖然有不少失敗的案例,但是也積累了很多架構設計上的寶貴經驗,整個團隊對業務和架構也有了更深的理解。

搜索庫拆分實踐

早期美團外賣 App 和美團外賣頻道兩個團隊的合并,帶來的最大痛點是代碼復用,而非平臺化,而在很長的一段時間內,我們也沒有想過從平臺化的角度去解決兩端代碼復用的問題。

然而代碼復用的一些失敗嘗試,給后續平臺化的架構帶來了不少寶貴的經驗。

當時是怎么解決代碼復用問題的呢?我們通過和產品、設計同學的溝通,約定了未來的需求,會從需求內容、交互、樣式上,兩端盡可能的保持一致。

經過多次討論后,團隊發起了兩端代碼復用的技術方案嘗試,我們決定將搜索模塊從主工程拆分出來,并實現兩端代碼復用。

然而兩端的搜索模塊代碼底層差異很大,BaseActivity 和 BaseFragment 不統一,UI 樣式不統一,數據 Model 不統一,圖片、網絡、埋點不統一,并且兩端發版周期也不一致。

針對這些問題的解決方案是:

  • 通過代理屏蔽 Activity 和 Fragment 基類不統一的問題。
  • 兩端主工程 style 覆蓋搜索庫的 UI 樣式。
  • 搜索庫使用獨立的數據 Model,上層去做數據適配。
  • 其他差異通通拋出接口讓上層實現。
  • 和 PM 溝通盡量使產品需求和發版周期一致。

大致架構如下圖:

雖然搜索庫在短期內拆分為獨立的工程,并實現了絕大部分的兩端代碼復用。

但是好景不長,僅僅更新過幾個版本后,由于需求和版本發布周期的差異,搜索庫開始變為兩個分支,并且兩個分支的差異越來越大,最后代碼無法合并而不得不永久維護兩個搜索庫。

搜索庫事實上是一次失敗的拆分,其中的問題總結起來有三個:

  • 在兩端底層差異巨大的情況下自上而下的強行拆分,導致大量實現和適配留在了兩端主工程實現,這樣的設計層級混亂,邊界模糊,并且極大的增加了業務開發的復雜性。
  • 寄希望于兩端需求和發版周期完全一致這個想法不切實際,如果在架構上不為兩端的差異性預留可伸縮的空間,復用最終是難以持續的。
  • 約定或規范,受限于組織架構和具體執行的個人,不確定性太高。

頁面組件化實踐

在經歷過搜索庫的失敗拆分后,大家認為目前還不具備實現模塊整體拆分和復用的條件,因此我們走向了另一個方向,即實現頁面的組件化以達成部分組件復用的目標。

頁面組件化的設計思路是:

  • 將頁面拆分為粒度更小的組件,組件內部除了包含 UI 實現,還包含數據層和邏輯層。
  • 組件提供個性化配置滿足兩端差異需求,如果無法滿足再通過代理拋到上層處理。

頁面組件化是一個良好的設計,但它主要適用于解決 Activity 巨大化的問題。

由于底層差異巨大的情況,使得頁面組件化很難實現大規模的復用,復用效率低。另一方面,頁面組件化也沒有為兩端差異性預留可伸縮的空間。

MVP 分層復用實踐

我們還嘗試過運用設計模式解決兩端代碼復用的問題。想法是將代碼分為易變的和穩定的兩部分,易變部分在兩端上層實現差異化處理,穩定部分可以在下層實現復用。

方案的主要設計思路是:

  • 借鑒 Clean MVP 架構,根據職責將代碼拆分為 Presenter,Data Repository,Use Case,View,Model 等角色。
  • UI、動畫、數據請求等邏輯在下層僅保留接口,在上層實現并注入到下層。
  • 對于兩端不一致的數據 Model,通過轉換器適配為下層統一的模型。

大致架構如下圖:

這是一種靈活、優雅的設計,能夠實現部分代碼的復用,并能解決兩端基礎庫和 UI 等差異。

這個方案在首頁和二級頻道頁的部分模塊使用了一段時間,但是因為學習成本較高等原因推廣比較緩慢。

另外,這個時期平臺化已被提上日程,業務痛點決定了我們必須快速實施模塊整體的拆分和復用,而優雅的設計模式并不適合解決這一類問題。

即使從復用性的角度來看,這樣的設計也會使得業務開發變得更為復雜、調試困難,對于新人來說難以勝任,最終推廣落地困難。

中間層實踐

通過多次實踐,我們認識到要實現兩端代碼復用,基礎庫的統一是必然的工作,是其他一切工作的基礎。否則必然導致復雜和難以維護的設計,最終導致兩端復用無法快速推進下去。

計算機界有一句名言:“計算機科學領域的任何問題都可以通過增加一個中間層來解決。”(原始版本出自計算機科學家 David Wheeler)我們當然有想過通過中間層設計屏蔽兩端的基礎庫差異。

例如網絡庫,外賣 App 基于 Volley 實現,外賣頻道基于 Retrofit 實現。我們曾經在 Volley 和 Retrofit 之上封裝了一層網絡框架,對外暴露統一的接口,上層可以切換底層依賴 Volley 或是 Retrofit。

但這個中間層并沒有上線,最終我們將兩端的網絡庫統一成了 Retrofit。

這里面有多個原因:

  • 首先 Retrofit 本身就是較高層次的封裝,并且擁有優雅的設計模式,理論上我們很難封裝一套擴展性更強的接口。
  • 其次長期來看底層網絡框架變更的風險極低,并且適配網絡層的各種插件也是一件費時費力的事情,因此保持網絡中間層的性價比極低。
  • 此外將兩端的網絡請求都替換為中間層接口,顯然工作量遠大于只保留一端的依賴。

通過實踐我們認識到,中間層設計是一把雙刃劍。如果基礎框架本身的擴展性足夠強,中間層設計就顯得多此一舉,甚至喪失了原有框架的良好特性。

平臺化實踐

好的架構源于不停地衍變,而非設計。對于外賣 Android 客戶端的平臺化架構構建也是經歷了同樣的過程。

我們從考慮如何解決代碼復用的問題,逐漸的衍變成如何去解決代碼復用和平臺化的兩個問題。而實際上外賣平臺化正是解決兩端代碼復用的一劑良藥。

我們通過建立外賣平臺,將現有的外賣業務降級為一個頻道,將外賣業務以 aar 的形式分別接入到外賣平臺和美團平臺。這樣在解決外賣平臺化的同時,代碼復用的問題也將得到完美的解決。

平臺化架構

經過了整整一年的艱苦奮斗,形成了如圖所示的美團外賣 Android 客戶端平臺化架構,如下圖:

從底層到高層依次為平臺層、業務層和宿主層:

  • 平臺層,內容包括承載上層的數據通信和頁面跳轉;提供外賣核心服務,例如商品管理、訂單管理、購物車管理等;提供配置管理服務;提供統一的基礎設施能力,例如網絡、圖片、監控、報警、定位、分享、熱修、埋點、Crash 上報等;提供其他管理能力,例如生命周期管理、組件化等。
  • 業務層,內容包括外賣業務和垂直業務。
  • 宿主層,內容包括 Waimai App 殼和美團外賣頻道 Waimai-channel 殼,這一層用于 Application 的初始化、dex 加載和其他各種必要的組件或基礎庫的初始化。

在構建平臺化架構的過程中,我們遇到這樣一個問題,如何長久的維持我們平臺化架構的層級邊界。

試想,如果所有的代碼都在一個工程里面開發,通過包名、約定去規范層級邊界,任何一個緊急的需求都可能破壞層級邊界。

維持層級邊界的最好辦法是什么?我們的經驗是工程隔離。

平臺化的每一層都去做工程隔離,業務層的每個業務都建立自己的工程庫,實現工程隔離。同時,配套編譯腳本,檢查業務庫之間是否存在相互依賴關系。

工程隔離的好處是顯而易見的:

每個工程都可以獨立編譯、獨立打包。

每個工程內部的修改,不會影響其他工程。

業務庫工程可以快速拆分出來,集成到其他 App 中。

但工程隔離帶來的另一個問題是,同層間的業務庫需要通信怎么辦?這時候就需要提供業務庫通信框架來解決這個問題。

業務庫通信框架

在拆分外賣商家業務庫的時候,我們就發這樣一個案例:在商家頁有一個業務,當發現當前商家是打烊的,就會彈出一個浮層,推薦相似的商家列表,而在我們之前劃分的外賣子業務庫里面,相似商家列表應該是屬于頁面庫里面的內容。

那怎么讓商家業務庫訪問到頁面庫里面的代碼呢?如果我們將商家庫去依賴頁面庫,那我們的層級邊界就會被打破,我們的依賴關系也會變得復雜。

因此我們需要在架構中提供同層間的通信框架,它去解決不打破層級邊界的情況下,完成同層間的通信。

匯總同層間通信的場景,大致上可以劃分為:

  • 頁面的跳轉。
  • 基本數據類型的傳遞(包括可序列化的共有類對象的傳遞)。
  • 模塊內部自定義方法和類的調用。

針對上述情況,在我們的架構里面提供了二種平級間的通信方式:scheme 路由和美團自建的 ServiceLoaders sdk。

scheme 路由本質上是利用 Android 的 scheme 原理進行通信,ServiceLoader 本質上是利用的 Java 反射機制進行通信。

scheme 路由的調用如圖所示:

最終效果:所有業務頁面的跳轉,都需要通過平臺層的 scheme 路由去分發。通過 scheme 路由,所有業務都得到解耦,不再需要相互依賴而可以實現頁面的跳轉和基本數據類型的傳遞。

serviceloader 的調用如圖所示:

提供方和使用方通過平臺層的一個接口作為雙方交互的約束。使用方通過平臺層的 ServiceLoader 完成提供方的實現對象獲取。

這種方式可以解決模塊內部自定義方法和類的調用,例如我們之前提到了商家庫需要調用頁面庫代碼的問題就可以通過 ServiceLoader 解決。

外賣內核模塊設計

在實踐的過程中,我們也遇到業務本身就不好劃分層級邊界的業務。大家可以從美團外賣三層架構圖上,看出外賣業務庫,像商家、訂單等,是和外賣的垂類業務庫是同級的。

而實際上外賣業務的子業務是否應該和垂類業務保持同層是一個目前無法確定的事情。

目前,外賣接入的垂類業務商超業務,是隸屬于外賣業務的子頻道,它依然依賴著外賣的核心 Model、核心服務,包括商品管理、訂單管理、購物車管理等。

因此目前它和外賣業務的商家、訂單這樣的子業務庫同層是沒有問題的。但隨著商超業務的發展,商超業務未來可能會建設自己的商品管理、訂單管理、購物車管理的服務,那么到時商超業務就會上升到和外賣業務一樣同層的業務。

這時候,外賣核心管理服務,處在平臺層,就會導致架構的層級邊界變得不再清晰。

我們的解決辦法是通過設計一個屬于外賣業務的內核模塊來適應未來的變化,內核模塊的設計如圖:

  • 內圈為基礎模型類,這些模型類構成了外賣核心業務(從門店→點菜→購物車→訂單)的基礎。
  • 中間圈為依賴基礎模型類構建的基礎服務(CRUD)。
  • 最外圈為外賣的各維度業務,向內依賴基礎模型圈和外賣基礎服務圈。

如果未來確定外賣平臺需要接入更多和外賣平級的業務,且最內圈都完全不一樣,我們將把外賣內核模塊上移,在外賣業務子庫下建立對內核模塊的依賴。

如果未來只是有更多的外賣子業務的接入,那就繼續保留我們現在的架構;如果未來接入的業務基礎模型類一樣,但自己的業務服務需要分化,那么我們將保留內核模塊最核心的內圈,并抽象出服務層由外賣和商超上層自己實現真正的服務。

業務庫拆分

在拆分業務庫的時候,我們面臨著這樣的問題:業務之間的關系是較為復雜的,如何去拆分業務庫,才是較為合理的呢?

一開始我們準備根據外賣業務核心流程:頁面→商家→下單,去拆分外賣業務。

但是隨著外賣子頻道業務的快速發展,子頻道業務也建立了自己的研發團隊,在頁面、商家、下單等環節,也開始建立自己的頁面。

如果我們仍然按照外賣下單的流程去拆分庫,那在同一個庫之間,就會有外賣團隊和外賣子頻道團隊共同開發的情況,這樣職責邊界很不清晰,在實際的開發過程中,肯定會出現理不清的情況。

我們都知道軟件工程領域有所謂的康威定律:

Organizations which design systems are constrained to produce designs which are copies of the communication structures of these organizations. 

- Melvin Conway(1967)

翻譯成中文的大概意思是:設計系統的組織,其產生的設計等同于組織之內、組織之間的溝通結構。

在康威定理的指導下:我們認為技術架構應該反映出團隊的組織結構,同時,組織結構的變遷,也應該導致技術架構的演進。

美團外賣平臺下包含外賣業務和垂直品類業務,對于在我們團隊中已經有了組織結構,優先組織結構,去拆出獨立的業務庫,方便子業務庫的同學內部溝通協作,減少他們跨組織溝通的成本。

同時,我們將負責外賣業務的大團隊,再進一步細化成頁面小組、商家小組和訂單小組,由這些小組的同學去在外賣業務下完成更細維度的外賣子業務庫拆分。

根據組織結構劃分的業務庫,天然的存在業務邊界,每個同學都會按照自己業務的目標去繼續完善自己的業務庫。這樣的拆庫對內是高內聚,對外是低耦合的,有效的降低了內外溝通協作的成本。

工程內代碼隔離

在實現工程隔離之后,我們發現工程內部的代碼還是可以相互引用的。工程內部如果也不能實現代碼的隔離,那么工程內部的邊界就是模糊的。

我們希望工程內至少能夠實現頁面級別的代碼隔離,因為 Activity 是組成一個 App 的頁面單元,圍繞這個 Activity,通常會有大量的代碼及資源文件,我們希望這些代碼和資源文件是被集中管理的。

通常我們想到的做法是以 module 工程為單位的相互隔離,但在 module 是相對比較重的一個約束,難道每個 Activity 都要建一個 module 嗎?

這樣代碼結構會變得很復雜,而且針對一些大的業務體,又會形成巨大化的 module。

那我們又想到規范代碼,用包名去人為約定,但靠包名約束的代碼,邊界模糊,時不時的緊急需求,就把包名約定打破了,而且資源文件的擺放也是任意的,遷移成本高。

那怎么去解決工程內部的邊界問題呢?《微信的模塊化架構重構實踐》一文中提到了一個重要的概念 p(pins)工程,p 工程可謂是工程內約束代碼邊界的重要法寶。

通過在 Gradle 里面配置 sourceSets,就可以改變工程內的代碼結構目錄,完成代碼的隔離,配置示例:

效果如圖所示:

從上圖可以看出,這個業務庫被以頁面為單元拆分成了多個 p 工程,每個 p 工程的邊界都是清楚的,實現了工程內的代碼隔離。

工程內代碼隔離帶來的好處顯而易見:

  • p 工程實現了最小粒度的代碼邊界約束。
  • 工程內模塊職責清晰。
  • 業務模塊可以被快速的拆分出來。

代碼復用

p 工程滿足了工程內代碼隔離的需求,但是別忘了,我們每個模塊在外賣兩個終端上(外賣 App&美團 App)上可能存在差異,如果能在模塊內部實現兩端差異,我們的目標才算達成。

基于上述考慮,我們想到了使用 Gradle 提供的 productFlavors 來實現兩端的差異化。

為此,我們需要定義兩個 flavor:wm 和 mt。

但是,這樣生成的 p 工程是并列的,也就是說,各個 p 工程中所有的差異化代碼都需要被存放在這兩個 flavor 對應的 SourceSet 下,這豈不是跟模塊間代碼隔離的理念相違背?

理想的結構是在 p 工程內部進行 flavor 劃分,由 p 工程內部包容差異化,繼續改成 Gradle 腳本如下:

最終工程結構變成如下:

通過 p 工程和 flavor 的靈活應用,我們最終將業務庫配置成以 p 工程為維度的模塊單元,并在 p 工程內部兼容兩端的共性及差異,代碼復用被很好的解決了。

同時,兩端差異的問題是歸屬在 p 工程內部自己處理的,并沒有建立中間層,或將差異拋給上層殼工程去完成,這樣的設計遵守了邊界清晰,向下依賴的原則。

但是,工程內隔離也存在與工程隔離一樣的問題:同層級 p 工程需要通信怎么辦?

我們在拆分商家庫的時候,就面臨這這樣的問題,商品活動頁和商品詳情頁,可以根據頁面維度,去拆分成 2 個 p 工程,這兩個頁面都會用到同一個商品樣式的 item。

如何讓同層間商品活動頁 p 工程和商品詳情頁 p 工程訪問到商品樣式 item呢?

在實際拆庫的實踐中,我們逐漸的探索出三級工程結構。三級工程結構不僅可以解決工程內p工程通信的問題,而且可以保持架構的靈活性。

三級工程結構

三級工程結構,指的是工程→module→p 工程的三級結構。

我們可以將任何一個非常復雜的業務工程內部劃分成若干個獨立單元的 module 工程,同時獨立單元的 module 工程,我們可以繼續去劃分它內部的獨立 p 工程。

因為 module 是具備編譯時的代碼隔離的,邊界是不容易被打破的,它可以隨時升級為一個工程。

需要通信的 p 工程依賴 module 的主目錄,base 目錄,通過base目錄實現通信。

工程和 module 具有編譯上隔離代碼的能力,p 工程具有最小約束代碼邊界的能力,這樣的設計可以使得工程內邊界清晰,向下依賴。

設計如圖所示:

三級工程結構的最大好處就是,每級都可按照需要靈活的升級或降級,這樣靈活的升降級,可以隨時適應團隊組織結構的變化,保持架構拆分合并的靈活性,從而動態的滿足了康威定理。

工程化建設

平臺化一個直觀的結果就是產生了很多子庫,如何對這些子庫進行有效的工程化管理將是一個影響團隊研發效率的問題。目前為止,我們從以下兩個方面做了改進。

一鍵切源碼

主工程集成業務庫時,有兩種依賴模式:aar 依賴和源碼依賴。默認是 aar 依賴,但是在平時開發時,經常需要從 aar 依賴切換到源碼依賴,比如新需求開發、bugfix 及排查問題等。

正常情況我們需要在各個工程的 build. 中將 compile aar 手動改為 compile project,如果業務庫也需要依賴平臺庫源碼,也要做類似的操作。

如下圖所示:

這樣手動操作會帶來兩個問題:

  • build.gradle 改動頻繁,如果開發人員不小心 push 上去了,將會造成各種沖突。
  • 當業務庫越來越多時,這種改動的成本就越來越大了。

鑒于這種需求具備通用性,我們開發了一個 Gradle 插件,通過主工程的一個配置文件(被 git ignore),可一鍵切換至源碼依賴。

例如需要源碼依賴商家庫,那么只需要在主工程中將該庫的源碼依賴開關打開即可。商家庫還依賴平臺庫,默認也是 aar 依賴,如果想改成源碼依賴,也只需把開關打開即可。

一鍵打包

業務庫增多以后,構建流程也變得復雜起來,我們交付的產物有兩種:外賣 App 的 apk 和外賣頻道的 aar。

外賣 App 的情況會簡單一些,在 Jenkins 上關聯各個業務庫指定分支的源碼,直接打包即可。

而外賣頻道的情況則比較復雜,因為受到美團平臺的一些限制,頻道打包不能直接關聯各個業務庫的源碼,只能依賴 aar。

按照傳統做法,需要逐個打業務庫的 aar,然后統一在頻道工程中集成,最后再打頻道 aar,這樣效率實在太低。為此,我們改進了頻道的打包流程。

如下圖所示:

先打平臺庫 aar,打完后自動提 PR 到各個業務庫去修改平臺庫的版本號,接著再逐個觸發業務庫去打 aar。

業務庫打完 aar 之后再自動提 PR 到頻道主庫去修改業務庫的版本號,等全部業務庫 aar 打完后最后再自動觸發打頻道主庫的 aar,至此一鍵打包完畢。

平臺化總結

從搜索庫拆分的第一次嘗試算起,外賣 Android 客戶端在架構上的持續探索和實踐已經經歷了 2 年多的時間。

起初為了解決兩端代碼復用的問題,我們嘗試過自上而下的強行拆分和復用,但很快就暴露出層次混亂、邊界模糊帶來的問題,并且認識到如果不能提供兩端差異化的解決方案,代碼復用是很難持續的。

后來我們又嘗試過運用設計模式約束邊界,先實現解耦再進行復用,但在推廣落地過程中認識到復雜的設計很難快速推進下去。

在平臺化開始的時候,團隊已經形成了設計簡單、邊界清晰的架構理念。我們將整體結構劃分為宿主層、業務層、平臺層,并嚴格約束層次間的依賴關系。

在業務模塊拆分的過程中,我們借鑒微信的工程結構方案,按照三級工程結構劃分業務邊界,實現靈活的代碼隔離,并降低了后續模塊遷出和遷入成本,使得架構動態滿足康威定律。

在兩端代碼復用的問題上,我們認識到要實現可持續的代碼復用,必須自下向上的逐步統一兩端底層的基礎依賴,同時又能容易的支持兩端上層業務的差異化處理。

使用 Flavor 管理兩端的差異代碼,盡量減少向上依賴,在具體實施時應用之前積累的解耦設計的經驗,從而滿足了架構的可伸縮性。

沒有一個方案能獲得每個人的贊同。在平臺化的實施過程中,團隊成員多次對方案選型發生過針鋒相對的討論。

這時我們會拋開技術方案,回到問題本身,去重新審視業務的痛點,列出要解決的問題,再回過頭來看哪一個方案能夠解決問題。

雖然我們并不常常這么做,但某些時刻也會強制決策和實施,遇到問題再復盤和調整。

任何一種設計理念都有其適用場景。我們在不斷關注業內一些優秀的架構和設計理念,以及公司內部美團 App、點評 App 團隊的平臺化實踐經驗,學習和借鑒了許多優秀的設計思想,但也由于盲目濫用踩過不少坑。

我們認識到架構的選擇正如其他技術問題一樣,應該是面向問題的,而不是面向技術本身。

架構的演進必須在理論和實踐中交替前行,脫離了其中一個談論架構,都將是個悲劇。

展望

平臺化之后,各業務團隊的協作關系和開發流程都發生了很大轉變。在如何提升平臺支持能力,如何保持架構的穩定性,如何使得各業務進一步解耦等問題上,我們又將面對新的問題和挑戰。

其中有三個問題是亟待我們解決的:

  • 要確保在長期的業務迭代中架構不被破壞,除了流程規范之外,還需要在本地編譯、遠程提交、代碼合并、打包提測等各個階段建立更健全的檢查工具來約束,而目前這些工具鏈還不完善。
  • 插件化架構是平臺型 App 集成的最好方式,不僅使得子業務具備動態發布的能力,還可以解決令人頭疼的編譯速度問題。目前美團平臺已經在部分業務上較好的實現了插件化集成,外賣正在跟進。
  • 統一頁面級開發的標準化框架,可以解決代碼的可維護性、可測試性,和更細粒度的可復用性,并且有利于各種自動化方案的實施。目前我們正在部分業務嘗試,后續會持續推進。

參考資料:

  • MVP + Clean Architecture
  • 58同城沈劍:好的架構源于不停地衍變,而非設計
  • 每個架構師都應該研究下康威定理
  • 微服務架構的理論基礎 - 康威定律
  • 架構的本質是管理復雜性,微服務本身也是架構演化的結果
  • 微信 Android 模塊化架構重構實踐
  • 配置構建變體
  • 美團 App 插件化實踐

作者:吳凱、曉飛、海冰

吳凱,美團點評技術專家。2016 年加入美團點評,目前負責外賣用戶端 Android 團隊,主要致力于外賣 Android 平臺化業務支持和技術建設。

曉飛,美團點評資深工程師。2015 年加入原美團,是外賣 Android 的早期開發者之一,目前作為外賣 Android App 負責人,主要負責平臺和業務架構。

海冰,美團點評高級工程師。2015 年加入原美團,曾支持開店寶等 B 端業務,目前作為外賣 Android App 主力開發,負責商家容器模塊,及平臺化相關推進工作。

責任編輯:武曉燕 來源: 美團點評技術團隊
相關推薦

2016-11-27 20:43:26

云計算迭代

2022-04-29 09:10:00

算法人工智能技術

2022-08-09 09:18:47

優化實踐

2022-03-25 10:47:59

架構實踐美團

2018-07-13 09:53:27

移動應用美團代碼

2022-08-26 20:00:00

系統架構

2022-08-25 22:24:19

架構電商系統

2018-12-07 12:54:22

App美團外賣iOS客戶端

2017-12-08 18:45:41

程序員外賣運維

2017-06-01 10:52:35

互聯網

2017-07-03 15:32:49

數據庫MySQL架構

2017-12-29 08:54:58

高可用數據庫架構

2018-01-19 14:04:05

人工智能機器學習智能語音

2022-08-09 08:42:15

引擎方案

2019-08-23 13:10:39

美團點評Kubernetes集群管理

2023-11-14 20:51:08

2018-06-01 10:08:00

DBA美團SQL

2017-03-22 17:51:43

互聯網

2015-11-16 16:00:21

點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 亚洲精品久久久久久一区二区 | 欧美另类视频在线 | 国产真实乱对白精彩久久小说 | caoporn免费 | 日本在线免费观看 | 18成人在线观看 | 国产中文一区二区三区 | 日本人和亚洲人zjzjhd | 日本一区二区高清不卡 | 国产成人精品免费视频大全最热 | 国产精品18hdxxxⅹ在线 | 一级毛片大全免费播放 | 欧洲亚洲一区 | 999视频 | 激情影院久久 | 日韩精品福利 | 91免费版在线观看 | 成人三级视频在线观看 | 91在线观看 | 日韩亚洲视频 | 欧美精品一区免费 | 亚洲欧美中文日韩在线v日本 | 日韩av一二三区 | 福利片在线观看 | 亚洲国产精品99久久久久久久久 | 日本成人久久 | 欧美激情a∨在线视频播放 成人免费共享视频 | 中文字幕亚洲视频 | 黑人巨大精品欧美黑白配亚洲 | 黄色亚洲 | 亚洲福利电影网 | 日韩精品在线免费观看 | 日日夜夜免费精品 | 国产99久久精品一区二区永久免费 | 欧美激情99 | 99成人| 一区二区三区高清 | 亚洲综合视频 | 一级黄色影片在线观看 | 成人三区四区 | 久久久www成人免费无遮挡大片 |