754
技術社區[雲棲]
IoC/DIP其實是一種管理思想
作者:陳皓(花名:鑽風)
關於IoC的的概念提出來已經很多年了,其被用於一種麵象對像的設計。我在這裏再簡單的回顧一下這個概念。我先談技術,再說管理。
話說,我們有一個開關要控製一個燈的開和關這兩個動作,最常見也是最沒有技術含量的實現會是這個樣子:
然後,有一天,我們發現需要對燈泡擴展一下,於是我們做了個抽象類:
但是,如果有一天,我們發現這個開關可能還要控製別的不單單是燈泡的東西,我們就發現這個開關耦合了燈泡這種類別,非常不利於我們的擴展,於是反轉控製出現了。
就像現實世界一樣,造開關的工廠根本不關心要控製的東西是什麼,它隻做一個開關應該做好的事,就是把電接通,把電斷開(不管是手動的,還是聲控的,還是光控,還是遙控的),而我們的造各種各樣的燈泡(不管是日關燈,白熾燈)的工廠也不關心你用什麼樣的開關,反正我隻管把燈的電源接口給做出來,然後,開關廠和電燈廠依賴於一個標準的通電和斷電的接口。於是產生了IoC控製反轉,如下圖:
所謂控製反轉的意思是,開關從以前的設備的專用開關,轉變到了控製電源的開關,而以前的設備要反過來依賴於開關廠聲明的電源連接接口。隻要符合開關廠定義的電源連接的接口,這個開關可以控製所有符合這個電源連接接口的設備。也就是說,開關從依賴設備這種情況,變成了,設備反過來依賴於開關所定義的接口。
隻要你看過我的那篇《麵向對象設計其實和麵象對象一點關係也沒有》,你就知道這樣的例子在生活中太多見了。比如說:
1)在交易的過程中,賣家向買家賣東西,一手交錢一手交貨,所以,基本上來說賣家和買家必需強耦合(必需見麵)。這個時候,銀行出來做擔保,買家把錢先墊到銀行,銀行讓賣家發貨,買家驗貨後,銀行再把錢打給賣家。這就是反轉控製。買賣雙方把對對方的直接控製,反轉到了讓對方來依賴一個標準的交易模型的接口。股票交易也是一樣的,證交所就是買賣雙方的標準交易模型接口。
2)上麵這個例子,可能還不明顯,再舉一個例子。海爾公司作為一個電器製商需要把自己的商品分銷到全國各地,但是發現,不同的分銷渠道有不同的玩法,於是派出了各種銷售代表玩不同的玩法,隨著渠道越來越多,發現,每增加一個渠道就要新增一批人和一個新的流程,嚴重耦合並依賴各渠道商的玩法。實在受不了了,於是製定業務標準,開發分銷信息化係統,隻有符合這個標準的渠道商才能成為海爾的分銷商。讓各個渠道商反過來依賴自己標準。反轉了控製,倒置了依賴。
可見,控製反轉和依賴倒置不單單的一種設計模式,反而更是一種管理模式。
在大公司中,有很多很多的團隊,這些團隊開發的軟件有很多依賴,跨團隊合作是一件挺麻煩的事情,下麵是一些比較真實的示例:
1)一個網頁會有很多頻道,於是,我們的前端工程師進入到各個頁麵為各種頻道開發他們的頁麵,隨著頻道越來越多,前端開發工程師的人數也越來越多,每增加一個頻道,就要增加一個為這個頻道服務的前端團隊,於是,人數越來越多,幹成了勞動密集型。為什麼不反轉控製,倒置依賴呢?前端的同學完全可以開發出各種頁麵的標準組件,布局,模板,以前與後端交互框架,然後,讓後端的同學反過來依賴於前端的標準,使用前端的框架,前端的布局,模板,和組件,以向前端接入後端的模塊。
2)一個平台需要接入各種各樣的業務係統,這些垂直業務係統都有自己的賬號體係,於是這個平台為了要兼這些垂直係統的賬號體係以做到權限控製,需要做各個係統和自己係統中的賬號映射,並為賬號和分配出來的資源設置各垂直係統的標識,還要在自己的代碼中要寫很多很多的依賴於各種賬號體係的代碼。其實,一個依賴倒置和反轉控製就很簡單。開發一個權限體係標準,讓接入方的賬號係統反過來依賴並控製這個標準的權限係統,從而做出一個幹淨的係統。
3)還有一個雲平台中的管理模式,一些底層服務的開發團隊隻管開發底層的技術,然後什麼也不管了,就交給上層的開發人員,在底層團隊的開發出來的產品上麵開發各種管理這個底層資源的東西,比如:生產底層資源的業務,底層資源的控製台,底層資源的監控係統。這個讓底層團隊隻幹純技術,不幹與底層技術無關的東西,看似很科學,其實是做錯了。因為,上層為各個雲資源控製生產,開發控製台和監控的團隊,隨著接入的資源的越來越多,完全幹不過來了,苦逼得一塌煳塗,因為底層的資源千差百怪,每接一個就要開發一堆這個產品的代碼。這個時候依賴倒置和反轉控製又可以解決問題了。很簡單,上層為各個雲資源控製生產,開發控製台,和監控的團隊應該製定一個標準,讓底層的IaaS雲資源開發團隊反過來依賴這個標準,統一接入方式,如果開發的雲資源不符我的生產控製模型,沒有控製台,不把監控數據喂入我的監控係統,對不起,請不要接入我這個PaaS平台。
4)一個集中式的處理電子商務中的訂單的流程。各個垂直業務線都需要通過這個平台來處理自己的交易業務,但是垂直業務線上的個性化需求太多。於是,這個技術平台開始出現了黑魔法——“為了害怕改變數據庫表結構,不得不在數據庫中預留一些字段,裏麵存把業務方的個性化字段存成如JSON這樣的東西”,並為之自豪認為可以快速解決業務問題(WTF)。然而,惡夢並沒就此結束,管理這個技術平台的小組開始發現,對來自各個業務方的需求應接不暇,各種變態需求嚴重幹擾係統,各種技術決定越來越不好做,導致需求排期排不過來。於是,不單單得到了各個業務方的各種抱怨,最可怕的是還有高層老大們壓過來的Deadline,加班加點,苦逼之極,最後業務方自己要去一個自己的平台。為什麼不用依賴倒置和反轉控製的思想呢?開發一個插件模型、工作流引擎和Pub/Sub係統,讓業務方的個性化需求可以以插件的方式插入我的訂單流程中,業務方自的數據存在自己的庫中,業務邏輯也不要侵入我的係統,並可以使用工作流引擎或Pub/Sub的協義標準來自己定義工作流的各個步驟(甚至把工作流引擎的各個步驟的Decider交給各個業務方自行處理)。讓各個業務方來依賴於我的標準插件和工作流接口,反轉迭控製,讓他們來控製我的係統,依賴倒置,讓他們來依賴我的標準。(這個團隊想過把自己的係統內部開源出去讓別的團隊也進來參與,可以是可以,但一定要用Linux/Git這種方式,允許出現多個分支,多個發行版。但多個版本又造成了多個業務平台,這會上上層垂直業務不知所措)
5)看過《SteveY對Amazon和Google平台的吐槽》的人都知道,Amazon內部係統的SOA架構(這個SOA架構離IBM定義的那個非常變態的SOA還有一定距離),但是這基本上都是依賴倒置和控製反轉的思路了—— 與其讓我來幫你實現你的業務邏輯,不如把我的業務邏輯開放成服務的方式讓你來控製。
6)再說一個我在Amazon經曆的例子。有一個項目是在給Amazon的各個商區(Marketplace)做國際出口的業務,我們先把Media類的產品(書,DVD之類的)做國際出口開放,項目不難,就是讓商家同意一個法律協議(上傳自己的簽名),然後後台小改一下。美國的,歐洲的做的都沒有問題,物流團隊在出口報關單上打的都是Amazon倉庫的地址和商家的簽名(本來這就是錯的,打的應該是商家的地址和商家的簽名),但是到了日本,就出了問題,因為日本海關即要日文信息,也要商家的英文名和英文地址,而我們的係統裏麵隻有商家的日文信息。本來,這是一個挺簡單的事——數據庫裏加兩個字段,在那個同意條款的網頁上收集一下商家的英文名和地址,然後把這些信息傳給後麵的物流團隊。物流團隊一看這個,發現搞不了,因為他還要傳給倉庫,N多的地方都要加這兩個字段,還要寫下各種if (site == JP)這樣的判斷。物流團隊不蠻幹,重新設計自己的係統。做一個Document Template的東西,這個就是那個那個要貼在物流盒子上的單子。再也不讓各個業務團隊把那些信息傳過來,而是把這個Document Template的東西傳給上麵的業務方,他們想怎麼寫就怎麼寫, 寫完後,把這個東西傳回來。於是,大家依賴了一個標準的協議,而不是一其字段。(當然,這個改動過多,為此改了半年多,不過非常值)
所以說啊,在跨團隊的工作中,
- 如果依賴和控製的東西過多了,就需要製定標準,倒置依賴,反轉控製。
- 控製欲望最好不要太強,不要想著能幹所有的事情,要學會控製反轉和依賴倒置原則。否則隻會引火燒身。
- 反轉控製和依賴倒置是一種智慧。
(全文完)
最後更新:2017-04-03 07:57:02