我用段子讲.NET之依赖注入(一)
我用段子講.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
總結
以上是生活随笔為你收集整理的我用段子讲.NET之依赖注入(一)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: ABP Framework V4.4 R
- 下一篇: 张善友: .NET社区运营 | 202