日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

源码阅读中的收获

發(fā)布時(shí)間:2025/3/20 编程问答 14 豆豆
生活随笔 收集整理的這篇文章主要介紹了 源码阅读中的收获 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

最近在做短視頻相關(guān)的模塊,于是在看 GPUImage 的源碼。其實(shí)有一定了解的伙伴一定知道 GPUImage 是通過 addTarget 鏈條的形式添加每一個(gè)環(huán)節(jié)。在對(duì)于這樣的設(shè)計(jì)贊嘆之余,想到了實(shí)際開發(fā)場(chǎng)景下可以用到的場(chǎng)景,借此分享。

我們的項(xiàng)目中應(yīng)該有很多的聚合頁,每個(gè)聚合頁上都有 feed 流,而在很多的項(xiàng)目中 feed 流的場(chǎng)景都是可以進(jìn)行復(fù)用的。而在這樣的場(chǎng)景下我們希望復(fù)用的 feed 流中的 cell 可以在多個(gè)界面上進(jìn)行復(fù)用。但是如果每一個(gè) cell 上又有幾個(gè)點(diǎn)擊事件,如果每一個(gè) Controller 上都有一堆的事件處理代碼,又會(huì)代碼冗余量巨大。

開發(fā)中遇到的痛點(diǎn)

隨便舉個(gè)例子,微博的信息流,微博很多業(yè)務(wù)都是這樣的界面進(jìn)行展示,如果每個(gè) cell 的點(diǎn)擊事件代理回 controller 中進(jìn)行執(zhí)行,那 controller 有多重可想而知... 而且一旦以后業(yè)務(wù)調(diào)整,某些跳轉(zhuǎn)頁面更改,波及的頁面之廣,也是無法接受的。

這個(gè)時(shí)候就會(huì)想可不可以在一個(gè)地方固定的處理這些事件?

一些解決方案

我記得對(duì)于這個(gè)問題, 源神 曾經(jīng)提出過 self-manager 的概念可以解決類似的問題。在源神的解決方案中,feed 按鈕的功能相對(duì)單一這樣的方式是一種較好的方案,但是 feed 上的按鈕根據(jù)業(yè)務(wù)場(chǎng)景做不一樣的跳轉(zhuǎn),這樣的處理又該如何處理呢? 其實(shí)對(duì)于源神的方案其實(shí)傳入枚舉,對(duì)它做對(duì)應(yīng)的處理就可以了。

還是用微博進(jìn)行舉例,現(xiàn)在我們有A,B,C三條業(yè)務(wù)線都會(huì)對(duì)會(huì)有 feed 展示這個(gè) cell。

  • A 業(yè)務(wù)線要求就是要求底部 tabbar 是轉(zhuǎn)發(fā),評(píng)論和點(diǎn)贊的功能
  • B 業(yè)務(wù)線的要求是轉(zhuǎn)發(fā)的按鈕是跳轉(zhuǎn)到業(yè)務(wù)線 A, 評(píng)論按鈕的點(diǎn)擊事件跳轉(zhuǎn)到業(yè)務(wù)線C,點(diǎn)贊按鈕的功能保留
  • C 業(yè)務(wù)線的要求是轉(zhuǎn)發(fā)的按鈕跳轉(zhuǎn)到業(yè)務(wù)線 B, 評(píng)論的按鈕保留原功能,點(diǎn)贊的按鈕跳轉(zhuǎn)到業(yè)務(wù)線 B 這樣的操作。

對(duì)于這樣的惡心要求(不要覺得我天馬行空,我真的遇到過這類似的業(yè)務(wù)場(chǎng)景,而且也確實(shí)有對(duì)應(yīng)的需要),如果此時(shí)還是使用 self-manager,來對(duì)狀態(tài)進(jìn)行判斷。可能偽代碼的結(jié)構(gòu)大致如下。

typedef NS_ENUM(NSInteger,BusinessLineType){BusinessLineTypeA = 0,BusinessLineTypeB,BusinessLineTypeC, }typedef NS_ENUM(NSInteger,CommentBtnHandleType){CommentHandleTypeA = 0,CommentHandleTypeB,CommentHandleTypeC, }......-(viod)configureCellWithBusiness:(BusinessLineType)businessType{//根據(jù) businseeType 進(jìn)行判斷 將評(píng)論點(diǎn)擊事件的枚舉傳入下一級(jí) 然后正確響應(yīng)點(diǎn)擊事件//根據(jù) businseeType 進(jìn)行判斷 將轉(zhuǎn)發(fā)按鈕事件根據(jù)業(yè)務(wù)線枚舉講點(diǎn)擊枚舉傳入下一級(jí)...} 復(fù)制代碼

不知道大家對(duì)于這樣的代碼看到后的感受是怎么樣的,但是我可以設(shè)想到,在沒有足夠的文檔說明的情況下,如果組里來了一個(gè)新的小伙伴或者讓一個(gè)對(duì)當(dāng)前業(yè)務(wù)場(chǎng)景不足夠熟悉的小伙伴進(jìn)行維護(hù),一定很抓狂,感覺這樣的形式在維護(hù)上的成本還是比較高的。所以這樣的方案還是比較適合處理業(yè)務(wù)上職責(zé)比較單一的小塊。

此外對(duì)于大廠可能有一條業(yè)務(wù)線的業(yè)務(wù)代碼需要使用到多個(gè)產(chǎn)品中的情況,這樣的方案一樣也就不再適用了。因?yàn)?view 層承接了業(yè)務(wù)。 而兩個(gè)產(chǎn)品的設(shè)計(jì)并不相同,但是業(yè)務(wù)的邏輯是相同的,這個(gè)時(shí)候就不是簡(jiǎn)單的替換 view 層就能完成功能添加那么簡(jiǎn)單的問題了。

###曾經(jīng)的方案

基于上邊的復(fù)雜業(yè)務(wù)可讀性差和讓業(yè)務(wù)和 view 完全解耦的思路,這個(gè)時(shí)候就需要思考,是不是有更好的處理方案。在一開始我們的項(xiàng)目出現(xiàn)這樣的需求的時(shí)候,我想到的解決方案是創(chuàng)建一個(gè)事件處理中心的概念。

就是將 cell 中的每一個(gè)試圖需要響應(yīng)事件回調(diào)到 cell 層,然后 cell 中有一個(gè) delegate , 創(chuàng)建一個(gè)叫 HandleEventCenter 的對(duì)象(controller 創(chuàng)建數(shù)組維護(hù))來起到回調(diào)中心的作用。

這樣對(duì)于上邊的需求,我們的處理方案就會(huì)變得更加靈活,可以寫一個(gè)通用處理一般場(chǎng)景下的基類,然后根據(jù)業(yè)務(wù)線的不同繼承自基類,重寫需要特殊處理的基類的問題。

這是看下這樣處理的優(yōu)缺點(diǎn):

  • 解決了 view 層和業(yè)務(wù)代碼之間代碼耦合的問題,同時(shí)事件的處理不需要在每個(gè) controller 上寫多次。同時(shí)可以較好的應(yīng)對(duì)點(diǎn)擊事件在不同業(yè)務(wù)線處理不同邏輯的問題,而且代碼的可讀性問題也得到了解決。

  • 問題就在源神提到的我們要將事件一層層向上回調(diào),寫了很多坨看上去很不爽的回調(diào)代碼的問題(無論 delegate 還是 block 都不夠優(yōu)雅)

更好的處理方案

看到 GPUImage 的源碼之后,我當(dāng)時(shí)想到的方式,就是用這種事件鏈條的形式,將事件傳遞下去就行了。其實(shí)在日常開發(fā)中,我們都習(xí)慣了使用 delegate 或者 block 兩種方式對(duì)事件向上進(jìn)行傳遞,但是忘記了系統(tǒng)很常用的的 target - action 模式。

下邊來看下我們?cè)?jīng)固有模式和現(xiàn)在解決方案的區(qū)別。

  • 曾經(jīng)的方案:我們捕捉到事件執(zhí)行 -> 傳給上一層(block 或者 代理的模式) -> 再上一層 -> 最后的代理中心 -> 事件響應(yīng)

  • 現(xiàn)在的解決方案:將事件代理中心 -> 傳遞給 cell 層 -> 傳遞給各個(gè)事件層 -> 在事件執(zhí)行處調(diào)用處理中心對(duì)應(yīng)的方法

這樣每層一大堆惡心代碼問題得到了解決,也完全抽離了試圖和業(yè)務(wù)之間的耦合性。除此之外,如果我們的 cell 上添加了新的響應(yīng)事件,不需要在層層響應(yīng),只需要在處理中心添加新的代理,然后再執(zhí)行處 target 調(diào)用對(duì)應(yīng)方法即可。感覺很大程度上減少了代碼量,同時(shí)降低了維護(hù)成本。

一些題外話

其實(shí)我們?cè)趯?shí)際的開發(fā)中,發(fā)現(xiàn)一些特殊的場(chǎng)景下,事件處理中心的方案存在很大的弊端。比如 我們的界面上有一個(gè)編輯功能的按鈕,按鈕點(diǎn)擊后,我們會(huì)跳轉(zhuǎn)到一個(gè)新的界面對(duì) cell 的數(shù)據(jù)源進(jìn)行修改,這個(gè)時(shí)候再返回,我們需要根據(jù)新的數(shù)據(jù)源刷新當(dāng)前的 cell 。 事件處理中心的處理方案,就不足以解決這樣復(fù)雜的問題,否則就需要和 tableView 產(chǎn)生耦合。當(dāng)然這樣的問題,我們?nèi)∏傻倪M(jìn)行了解決,本文就不進(jìn)行介紹了。

提這樣的題外話,不過是想表達(dá)每一種方案中可能或多或少的都存在各種各樣的問題,但是針對(duì)問題,我們總是可以找到更好的解決方案。總是思考著,我們的程序也終究會(huì)變得更好。

當(dāng)然本文中提到的方案也可能存在各種各樣的問題,希望不吝賜教,希望在探討中找到更平衡的方案。共同進(jìn)步~~~

最后

之前看源碼,一直關(guān)注點(diǎn)都在于技術(shù)的細(xì)節(jié)和如何解決問題上。但是經(jīng)此發(fā)現(xiàn),在讀源碼的過程中,真的可以思考那些優(yōu)秀的開源的代碼,為什么這樣設(shè)計(jì),在我們?nèi)粘i_發(fā)中,這樣的設(shè)計(jì)是不是可以得到推廣和應(yīng)用。我相信在這一過程中,不知不覺,大家都會(huì)獲得足夠的成長和收獲~~~

轉(zhuǎn)載于:https://juejin.im/post/5a31406e6fb9a0450407e1a5

總結(jié)

以上是生活随笔為你收集整理的源码阅读中的收获的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。