作者 | 李志信(冀鋒)來源 | 阿里開發(fā)者公眾號
IOC(inversion of control)即控制反轉(zhuǎn),是面向對象編程中的一種設(shè)計(jì)原則,可以用來減低計(jì)算機(jī)代碼之間的耦合度。IOC-golang 是一款服務(wù)于Go語言開發(fā)者的依賴注入框架,基于控制反轉(zhuǎn)思路,方便開發(fā)人員搭建任何 Go 應(yīng)用。
在本文中,我不會羅列這個(gè)項(xiàng)目的種種功能與實(shí)現(xiàn),而是站在開發(fā)者的角度,談一談我認(rèn)為 Go 應(yīng)用開發(fā)的“理想姿態(tài)”。
項(xiàng)目背景
在面向?qū)ο缶幊痰乃悸废拢_發(fā)者需要直接關(guān)心對象之間的依賴關(guān)系、對象的加載模型、對象的生命周期等等問題。對于較為復(fù)雜的業(yè)務(wù)應(yīng)用系統(tǒng),隨著對象數(shù)目增長,對象之間的拓?fù)?/a>關(guān)系呈指數(shù)級增加,如果這些邏輯全部由開發(fā)人員手動設(shè)計(jì)和維護(hù),將會在應(yīng)用內(nèi)保存較多業(yè)務(wù)無關(guān)的冗余代碼,影響開發(fā)效率,提高代碼學(xué)習(xí)成本,增加了模塊之間的耦合度,容易產(chǎn)生循環(huán)依賴等等問題。
隨著開發(fā)者的增多,設(shè)計(jì)模型的復(fù)雜化,將會產(chǎn)生對象管理框架的訴求,例如 Java 生態(tài)的 Spring 框架,其設(shè)計(jì)的核心就是控制反轉(zhuǎn)思路,從而為開發(fā)者提供依賴注入、配置注入、生命周期管理等能力。Go 語言生態(tài)在開源側(cè)也有較多基于該思路的實(shí)現(xiàn),但普遍能力較為單一,相比于我們的設(shè)計(jì)思路 ,在可擴(kuò)展性、易用性等方面有所不足。
IOC-golang 不是 Go 語言實(shí)現(xiàn)的 Spring 框架!
我們致力于打造一款針對 Go 開發(fā)人員的框架,它適配與 Go 的語法和各種基本概念,符合 Go 語言開發(fā)習(xí)慣,能真正為開發(fā)人員提供編程、思考、運(yùn)維、以及代碼閱讀上的便利。
設(shè)計(jì)思路
讓我們聊一些輕松的話題。
應(yīng)用開發(fā)思路
應(yīng)用程序多種多樣,都是由開發(fā)人員一行一行代碼編寫出來的,身為開發(fā)人員,在編寫代碼之前,一定是對接下來要寫的每一行代碼有初步的思考與設(shè)計(jì)。例如,我身為一個(gè) Go 開發(fā)人員,如果期望編寫一個(gè)web 后端服務(wù)程序,那么我會怎么做?
最直觀的思路,我需要啟動一個(gè)http server,用于監(jiān)聽某個(gè)端口,并且處理http協(xié)議的請求。使用面向?qū)ο蟮乃悸?,我需要?gòu)建一個(gè)http server對象,之后調(diào)用方法開啟監(jiān)聽。再往下一層思考,這個(gè)http server 對象如果要創(chuàng)建出來,需要依賴一些對象,這些對象可能包含:多個(gè) http handler 對象、用于可視化上報(bào)的對象、管理安全認(rèn)證的對象等等。再下一層,一個(gè)http handler 對象依賴的對象有:負(fù)責(zé)執(zhí)行序列化操作的對象、傳輸結(jié)構(gòu)對象、業(yè)務(wù)處理對象;業(yè)務(wù)處理對象又依賴一些sdk,例如緩存客戶端對象、數(shù)據(jù)庫客戶端對象等等。我們現(xiàn)在層層思考的過程,也就是自頂向下的設(shè)計(jì)模型。
我們可以把一個(gè)復(fù)雜的應(yīng)用程序,根據(jù)依賴關(guān)系,抽象為一個(gè)具有單起點(diǎn)的有向圖,以上面描述的場景為例,我們可以畫出具有如下拓?fù)涞膱D。
腦海中有了這些拓?fù)?,就可以按照?xí)慣的方式編寫代碼了,我可能選擇先把未實(shí)現(xiàn)的模塊抽象成接口,由上至下編寫結(jié)構(gòu),我也可能習(xí)慣自底向上開發(fā),先從最具體的底層結(jié)構(gòu)入手,然后用多個(gè)子結(jié)構(gòu)組成一個(gè)完整的上層結(jié)構(gòu)。無論選擇哪種實(shí)現(xiàn)方案,我在開發(fā)時(shí)總會關(guān)心一件事情:我要開發(fā)的結(jié)構(gòu),是由哪些結(jié)構(gòu)組成的,我把這個(gè)事情稱作一個(gè)“開發(fā)單元”,這也是IOC-golang 框架關(guān)心的主要問題之一。
按照常規(guī)的應(yīng)用開發(fā)模式,在一個(gè)“開發(fā)單元”內(nèi),開發(fā)者需要關(guān)注哪些事情?我們習(xí)慣于編寫一個(gè)構(gòu)造函數(shù)返回需要的對象,這個(gè)構(gòu)造函數(shù)的入?yún)?,包含了一些參?shù)以及下游依賴,我們在構(gòu)造函數(shù)中會把這些對象和參數(shù)拼接成一個(gè)結(jié)構(gòu),再執(zhí)行初始化邏輯,最后返回。
我們把這個(gè)“開發(fā)單元”關(guān)心的東西,按照依賴關(guān)系抽象成下圖。
也就是說,如果想基于一個(gè)結(jié)構(gòu)構(gòu)造出一個(gè)對象,我們最多需要提供這三個(gè)東西就夠了:參數(shù)/配置、依賴的子對象和一段包含初始化邏輯的函數(shù),當(dāng)然對于一些簡單的結(jié)構(gòu),可能只需要三者中的一兩者,甚至都不需要。按照這一思路,開發(fā)人員可以把 “編寫一個(gè)應(yīng)用” ,拆分成若干個(gè) “構(gòu)造一個(gè)對象”的過程,二者是等價(jià)的,我們都在編碼的過程中,潛移默化地做了這件事情。
點(diǎn)擊鏈接查看原文,關(guān)注公眾號【阿里開發(fā)者】獲取更多福利!https://mp.weixin.qq.com/s/Ar-JdkrQ5NnCWcGOoCuVgg