設萬維讀者為首頁 萬維讀者網 -- 全球華人的精神家園 廣告服務 聯繫我們 關於萬維
 
首  頁 新  聞 視  頻 博  客 論  壇 分類廣告 購  物
搜索>> 發表日誌 控制面板 個人相冊 給我留言
幫助 退出
茶樹油之家  
與大家交流和分享蘋果產品、網絡技術,以及美樂家茶樹油及相關的信息  
https://blog.creaders.net/u/588/ > 複製 > 收藏本頁
網絡日誌正文
編程技巧探討:為什麼DI很重要? 2011-04-17 21:42:49
上一周,我們工作小組中有人問我一個問題:為什麼DI(Dependency Injection,依靠性元插入的模式,這是編程中常用的一種模式)十分重要?現在許多編程人員採用OO(Object Oriented,目標編程)的方式。他們以為在一個class中定義數據和接口,將程序中的邏輯包含在其中就足夠了。他們困惑地提出疑問,什麼是DI,為什麼還要採用DI模式?

第二天,我碰到單位中一位資深的編程員,我向他問了一個類似的問題,並問他具體怎麼使用的。他說他只是在對原程序的測試中採用DI,在測試中假設有關讀寫數據庫的變元,這樣不會真正對數據庫產生影響。這是測試中常用的方法,但這並不說明DI的全部。實際上,DI是一個非常重要的概念,而且是編程中常用的一種策略。

用一個形象的比喻,公司里IT部門需要採購部門購買一些硬件,IT按照要求將批準的單子交給採購部門,IT部門不感興趣採購部門的誰去完成這個任務,也不需要了解,部門之間只需要按照之間的交接口進行聯繫和交流。DI編程模式就是按照這樣的方式來編程,“部門”之間不需要知道誰在做具體的工作。

我回憶起我過去所寫的許多項目,並查看我過去的程序。在這裡我對此用一個簡單的例子作具體的解釋。先看看下面的一個C#例子:

public class MyDataReader {
  ...

  public bool ReadData() {
    var dbService = new MyDbService();
    ....
    var data = dbService.GetObject();
    ....
  }
}

上面有問題的地方是dbService變元由MyDbService class產生的一行,這種採用new來指定特定class的方式在編程中普遍存在。很明顯MyDataReader class依賴於MyDbService class。換言之,MyDataReader知道所需要的dbService是從那一個class產生的。MyDataReader有必要知道具體創建的class嗎?它只是使用一數據服務通過其接口取得數據(如GetObject()接口),它並不需要知道數據是如何取得的,那麼它關心具體服務的class有必要嗎?如果能夠將這種依賴性分隔,讓一個中介來提供一個數據服務變元,這樣不就更好嗎?

現在我們來看看下面改進的編碼:

public class MyDataReader {
  ...

  public bool ReadData() {
    var dbService = DIContainer.GetInstance<IDBService>();
    ....
    var data = dbService.GetObject();
    ....
  }
}

這裡只是一個小小的改動,DIContainer作為一個中介,通過它的接口GetInstance指定所需要的變元,這個變元具有抽象界面定義IDBService即可。DIContainer就像一個黑匣子,它知道如果根據要求的服務提供具體class的變元。這就是DI的典型應用例子。如果MyDataReader需要從不同的數據源取數據,將來MyDataReader根本不需要改動,只要告訴DIContainer即可。 這個服務元可能是從MyDbService,也可能是通過類似別的class如SqlDbService或OracleDbService。

由此可見,採用DI模式可以帶來很多的好處。具體採用什麼樣的DI平台,如果設計和給DI提供不同Interface和具體class的相互對應關係,這些都超出本文的內容了,我在我的其它博客文(在blogger的英文博客, under "Design Pattern" tag)中有詳細敘述。

現在有關DI的編程模式有許多,我個人認為,作為一個熟練的編程人員,應該學習和掌握這方面的知識,這樣就可以寫出更好、更乾淨、可維護和擴展的應用程序。在學習之前,首先要明白DI的道理,解決什麼類型的問題,這樣就容易理解DI的重要性和各種DI是如何解決這類問題的。如果你能熟練地運用DI技術,你的編程技術將會是高人一籌,而且如果你將來工作有這方面的要求,你將不會面對天書而一頭霧水。


本文為我試圖用萬維網博客寫技術方面(我在新浪博客上也做了成功的嘗試)的一個嘗試,萬維網博客提供有限的界面,但提供源代碼接口,這樣就可以直接通過HTML碼加入我所需要的基本功能。我今天寫了一篇英文博客,以此為藍本,我成功地復製成中文版的技術博文,編碼帶有不同的顏色,花的功夫不太大,這次嘗試看來是成功的。
瀏覽(1507) (0) 評論(2)
發表評論
文章評論
作者:茶樹油之家 留言時間:2011-05-18 09:30:56
In order for my app to get the instances needed, there must be, first, a place to do the configuration and class mapping, and secondly, an API to get instances. DIContainer is my magic box. This is my proposed architecture for the DI implementation.

The basic logic of DI is to delegate the knowledge of how to create instances to a magic box, such as a container or service. This container is a generic one for all various instances I need for my app. The example codes in my blog show to get instance of IDBService. I could extend it to get instances like logger, data process and others.

If you need to get new or different instances from the container, DIContainer is the only place to change. In addition to that, in my practice of DI, I found this DI wrapper class is very flexible. For example, initially, I used StructureMap and String.Net as my engine for interface to class mapping, later I switched to Microsoft MEF. I only changed the DIContainer library for this update, all my app and other libraries are changed at atll sine my DIContainer's APIs have not changed at all.

By the way, I updated my blog with correction of my codes.
回復 | 0
作者:bfbx 留言時間:2011-05-11 11:58:43
In this example, you removed MyDataReader's dependency on MyDbService. But you introduced a new dependency on DIContainer.

The DI way of doing this is to create a pair of getDbService() and setDbService(IDbService dbService). At runtime you call setDbService(IDbService dbService) to inject the dependency before it's used.
回復 | 0
我的名片
茶樹油之家
來自: 加拿大
註冊日期: 2007-01-19
訪問總量: 509,824 次
點擊查看我的個人資料
Calendar
最新發布
· ZOOM 會議:iOS 平台上的軟件開
· 專注做一件事是最好的擺脫
· 我的 iOS app 更新了
· 有關老面製作的問與答(三)
· 從Legacy 小道,我重新開始了跑
· 從Legacy 小道,我重新開始了跑
· 為準備馬拉松長跑的第一次嘗試
分類目錄
【社會公益】
· 飄香茉莉 - 李靖惠
· 天使的恩賜
· 經典京劇『鎖麟囊』
· 挑戰自己:參加2013卡爾加里馬拉
· 夢想合唱團大聚會與奧運夢想
· 中央電視台的夢想合唱團公益活動
【WWDC】
· 學習WWDC 2017
· 學習WWDC 2015
· 網上學習:WWDC 2013視頻講座
· WWDC 2013技術講座視頻
· WWDC 2012筆記(4)
· WWDC2012的學習筆記(3)
· WWDC 2012的學習筆記(2)
· WWDC 2012的學習筆記(1)
· WWDC2011視頻的學習筆記(21)
· WWDC2011視頻的學習筆記(19)
【網絡安全】
· Heartbleed網絡安全漏洞
· 蘋果小技巧:如何在PDF文件上加
· 警惕你的蘋果禮物卡被竊
· 蘋果用戶的獨特免疫能力
· 蘋果發布安全更新2011-003
· 最新的微軟IE漏洞和劫持Cookie的
· 新的惡意軟件第二番攻擊蘋果
· 新的惡意軟件開始攻擊蘋果
【生活與健康】
· 有關老面製作的問與答(三)
· 從Legacy 小道,我重新開始了跑
· 從Legacy 小道,我重新開始了跑
· 為準備馬拉松長跑的第一次嘗試
· 張宏文與西班牙華人的醫療諮詢
· 有關老面製作的問與答(二)
· 美麗的洛基山脈
· 有關老面製作的問與答(一)
· 我為什麼喜歡蘋果
· 加拿大抗新冠病毒動態 2020.4.16
【TED視頻】
· 請求的藝術
· TED有關兩種不同政治制度的精彩
· 游擊隊方式的城市菜園
· 玩遊戲可以多活十年
· 中毒寶寶
· 中美關係不需要多一個律師
· TED視頻:脆弱的力量
· TED視頻精選:戴維·卡梅倫論政府
· TED視頻:為什麼SOPA是一個餿主
· TED視頻:失敗是成功之母
【海外生活】
· 從Legacy 小道,我重新開始了跑
· 從Legacy 小道,我重新開始了跑
· 為準備馬拉松長跑的第一次嘗試
· 張宏文與西班牙華人的醫療諮詢
· 有關老面製作的問與答(二)
· 美麗的洛基山脈
· 有關老面製作的問與答(一)
· 我為什麼喜歡蘋果
· 加拿大抗新冠病毒動態 2020.4.16
· 加拿大抗新冠病毒動態 2020.4.16
【網絡服務】
· 專注做一件事是最好的擺脫
· 谷歌帳號和相應的雲服務
· 用圖像和風格語言css 定義數字章
· 網絡服務:計算型知識引擎服務
· 如何優化圖像所占用的空間
· 用視覺方式快速算算數
· 新浪【船過水無痕】的博文,非常
· 蘋果的雲服務iCloud與谷歌的雲服
· 新浪微博對話實例
· 使用網絡翻譯服務,寫中文博客
【軟件開發】
· ZOOM 會議:iOS 平台上的軟件開
· 專注做一件事是最好的擺脫
· 我的 iOS app 更新了
· iOS App: TapToCount - 3W
· 第一個iOS app 的里程碑
· TestFlight - 蘋果iOS app測試的
· 24點的算法
· 學習WWDC 2015
· 漢字聽寫大會-電腦書寫輸入法
· WWDC2012的學習筆記(3)
【我愛蘋果】
· ZOOM 會議:iOS 平台上的軟件開
· 我為什麼喜歡蘋果
· iOS App: TapToCount - 3W
· 為武漢發生COVID-19疫情做一點貢
· 第一個iOS app 的里程碑
· 創作app的樂趣
· 你知道你的睡覺節奏規律嗎?
· 學習WWDC 2017
· 點擊計數 - 記住隨時隨地的點滴
· 學習WWDC 2015
【網絡技術】
· 專注做一件事是最好的擺脫
· 如何用 Blogger 邀請朋友共同寫
· 今天是3.14日,以及VIM的強大區
· 探討:採用QR碼快速連接Wi-Fi
· 互聯網+和微信
· 寫博客的體會
· WA實例:分數的計算
· 如何將XML內容用HTML格式表述
· 如何優化圖像所占用的空間
· 谷歌博客更新:增加動態放大圖像
【茶樹油】
· 有關老面製作的問與答(三)
· 茶樹精油消毒殺菌的熏蒸法
· 新冠病毒核酸檢測之淺解
· 倡議:聯合海外華人寫抗疫日記
· 茶樹精油新用法:消毒和清潔面部
· 為關心COVID-19疫情寫的小詩
· 為武漢發生COVID-19疫情做一點貢
· 2018,達到一萬公里里程碑!
· Melaleuca 2017/12/26 年銷售額
· 跑步里程達到八千公里
存檔目錄
2020-05-11 - 2020-05-21
2020-04-04 - 2020-04-23
2020-03-01 - 2020-03-31
2020-01-07 - 2020-01-25
2019-03-20 - 2019-03-20
2019-02-09 - 2019-02-09
2018-12-31 - 2018-12-31
2018-05-18 - 2018-05-18
2017-12-09 - 2017-12-26
2017-10-19 - 2017-10-19
2017-09-06 - 2017-09-06
2017-08-17 - 2017-08-17
2017-06-07 - 2017-06-28
2017-04-12 - 2017-04-28
2017-03-31 - 2017-03-31
2017-02-22 - 2017-02-22
2017-01-18 - 2017-01-23
2016-10-25 - 2016-10-25
2016-03-21 - 2016-03-21
2016-02-01 - 2016-02-17
2016-01-12 - 2016-01-22
2015-12-04 - 2015-12-11
2015-11-19 - 2015-11-24
2015-10-14 - 2015-10-14
2015-08-05 - 2015-08-05
2015-07-24 - 2015-07-24
2015-04-06 - 2015-04-24
2015-03-14 - 2015-03-18
2015-02-05 - 2015-02-05
2015-01-20 - 2015-01-20
2014-12-13 - 2014-12-13
2014-11-13 - 2014-11-13
2014-10-01 - 2014-10-10
2014-09-01 - 2014-09-24
2014-08-07 - 2014-08-29
2014-07-11 - 2014-07-31
2014-06-23 - 2014-06-23
2014-05-02 - 2014-05-31
2014-04-20 - 2014-04-27
2014-02-14 - 2014-02-14
2014-01-06 - 2014-01-29
2013-12-02 - 2013-12-30
2013-11-06 - 2013-11-18
2013-10-12 - 2013-10-30
2013-09-03 - 2013-09-03
2013-08-01 - 2013-08-23
2013-07-05 - 2013-07-30
2013-06-03 - 2013-06-14
2013-04-03 - 2013-04-30
2013-03-07 - 2013-03-30
2013-02-18 - 2013-02-23
2012-12-05 - 2012-12-25
2012-11-08 - 2012-11-25
2012-10-05 - 2012-10-18
2012-09-26 - 2012-09-26
2012-08-03 - 2012-08-25
2012-07-07 - 2012-07-27
2012-06-01 - 2012-06-28
2012-05-01 - 2012-05-27
2012-04-08 - 2012-04-27
2012-03-03 - 2012-03-31
2012-02-07 - 2012-02-29
2012-01-15 - 2012-01-27
2011-12-03 - 2011-12-20
2011-11-02 - 2011-11-22
2011-10-01 - 2011-10-30
2011-09-03 - 2011-09-24
2011-08-01 - 2011-08-31
2011-07-01 - 2011-07-30
2011-06-01 - 2011-06-29
2011-05-01 - 2011-05-31
2011-04-02 - 2011-04-30
2007-01-19 - 2007-01-19
 
關於本站 | 廣告服務 | 聯繫我們 | 招聘信息 | 網站導航 | 隱私保護
Copyright (C) 1998-2024. Creaders.NET. All Rights Reserved.