摘要:移動精英開發(fā)社群的第期,也是圍繞架構(gòu)這個話題進行討論。本次我們希望結(jié)合實際開發(fā)中遇到的問題,來聊聊移動端的架構(gòu)設計。這樣的模式改進一些,可能會更適合移動端架構(gòu)。潘衛(wèi)杰之前我們公司移動端的大項目就是插座式開發(fā)的,批量出各個行業(yè)的。
此前,58 同城的技術委員會執(zhí)行主席沈劍在 OneAPM 的技術公開課上分享過一個主題,「好的架構(gòu)不是設計出來的,而是演技出來的」。因為對很多創(chuàng)業(yè)公司而言,隨著業(yè)務的發(fā)展,網(wǎng)站流量或者移動端用戶都會經(jīng)歷不同的階段。前期的時候,很難去設計一個百萬或者千萬級并發(fā)的架構(gòu),所以后期往往不斷對架構(gòu)進行更新迭代。
當然,在這里也推薦一篇文章《移動開發(fā)中的痛點》,本文是 infoQ 舉辦線下聚會的一次討論整理,當時參與的討論者包括唐巧、郭亮、郭虹宇、鄧宇光、代碼家等國內(nèi)知名移動開發(fā)者。其中就談及了 MVC 架構(gòu)的痛點,以及 React Native 所代表的 Web 開發(fā) Native App 技術,相信會對大家有所啟發(fā)。移動精英開發(fā)社群的第8期,也是圍繞「架構(gòu)」這個話題進行討論。本文系滴滴出行的劉佳達整理。
以下為討論內(nèi)容整理:
主持人韓兵:「架構(gòu)」對開發(fā)者而言就是「高大上」,當然也不是每位 coder 都能搞定。對很多菜鳥而言就更陌生了,基本只能停留在理論層次。實踐才能出真知,一個好的架構(gòu)也是這樣產(chǎn)生的。本次我們希望結(jié)合實際開發(fā)中遇到的問題,來聊聊移動端的架構(gòu)設計。
李文杰:我們的項目劃分成了:數(shù)據(jù)層、UI 層、邏輯層。
上海-李博:我們使用的是 MVVM(Model-View-ViewModel),然后使用了一些 React Native。
韓兵:MVC 這樣的模式可以代替咱們移動端架構(gòu)嗎?
攻城獅:MVC、MVVM 只是一種設計模式而已。
Wallace:個人認為, MVC 這種經(jīng)典結(jié)構(gòu)已經(jīng)滿足不了現(xiàn)在的需求了。
Rory:MVC 這樣的模式改進一些,可能會更適合移動端架構(gòu)。從業(yè)務邏輯的角度看,架構(gòu)應該服從業(yè)務邏輯。
王威特-明道-ios:基于團隊、服務于團隊的代碼基礎規(guī)范包含開發(fā)模式,代碼規(guī)范等等。
Draven-ios:我認為,MVVM + React Native 能讓開發(fā)變得輕松很多。
李文杰-上海數(shù)云-ios:特別希望有一套成熟的架構(gòu),UI 和邏輯都寫好了。只要寫寫數(shù)據(jù)就可以用了。我針對的是超快速的簡單需求 APP 開發(fā),就像很多建站技術一樣,「拖一拖」就可以完成。
攻城獅:功能模塊化也是架構(gòu)中很重要的一環(huán)。
小龍:萬變不離其宗,天下武功出一家! 移動端各路設計不也是圍繞著 MVC 控制顯示數(shù)據(jù),然后再做各種拆分嗎?
露露:模塊與模塊之間,應該能快速拆分然后移植到新的項目中吧?
蜂鳥:用 React 基于響應式函數(shù)編程是可以簡化實現(xiàn)過程,省很多代碼。
劉玉嬌-小鄰小里-ios:問下大家網(wǎng)絡層搭建用的是 delegate 還是 block ?我們后來用的,發(fā)現(xiàn)好像 delegate 會好一點。
Draven-ios:block 比較靈活。
王宇-陸金所-ios:但是 block 寫的太隨意了。
Draven-ios:delegate 看起來比較規(guī)范。
小龍:block 是方便,但別忘了它是一個結(jié)構(gòu)體。
蜂鳥:昨天碰到一個問題,就是一個 App 有100多個人共同開發(fā),怎么設計架構(gòu)?才能讓100個人協(xié)同開發(fā)不出問題?
A-困惑:一般用 block。
Icocos:之前有人討論過,說用 MVP 比較好。
小龍:如果東西多了很重的,delegate 傳的時候只是一個指針。
進擊的小比克:一部分做網(wǎng)絡層,一部分做業(yè)務邏輯,一部分做 UI。
王威特-明道-ios:delegate 書寫規(guī)范,也可以避免循環(huán)引用的問題。block 書寫流暢,但是會把網(wǎng)絡的代碼分散在各處,最終維護不一定好。建議在網(wǎng)絡業(yè)務種的結(jié)構(gòu)內(nèi)用 delegate,反之block更方便。
露露:如果幾個實例用一個 delegate,需要判斷。
上海-李博:我覺得,進行工程性的管理,還是比較好。各做各的業(yè)務,淘寶就是采用這種模式。相當于每個業(yè)務維護一個工程。
潘衛(wèi)杰:可以使用插座式的模塊開發(fā)。分成多個小 Team ,負責相對獨立的業(yè)務功能開發(fā),每個 Team 配一個測試,通過了就提交,隨時可以打包出成品。
韓兵:之前也有人說了,架構(gòu)是不僅僅是為了方便業(yè)務,還有一個是為了我們 coder 快速開發(fā)。那架構(gòu)解決了我們項目開發(fā)中的什么問題?
露露:現(xiàn)在 block 用的很多,但是怎么才算使用的好呢?
小龍:delegate 是指針,block 是結(jié)構(gòu)體,一個傳遞的時候輕,但寫著麻煩,一個寫著方便傳遞的時候比較重。
潘衛(wèi)杰:之前我們公司移動端的大項目就是「插座式」開發(fā)的,批量出各個行業(yè)的 App。
Rory:移動架構(gòu)設計和選型根據(jù)我的經(jīng)驗應該遵守以下幾個原則吧:
優(yōu)先保證業(yè)務邏輯;
架構(gòu)設計遵循簡潔的原則;
架構(gòu)的學習成本不要太高,需要符合當前技術團隊內(nèi)開發(fā)人員的能力范圍;
架構(gòu)是在開發(fā)過程中不斷擴充和維護的,代碼重構(gòu)也是架構(gòu)的核心之一。
劉玉嬌:還有個問題,大家 VC 的分層是 base 然后下邊分為 baselist 和 baseentity 然后往下繼承嗎?
上海-李博:我感覺上面說的繼承這樣下去會越來越痛苦
潘衛(wèi)杰:前年的時候,行業(yè)內(nèi)有一個說法:各個行業(yè)扁平化,去中心化,很多行業(yè)老板也都想有自己的電子商務平臺。我們之前就給他們解決這個問題,但是我們又不能每家都出一個,就用這種方式出一個很多功能的,各家用的時候在后臺自定義組合。
小龍:高內(nèi)聚低耦合!
Noark9:以前公司做一個 Windows 上應用的覺得思路可以借鑒:我們有一個比較大的,我們稱為 shell(殼程序),然后,殼程序提供了接口請求的框架,用戶信息的接口,發(fā)送通知,以及一些公共的功能。然后,每個小功能,都作為一個動態(tài)庫接入,殼程序負責加載下載下來的動態(tài)庫,然后打開到界面上。
王宇-陸金所-ios:具體怎么和業(yè)務模塊拆分方法呢?
韓兵:服務端都是重架構(gòu),一般移動端都偏輕架構(gòu)。
王威特:是,繼承的耦合性太重。用組合的方式更好,前幾天的一篇文章就非常推薦閱讀。
http://blog.yongfengzhang.com/cn/blog/write-code-that-is-easy-to-delete-not-easy-to/
Rory:理論上,架構(gòu)不一定要多復雜。但是至少簡明的可以區(qū)分組件、組件的邏輯、業(yè)務邏輯、數(shù)據(jù)層。讓組件的邏輯和業(yè)務邏輯分離,減少代碼耦合;方法的適量重載和重寫;在項目的維護期,抽離項目特有的組件。
蜂鳥:具體到寫代碼,就是多用接口,定義個協(xié)議來實現(xiàn)后使用它。
小龍:面向協(xié)議就是看接口定義的怎么樣了??梢园迅餍袠I(yè)一些特性歸類為某一類屬性,統(tǒng)一處理,最后用的時候換個皮,換套文案就可以。
蜂鳥:API 接口定義的好,說明模塊分離,邊界定義的很清楚。
小龍:面向協(xié)議的變成是不是給 ViewController 暴露的都是 id<某個協(xié)議> ?這種形式的,而不需要 import 具體的類?求解答。
你該休息了:Android 架構(gòu)中熱部署大家常采用的多嗎 ?
李哲-京東:我重寫的時候,就遵循的就是各個模塊的拆分。將業(yè)務,功能,包括很小的通知名,顏色,緩存路徑都搞成了宏定義。將網(wǎng)絡,數(shù)據(jù),業(yè)務,功能都剝離了出來。
王威特:宏定義寫起來有些難堪,用 const string 不是更好嗎?
韓兵:可以推薦一些架構(gòu)設計比較好的來源代碼
阿塵:個人感覺,要深入移動架構(gòu),必須了解企業(yè)應用架構(gòu)。開源的完整 App 應該比較少。為什么要有架構(gòu)?根本原因還是在于復雜性。頭一次看到就五體投地,之前用 NimbusKit 搭架構(gòu),現(xiàn)在打算轉(zhuǎn)向 YYKit 。簡單的 App 是不需要架構(gòu)的。
李哲:將一些業(yè)務的解決方法,使用模型思想去解決,尤其是那個微博列表的設計。要寫易刪除,而不易擴展的代碼。
阿塵:個人感覺,合理的分層設計很關鍵。
哈哈:比如微信 SDK,集成了登錄、分享、支付三個大的功能,不支持多帶帶拆分使用,如果之前已經(jīng)使用了友盟、shareSDK 等,只想接入微信支付功能,就會出現(xiàn)沖突問題。
阿塵:架構(gòu)的構(gòu)建是一個不斷權(quán)衡的過程。
有一個道理:架構(gòu)的構(gòu)建是一個不斷權(quán)衡的過程?這個有點不同意。
蜂鳥:我覺得架構(gòu)之所以需要,就是要保持一個基本的穩(wěn)定架構(gòu),別變來變?nèi)サ?。再變也是細?jié)和模塊功能的補充,跳不出已經(jīng)設定好的架構(gòu)。
韓兵:好的東西都不是不斷改,不斷優(yōu)化的。
小龍:響應式編程思想:不需要考慮調(diào)用順序,只需要知道考慮結(jié)果,類似于蝴蝶效應,產(chǎn)生一個事件,會影響很多東西,這些事件像流一樣的傳播出去,然后影響結(jié)果,借用面向?qū)ο蟮囊痪湓挘f物皆是流。
而函數(shù)式編程思想是把操作盡量寫成一系列嵌套的函數(shù)或者方法調(diào)用。函數(shù)式編程特點:每個方法必須有返回值(本身對象),把函數(shù)或者 Block 當做參數(shù),block 參數(shù)(需要操作的值)block 返回值(操作結(jié)果)。
代表:ReactiveCocoa。
李哲-京東:而一個好的架構(gòu)也總是在業(yè)務不斷變化中慢慢變好的。
小龍:鏈式編程思想:是將多個操作(多行代碼)通過點號(.)鏈接在一起成為一句代碼,使代碼可讀性好。a(1).b(2).c(3)
鏈式編程特點:方法的返回值是 block,block 必須有返回值(本身對象),block 參數(shù)(需要操作的值)
代表:masonry 框架。
蜂鳥:如果架構(gòu)總是變來變?nèi)?,恰恰證明了架構(gòu)設計的不合理。
攻城獅:現(xiàn)在好多大公司有個技術平臺部,把一些功能抽象出來模塊化,這樣業(yè)務線開發(fā)就簡單很多,效率也高了。
阿塵:架構(gòu)是一組決策的組合,做每個決策的過程都是一次取舍和權(quán)衡,這樣理解嗎?我覺得,實踐出真知,從0開始打造一個復雜 App 的過程,會讓你受益匪淺。
王威特:這回到主持人說的,架構(gòu)是經(jīng)驗積累出來的,慢慢來。即使做了一個壞架構(gòu),以后和別人的對比下就收獲頗豐了。
攻城獅:架構(gòu)不是一下就有的,走過才知道捷徑。
蜂鳥:同意你說的決策的取舍平衡,我的看法是這種決策取舍越少越好。好的架構(gòu)應該能有空間適應這種業(yè)務的變化,預見到也許會有的改動,有點理想化了。
王威特:一個長期迭代的 App 做的就是架構(gòu)和業(yè)務,架構(gòu)能力也是慢慢磨出來的。如果在外包公司工作,更要做好架構(gòu),才能快速開發(fā)。
攻城獅:有些公司 iOS 頁面跳轉(zhuǎn)是統(tǒng)一的一個管理類來管理的,在座各位有這么做的嗎?
進擊的小比克:現(xiàn)在的項目既按功能模塊分,又分業(yè)務邏輯、網(wǎng)絡層、數(shù)據(jù)層,分得有點亂??!和網(wǎng)絡服務器框架一樣。
高山:比如一個頁面,需要 abcd 四個頁面才能過來,現(xiàn)在一個 url ,很多前置條件都沒有,可能導致錯誤。這就對架構(gòu)解耦提出更高的要求。
王威特:最早 ABRouter ,你給 viewController 寫個 category 就行了。這里說的是iOS,用 router 實現(xiàn)跳轉(zhuǎn),一個極大的極大的便利就是以后你的 App 需要實現(xiàn)從 safari 瀏覽器打開 App ,發(fā)現(xiàn)你都搞定了。
韓兵:好像咱們討論組做服務端的人不多。什么是服務端架構(gòu)?服務端涉及的東西太多。只有親自設計過和處理過數(shù)量級比較大的系統(tǒng),才可能會對架構(gòu)有所體悟。要不然很可能是「紙上談兵」。
Wallace:其實好的架構(gòu),無非是能在你現(xiàn)有的情況下,能解決實際中存在的問題。有些很牛逼的架構(gòu)不一定適用于現(xiàn)在的具體場景。
韓兵:本身架構(gòu)包含的知識就很多,不僅僅一門編程語言。
攻城獅:Java 比較成熟,但是提供的架構(gòu)還有一些并不是很成熟。
檸檬:從頭看了下,都是偏于理論,對于架構(gòu)還是沒什么印象,比如說 MVC,這也是最基本的。但是如何做到架構(gòu)師級別?求指教。
檸檬:最近在整理一些知識,個人感覺,想能為架構(gòu)師,就是把基本的東西包「打包」在一個項目中。
Wallace:其實寫的時間長了,很自然的就能時刻考慮到「高內(nèi)聚低耦合」的思維了。尤其是,寫完一個模塊后也可以錘煉自己。
韓兵:設計一個 App,首先應該考慮的就是它的架構(gòu)。先把結(jié)構(gòu)搭建起來,網(wǎng)絡層封裝好,第三方控件封裝好,然后最快速度支撐起業(yè)務層。其實在實際開發(fā)中,沒有那么多時間成本,還是需要優(yōu)化一些東西。
丁建龍:模塊化,最少的暴露參數(shù)和接口。
檸檬:目前所面臨的代碼質(zhì)量問題,絕大部分不是技術問題,不是 coding 能力問題,是節(jié)奏把控,是質(zhì)量觀念的問題,如何平衡 scope 、quality、schedule,這不是自下而上的變革,是自上而下的思想改變,每一個技術 leader 都需要去權(quán)衡把控。
一切質(zhì)量問題,本質(zhì)上就是技術 leader 的問題,很多人可能會說,業(yè)務需求太多,工作量太大,跑得太快,這些都是事實,事實的背后是,我們技術有沒有真正去理解業(yè)務,理解產(chǎn)品的思路和想法,理解業(yè)務的核心訴求和難點,大家一定可以平衡好這三方面的關系。
韓兵:大家的項目都是怎么搭建起來的?
檸檬:我們是第一版肯定是快速出原形,看用戶的功能,兩周一個迭代。成型后重構(gòu)。
Rory:初期:簡易架構(gòu),實現(xiàn)基礎功能,組件;開發(fā)過程中:迭代豐富組件,抽離業(yè)務,形成模塊化。像初期選型,我可以用諾遠目前1.0->1.1的版本發(fā)展歷程舉個例子。后期維護擴容,可以用365日歷的 Android 客戶端舉個例子。
韓兵:這個只有實踐過,才可能會有一些感悟。說說大家 App 從無到有的構(gòu)建過程。從這個過程中理解架構(gòu)的形成和運作。個人覺得從這點入手,會容易理解一些。
檸檬:架構(gòu)看功力,架構(gòu)師的路很長,不斷的被指責,改進的過程,這是漫長的過程。我現(xiàn)在的想法是把幾乎所有項目都用到的東西,整理在一個項目下,以后獨立開發(fā)可以直接運用。還可以把整個項目底層做一個基類。
Rory:目前互聯(lián)網(wǎng)行業(yè)主要還是敏捷開發(fā),所以初期選型的時候,其實架構(gòu)細分顯得不是很重要,倒是架構(gòu)上為后期模塊化,可擴展性的方面考慮更多。比如,小諾理財 Android 客戶端,初期架構(gòu)只做了網(wǎng)絡層,數(shù)據(jù)解析,activity 基類封裝,圖片緩存,和一些常用的 UI 組件。
露露:我覺得你可以整合,但是如果用了某一個功能,能快速拆分。
Wallace:我曾經(jīng)最開始工作的時候,以為把見過的東西都存下來,到時候用上,但其實都沒用上。
Rory:整體上業(yè)務結(jié)構(gòu)初期都是在 Activity 中處理的,沒有做業(yè)務邏輯的抽離。從1.0-1.1的過程中,這邊的 Android 技術團隊進行了一些重構(gòu)和業(yè)務抽離,構(gòu)建基礎。形成目前定制的 UI組件庫(目前 UI 組件的邏輯仍然未進行細致抽離)、業(yè)務邏輯 control 單元(目前是依據(jù)業(yè)務模塊的不同,抽離不同模塊的 control。)這么做,主要的目的是為了后續(xù)新加入的技術,可以快速熟悉項目,了解業(yè)務。
韓兵:如果這個項目越做越大,咱們就暫定理財項目,是不是要考慮底層框架對現(xiàn)有業(yè)務的支持?如果團隊越來越大,是不是還要考慮對n多個團隊的支持?
Rory:理財和支付一樣,對數(shù)據(jù)安全和通信安全比較重視。
阿塵:橫向業(yè)務模塊化,豎向低耦合,做到單向依賴。
Rory:曾經(jīng)參與過,365日歷 Android 客戶端的后期維護。當時客戶端項目到了后期,模塊劃分會越來越多,項目會變得越來越臃腫。這時候在 java 層面和 Android framework 層的優(yōu)化其實更少。
多數(shù)組件這時候都已經(jīng)很成熟,這時候需要集成性能測試,針對某一點上進行細節(jié)優(yōu)化。架構(gòu)上也是抽離出更多的庫,進行細分支持。365日歷其實是典型的 MVC 向 MVP 的過渡。當然,我離職的時候這個過渡還未完成。基本上雛形可以看到,UI 層和業(yè)務層已經(jīng)進行深度劃分,通過 control 控制數(shù)據(jù)傳遞和通信。
MVP,個人經(jīng)驗更適合移動端,移動端開發(fā)的主要難點是兩個,業(yè)務邏輯和界面效果。
韓兵:所以移動端和服務端考慮的點也是不一樣的!
Rory:把 UI 和業(yè)務邏輯區(qū)分,這樣控制單元更有針對性,對原有業(yè)務或者UI的修改更有針對性,迭代過程中產(chǎn)生錯誤理解和錯誤邏輯導致 bug 的可能性也更小。
可能因為這樣抽離后,新技術的加入,理解項目需要更長的時間。代碼閱讀性會隨著項目的臃腫變得越來越差。所以必要的抽離就是保證代碼的可讀性。
過渡重構(gòu)舉個很簡單的例子,一個 View 的 UI 邏輯非要強行適應整個項目所有的 View,創(chuàng)造 n 個構(gòu)造,傳入多個控制參數(shù)。那么邏輯理解起來是不是很困難?最簡單的判定標準,代碼的創(chuàng)造者如果隔一段時間都很難讀得懂自己寫的代碼,算不算一種過度?
簡單的總結(jié)下,架構(gòu)應該隨著項目發(fā)展不斷發(fā)展,一成不變的架構(gòu)是行不通的!
國內(nèi) ITOM 管理平臺 OneAPM 致力于幫助企業(yè)用戶提供全棧式的性能管理以及 IT 運維管理服務,通過一個探針就能夠完成日志分析、安全防護、APM 基礎組件監(jiān)控、集成報警以及大數(shù)據(jù)分析等功能。想閱讀更多優(yōu)秀文章,請訪問 OneAPM 官方技術博客
本文轉(zhuǎn)自 OneAPM 官方博客
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/11737.html
摘要:解決方法如果使用頁面數(shù)據(jù)不超過一屏禁止?jié)L動,那么即使變成了頁面也不會有什么變化。 作者:@micky思 @wupq @yewq 在H5的開發(fā)中,個人的制作頁面布局習性不同,多多少少會產(chǎn)生在真機上input的光標和鍵盤的彈出會出現(xiàn)的各種BUG,文中整理了部分遇到的問題,歡迎新增 ios移動端輸入框上浮導致輸入位置偏移 問題原因:遮罩層定位為fixed,當鍵盤彈起時,ios11以及以下...
摘要:解決方法如果使用頁面數(shù)據(jù)不超過一屏禁止?jié)L動,那么即使變成了頁面也不會有什么變化。 作者:@micky思 @wupq @yewq 在H5的開發(fā)中,個人的制作頁面布局習性不同,多多少少會產(chǎn)生在真機上input的光標和鍵盤的彈出會出現(xiàn)的各種BUG,文中整理了部分遇到的問題,歡迎新增 ios移動端輸入框上浮導致輸入位置偏移 問題原因:遮罩層定位為fixed,當鍵盤彈起時,ios11以及以下...
摘要:解決方法如果使用頁面數(shù)據(jù)不超過一屏禁止?jié)L動,那么即使變成了頁面也不會有什么變化。 作者:@micky思 @wupq @yewq 在H5的開發(fā)中,個人的制作頁面布局習性不同,多多少少會產(chǎn)生在真機上input的光標和鍵盤的彈出會出現(xiàn)的各種BUG,文中整理了部分遇到的問題,歡迎新增 ios移動端輸入框上浮導致輸入位置偏移 問題原因:遮罩層定位為fixed,當鍵盤彈起時,ios11以及以下...
摘要:單頁面應用的出現(xiàn)依然存在著爭議性,我們該如何看待他的兩面性呢接下來小生給大家總結(jié)一下他的優(yōu)缺點。單頁面應用的優(yōu)勢無刷新體驗沒有了令人詬病的頁面頻繁刷新,同時節(jié)約瀏覽器資源,路由響應比較及時,提升了用戶的體驗。 前端猿一天不學習就沒飯吃了,后端猿三天不學習仍舊有白米飯擺于桌前。IT行業(yè)的快速發(fā)展一直在推動著前端技術棧在不斷地更新?lián)Q代,前端的發(fā)展成了互聯(lián)網(wǎng)時代的一個縮影。而單頁面應用的發(fā)展...
閱讀 2248·2021-11-24 11:15
閱讀 3099·2021-11-24 10:46
閱讀 1400·2021-11-24 09:39
閱讀 3933·2021-08-18 10:21
閱讀 1488·2019-08-30 15:53
閱讀 1402·2019-08-30 11:19
閱讀 3335·2019-08-29 18:42
閱讀 2333·2019-08-29 16:58