我用段子講.NET之依賴注入(一)

溪源More發表於2021-06-30

《我用段子講.NET之依賴注入其一》

1)

西城的某個人工湖畔,湖水清澈見底,湖畔柳樹成蔭。人工湖往北,坐落著兩幢寫字樓,水晶大廈靠近地鐵站,由於為了與湖面天際線保持一致,樓層只有26層高,但外觀非常好看,水藍色的玻璃幕牆,波紋狀的外觀裝飾,無處不洋溢著青春時尚。而另一座創新大廈與其隔河相對,樓層相對較高,設計風格偏中規中矩,外觀樸實無華,標準的寫字樓風格,與水晶大廈相比,雖然沒有好看的外表,但卻顯得厚重充滿內涵。

年輕程式設計師木哥和老程式設計師董哥,他們就分別在這兩座寫作樓中工作,他們也將作為本公眾號未來【我用故事講.NET】系列文章的主角出現。當然,他們都是小編自己塑造出來的人物形象,如有雷同,純屬巧合。

小木是一位.NET工程師,年輕而風華正茂,從大學畢業起就一直從事該領域,迄今已經約莫三年有餘,他也是一位技術愛好者,經常追逐於各種新穎的網際網路技術和概念,加了很多技術社群,經常參加各種大佬組織的技術沙龍,當然,他也自感技術之無止境,經常感慨新技術重新整理飛快。

而董哥則是一位底層工程師,他今年將近40歲,四十而不惑,在這個35歲就淘汰的年代,他並沒有被時代淘汰,而是頑強的奮鬥著。他外表穩重質樸,長時間在辦公室工作,顯得皮膚格外白皙,事實上其他人第一次見到他就能猜到他一定是一位技術老司機,因為頭頂上有一小塊區域已經開始出現了水土流失的跡象。他在電氣製造領域和.NET底層應用方面擁有豐富的經驗,雖然董哥的主業是偏嵌入式方向,但他對.NET也同樣充滿興趣。

二人因為一次偶然的機會互相認識,共同的技術體系和興趣愛好,加之辦公地點也離得不遠,他們經常碰面,互相討論技術問題。

以上都是背景。

2)

最近小木同學發現越來越多的技術部落格都在介紹微軟新出的技術框架.NET Core,雖然他們公司的主要產品體系依然還是基於.NET Framework,但作為技術愛好者的他也按耐不住內心的激情,早就按照官方的教程,在自己本地安裝了最新版的開發工具Visualstudio2019。他準備摩拳擦掌,大幹一場,好好的把該技術消化好,儘快在公司完成一波輸出,成為帶領公司技術革新的帶頭人。

這幾天他的心情特別好,激情澎湃,充滿了創造一番新事業的熱情。某個週日,他打算開始動手了。他首先把dotnetcore的sdk部署好,然後開始按照官方的步驟,準備開始構建自己的第一個asp.netcore應用。他給自己準備了一個專案作為例項,按照結構化方法的標準步驟,編寫了一套用於開發該例項專案的設計文件,在這個專案中,他設計了幾個簡單的業務表,並按照官方教程的步驟編寫了幾個控制器和業務邏輯層及資料訪問層,雖然他聽人說過單元測試是實現程式碼效率提升的好辦法,但他還不會用,所以只能按照最傳統的方法=》直接進行程式碼除錯。

他的電腦執行速度很快,所以環境很快就跑起來了,可是他執行第一個介面方法就報錯了,提示【物件例項化失敗,未能建立指定的物件】,這是啥意思?觸及了啥未知領域?難道.netcore框架還不成熟,還是新的技術體系不能直接這麼用了?

他去網上尋求解決方案,並很快就搜到了,原來他沒有正確的使用依賴注入框架,由於他的業務邏輯層未在應用程式啟動時配置注入方式,使得控制器呼叫該邏輯層時,出現了例項化失敗的錯誤。他按照網上的方法很快就解決了該問題,並能夠正常的開始進行程式碼除錯了。

可是,這個問題始終困擾著他,為啥.net core裡面的業務開發都會先寫一個介面,並通過依賴注入的方式來實現類的載入,這樣的操作難道不累嗎?這個依賴注入究竟是啥意思,對我們crud工程師來說,有啥意義呢?

他決定上班時,找董哥去請教一番。

3)

次日,他跟董哥約好了下班後去拜訪他,並在6點左右如約來到董哥的辦公室。

董哥的辦公室坐落在創新大廈的頂樓,窗外正對人工湖,風景還挺好看的,是一個思考人生的好去處。董哥今天身著他們公司的工裝,正在電腦旁思考著啥技術問題,看到小木同學進來,微笑著迎接他進來。今天的小木同學沒有心情看風景,單刀直入,一落座就向董哥丟擲了前面幾個問題。

董哥微微一笑,拿出一張草稿紙,並在草稿紙上繪下了一個圖案,畫完後,將紙遞給小木同學,並微笑著說:

“你先看下這張圖,我給你倒一杯水,再慢慢解釋”。

小木同學接過草稿紙,仔細大量了起來,只見這張紙上畫著的圖案有點像一棵樹,筆直的樹幹上,零零碎碎長著幾根枝椏,枝椏上點綴著幾片樹葉。

“這是一棵樹?啥意思啊?“,他一臉詫異。

董哥給他遞上水,哈哈一笑:“這就是困擾你的問題啊。”

“額。。我才疏學淺,不太理解,你的意思是不是說,這些問題少想一點,不然像這棵樹一樣,樹葉都掉光了,年紀輕輕就禿頂?”

“噗”,董哥一口水噴濺而出,連嗆幾下。

”董哥,你別賣關子了,快告訴我吧。“

4)

”木哥,我問下你,如果你種了一棵蘋果樹,如果有一點想讓他結出梨子,你會怎麼做?“

”額。。有幾種方法,例如基因工程,轉個基因?當然,我顯然實現不了,那我只能用嫁接了“。

”是的,那依賴注入就是這樣類似於嫁接的抽象性思維。“

”再講深入一點?“
”首先,應用程式中所有的物件,就像是一棵樹上長出來的枝椏和樹葉,都是從母體長出來的。“

“我知道,在.NET裡面這叫root對吧?“

”不是,我們今天先不討論這個問題,而是先討論最基礎的問題,什麼叫做依賴注入。你剛剛提到的這個root的問題,在.NET裡面屬於垃圾回收問題,這個問題有點花時間,且與你之前提的話題關係有點遠。今天我們還是討論這個依賴注入問題,在.NETCore中,我們往往會使用一種技術框架,這種框架恰好就叫依賴注入框架。“

“我看到過設計原則這個說法,網上大佬們說可以用SOLID單詞來進行總結。“

”是的,包括單一職責原則,開閉原則,裡式替換原則,介面分離原則,依賴倒置原則。後來又新增了一種合成複用原則,其他原則今天由於時間關係先不提,我們重點來看看這個依賴倒置原則。而這個原則也有人將它稱為依賴注入原則。“

董哥喝了一杯水,慢悠悠的解釋道:”這個原則其實只有一句話,高層模組不依賴於底層模組,它們都依賴於抽象。回到我們平時寫的業務程式碼,往往都是從根開始構造物件,接著我們寫了一堆的new語句,並繼而例項化出了許多物件,而這些物件又例項化出許多類,每個類直接引用了許多其他看似有關的業務類。類和類之間的關係就像之前畫的那棵樹的樹枝一般,互相攪合在一起,高層模組嚴格依賴於低層模組,低層模組的任何改變都可能對高層模組造成影響,這將極大的提高程式碼的維護成本,事實上變成了一個高耦合問題。“

小木同學突然感覺到一個問題:”所以聽說多型也是用來解決物件與物件之間依賴問題的?“

5)

董哥說:”你說的對,其例如在早期計算機中,由於各個程式模組可能被寫入到不同的儲存介質中,如果每個模組與其他模組強耦合,一旦某個模組被重寫,那跟他建立連結關係的所有程式碼都將不得不重寫。

所以人們引入了多型的概念,首先定義一層抽象,並定義實現類,父類通過依賴這些抽象,並維護抽象和實現之間的關係,這樣如果某個用於實現的模組被替換了,那隻需替換這個用於維護連結關係的儲存介質即可,對原有程式碼幾乎沒有任何改動。“

小木同學恍然大悟:”依賴注入中定義介面也是為了實現模組間所呼叫時更好替換的問題麼?”

董哥說:”是的。就像我們在一棵普通茶樹上,想讓它長出十八羅漢,結出各種奼紫嫣紅、不同外觀的山茶花,那我們要做的首先是準備砧木,然後再準備接穗。事實上是將某種山茶花的某些共性“抽象化”出來,並讓它們通過與砧木相結合,實現“介面”與“呼叫者”的耦合,將抽象出來的“介面”注入到“呼叫者”裡面。“

小木同學連連點頭:“這樣呼叫者不依賴於其他實現者,它們都依賴於抽象,雖然看起來呼叫者同樣依賴了某些業務邏輯,但沒有直接耦合其他的實現側程式碼,只要介面不變,那呼叫者程式碼就幾乎沒有任何改動了?”

董哥繼續說到:“在物件導向開發中,介面就像一種契約,是業務規則的抽象。我們都可能見過這個單詞,使用者介面。這個單詞的英語原文是User Interface,按翻譯,這個單詞,不應該是使用者介面麼?其實,可以換一個角度來理解,我們所設計的介面是使用者與計算機進行資料交換的一種行為介面,通過將行為介面事先確定,將使得我們程式碼開發的過程變得更加簡單。而在應用程式中設計介面也同樣是為了這個目的。“

小木說:”好像介面無處不在,例如webapi,也是基於web的應用程式介面。“

董哥回答道:”是的。回到正題,在.NET Core中使用依賴注入不僅僅只為了程式碼的整潔性或維護性,隨著我們將業務程式碼抽象化成介面和實現兩部分,這也使得物件生命週期的統一管理成為可能,這就引發了第二個問題,.NET Core中的依賴注入框架。“

--end

相關文章