1. 程式人生 > >關於程式碼解耦

關於程式碼解耦

爛的程式碼,都有各自爛的地方,不過基本都有一個共同的特點:耦合重,各個模組各個類各個功能點 之間關係牽扯不清,經常你呼叫我呼叫你,或者全域性變數漫天飛; 對於怎麼理清這些模組或者類,《程式碼大全》講了很多,比如要形成金字塔型的呼叫層級關係,如果 不能保證,也一定要保證單向的呼叫關係,絕對不能形成環狀的呼叫關係; 即:A->B->C 而不能是 A->B->C->A,尤其要避免 A<->B 如果不能避免這種迴圈呼叫,A和B將無法區分開來,A和B不可避免的扯到了一起,不能單獨開發,不 能單獨編譯,無論改動A或者B中的一個,都會影響到另外一個;這樣,隨著功能一多,模組一多,最後全 扯到了一起;造成了你中有我,我中有你的感概噁心的耦合!! 如果能保證這種單調單向的呼叫關係,那程式碼將形成一定的上下有別的層級,其中任何一層只能呼叫 下層,絕對不能呼叫上層,最好是完全不用知道有上層!!即每層都把自己當作是最上層; 這樣有幾個好處: 1,模組解耦了,如果每層介面設計的好,那每層內部的改動對其他層或者其他模組完全是透明的, 這樣有利於分工; 2,模組解耦之後,得到另外的一個好處是:能極大的增強程式碼模組的複用度,很多模組也許用著用 著就發現提取出來,可以供很多的上層模組呼叫; 對於叢集中的svr節點來說,一般可以劃分成一些固定的層:比如:核心資料模組,驅動模組,業務 模組,RPC模組,基礎框架模組等等; 上面這些說的都是理論的玩意,而且很多人也都知道,但其實真正寫程式碼的時候,往往發現事情沒這 麼簡單,很多情況下,會發現A->B,B確實要反過來呼叫B;比如我經常發現有人這樣寫程式碼: 狀態機FSM模組需要通過RPC模組拉取資料,得到資料後,然後才能接著往下繼續處理;一般的 RPC 模組的介面是 rpc::get_data(req, fsm_id),rpc得到資料後,根據fsm_id從全域性FSM管理器 g_fsm_mgr  取出FSM,然後呼叫 FSM::on_data_back(resp)... 看到沒有,rpc 和 fsm 完整的融合在了一起,而且必須要通過全域性變數融合(這裡就會發生非常多的 噁心的地方,比如svr裡面有兩類都可能呼叫此rpc狀態機...),明顯這裡是有非常大的問題,rpc 明明和 業務是沒半點關係的,rpc應該做的就是遠端操作,至於操作的結果,rpc是不應該管的,他只需要簡單的 把結果返回給呼叫者(即上層)即可; 按上面這種做法,rpc 是無法重用的,如果另外寫一個svr,而這個svr用的同一套rpc,那他就只能 把這套rpc程式碼拷貝過來,然後再改幾個地方...重複?噁心?低效?bug滋生? 其實對於這個問題,有極其簡單極其有效卻完全被人忽視的辦法:回撥!! rpc提供的介面應該是這樣的: typedef (*on_data_back)(resp,...) rpc:get_data(req, on_data_back cb, void* params) rpc只需要在內部建立這個req的標誌(比如序列號)和 callback以及params的對映即可,當結果返回 時,只需要通過resp的標誌找到回撥資訊,然後 cb(resp, params) 即可,至於cb到底是幹什麼的,rpc無 權知道,也不需要知道!! 對於所有的下層需要呼叫上層的情況,回撥都應該是最好的選擇,也是必須的選擇; C語言的精華是指標,指標的精華是函式指標,C的生命,C的靈動,C的多變來源於函式指標;君不見 稍微大點的純C專案,函式指標都是極其常見的; 說起來其實很簡單,確實夠簡單,卻極致夠用;那為什麼很多專案中還是組織亂成一團麻呢?? 對於C++,回撥沒C這麼簡單,以前一直沒有找到好用的自然的類函式指標的玩意,後來發現了boost的 function和bind這兩個玩意,能完全實現類的回撥,而且能隨心所欲的攜帶引數,用多了感覺比C的函式指

針還好用,特別是攜帶引數這塊;C完全依靠void*這個指標攜帶,而boost的回撥不限!!

轉自 http://blog.chinaunix.net/uid-26443921-id-3361188.html