依賴注入:原理、實作與設計模式 (Dependency Injection: Principles, Practices, Patterns, 2/e)
內容描述
【名家名著】 21
想要讓程式更具彈性、更容易測試、更接近clean code,
你需要降低元件之間的耦合度,
依賴注入將是你強而有力的工具!
它是組合取代繼承的重要實踐!
Odd-e Taiwan 敏捷技術教練 陳仕傑(91)專文推薦
名人盛讚
「我非常推薦與認同書裡的脈絡安排與學習順序,其實戰性毋庸置疑。」
──Odd-e Taiwan 敏捷技術教練:陳仕傑(91)
「實用的範例內容讓原本虛無縹渺的概念具體化了... 作得太好了。」
──Glenn Block,來自Microsoft
「內容豐富、思路清晰、指引明確、而且... 永久受用。」
──David Barkol,來自Neudesic
「這本書正是所有.NET 軟體設計師需要的。」
──Paul Grebenc,來自PCA Services
「這本書把那些原本雲裡霧裡的模糊觀念全都撥雲見日。」
──Rama Krishna,來自3C Software
「跟隨這本書的獨特思維,深入學習現代軟體開發的實務原則。極度推薦!」
──Darren Neimke,來自HomeStart Finance
「對依賴注入議題所需要知道的一切都在這本書裡了,保證物超所值!」
──Jonas Bandi,來自TechTalk
「想了解依賴注入必讀之書。」
──Braj Panda,來自Capgemini India
「這本書是你在.NET 開發框架上的依賴注入架構指引經典。」
──Doug Ferguson,來自Improving Enterprises
「要讓軟體保持彈性應付多變的需求,就必須降低元件之間的依賴性。如果能夠把依賴性在使用時才注入,就能保持軟體發展的最大彈性,而這就是依賴注入。依賴注入是一項成果,應用這項成果最多的則是各式各樣的框架(尤其是Web框架),例如.NET Core、Spring Boot。依賴注入活用了眾多的設計模式,而這些設計模式則充分利用了OOP的多型來進行軟體的OOD。很少有作者可以把依賴注入寫得如此易學與完整,所以這本書毫無疑問成為該領域不可或缺的大部頭書籍,博碩文化引進本書翻譯為繁體中文,期待藉由這本書能大幅提升台灣程式設計師的軟體設計思維。」
──博碩文化 總編輯 陳錦輝
要降低軟體元件之間的緊耦合程度,最好的方法便是引入「依賴注入(DI,Dependency Injection)」技術。在鬆耦合架構下,不用再自己手動指定資料庫連線時要使用的驅動,而是透過一個可被替換的第三方元件進行。本書將說明如何在ASP.NET Core這類應用程式框架下,利用DI架構幫助你管理軟體中的變更與複雜度議題。
《依賴注入-原理、實作、與設計模式》的前身是來自於暢銷經典書籍《Dependency Injection in .NET》一書的重編與增量版本。本書會從基礎開始從頭介紹何謂DI架構,並且在說明打造具備鬆耦合與完善架構的應用程式上,會遇到哪些設計模式、應避免的反模式、並且對此提出可供參考的範例內容。這些以C#程式語言寫成的範例,具備完善的說明註解並搭配圖表,可以幫助讀者在以現代物件導向程式語言以及支援DI架構的容器函式庫進行開發時,順暢無誤地遵循實務原則與設計模式。
本書內容
❖教你如何將既有程式碼,重構為鬆耦合架構
❖以標準物件導向程式語言觀點來實作的DI技巧
❖與標準.NET框架整合的教學內容
❖將舊版範例內容重新編寫,以.NET Core框架來示範DI架構
本書適合那些對物件導向程式語言已有一定熟悉的讀者。
延伸閱讀:
《無瑕的程式碼》系列叢書
《單元測試的藝術》
《領域驅動設計》
《Working Effectively with Legacy Code中文版》
目錄大綱
關鍵字關係圖
推薦序
來自本書第一版的讀者回饋
前言
致謝
關於本書
推薦對象
本書概要
格式說明與檔案下載
線上討論區
作者簡介
PART I 朝著依賴注入邁進
Chapter 1 依賴注入的基礎:定義、理由與實作方法
1.1 編寫易於維護的程式碼
1.1.1 對依賴注入的常見誤解
1.1.2 為何需要依賴注入
1.2 初步的範例:Hello DI!
1.2.1 Hello DI!的程式碼
1.2.2 依賴注入能帶來的好處
1.3 適合與不適合注入的對象
1.3.1 穩定依賴性
1.3.2 不穩定依賴性
1.4 依賴注入在軟體中牽涉的範疇
1.4.1 物件的組合
1.4.2 物件的生命週期
1.4.3 物件的攔截
1.4.4 三種不同面向上的 DI
1.5 小結
重點回顧
Chapter 2 緊耦合架構
2.1 先寫一份緊耦合架構出來
2.1.1 以 Mary Rowan 為例
2.1.2 建立資料層
2.1.3 建立業務層
2.1.4 建立展示層
2.2 評估緊耦合架構應用程式
2.2.1 依賴關係圖
2.2.2 對可組合性的評估
2.3 缺乏可組合性的問題根源
2.3.1 對依賴關係圖的剖析
2.3.2 對資料層的剖析
2.3.3 其他需要關注的問題
2.4 小結
重點回顧
Chapter 3 鬆耦合架構
3.1 重新打造電商網站應用程式
3.1.1 打造更具可維護性的展示層
3.1.2 打造獨立於依賴的業務層
3.1.3 打造新的資料層
3.1.4 配合 ASP.NET 核心所實作的 IUserContext
3.1.5 在「組合根」組裝你的應用程式
3.2 分析鬆耦合架構應用程式
3.2.1 元件之間的互動關係
3.2.2 分析新的依賴關係圖
3.3 小結
重點回顧
PART II 分門別類
Chapter 4 DI 設計模式
4.1 組合根
4.1.1 組合根的運作方式
4.1.2 在組合根上運用 DI 容器
4.1.3 範例:純 DI 架構的組合根
4.1.4 依賴數量的爆增表象
4.2 建構子注入
4.2.1 建構子注入的運作方式
4.2.2 建構子注入的使用時機
4.2.3 建構子注入的使用實例
4.2.4 範例:在主打商品清單加上貨幣轉換功能
4.2.5 結論是...
4.3 方法注入
4.3.1 方法注入的運作方式
4.3.2 方法注入的使用時機
4.3.3 方法注入的使用實例
4.3.4 範例:在 Product 資料實體加入貨幣轉換
4.4 屬性注入
4.4.1 屬性注入的運作方式
4.4.2 屬性注入的使用時機
4.4.3 屬性注入的使用實例
4.4.4 範例:利用屬性注入來擴展可重複利用的函式庫
4.5 如何選擇設計模式
4.6 小結
重點回顧
Chapter 5 DI 反模式
5.1 控制狂
5.1.1 範例:建立依賴關係時的控制狂
5.1.2 範例:工廠模式下的控制狂
5.1.3 範例:對建構子多載時的控制狂
5.1.4 對控制狂反模式的反思
5.2 服務定位
5.2.1 範例:ProductService 中的服務定位
5.2.2 對服務定位反模式的反思
5.3 環境物件
5.3.1 範例:查詢時間用的環境物件
5.3.2 範例:紀錄時用的環境物件
5.3.3 對環境物件反模式的反思
5.4 限制性建構
5.4.1 範例:ProductRepository 的晚期繫結
5.4.2 對限制性建構反模式的反思
5.5 小結
重點回顧
Chapter 6 程式異樣
6.1 建構子過度注入的程式異樣
6.1.1 辨識建構子過度注入
6.1.2 將建構子過度注入重構為前台模式
6.1.3 將建構子過度注入重構為業務事件
6.2 抽象工廠的濫用
6.2.1 為了生命週期問題而濫用了抽象工廠
6.2.2 為了在執行期決定依賴對象而濫用抽象工廠
6.3 循環依賴
6.3.1 範例:違反 SRP 原則造成的循環依賴
6.3.2 分析 Mary 的依賴循環
6.3.3 解決違反 SRP 問題以重構循環依賴
6.3.4 打破依賴循環的策略
6.3.5 最終手段:以屬性注入來打破依賴的循環
6.4 小結
重點回顧
PART III 單純 DI 架構
Chapter 7 應用程式的物件組合
7.1 指令列介面應用程式的物件組合
7.1.1 範例:以 UpdateCurrency 程式來更新貨幣匯率
7.1.2 建立 UpdateCurrency 程式的組合根
7.1.3 在 CreateCurrencyParser 中組合物件關聯
7.1.4 剖析 UpdateCurrency 的架構層
7.2 通用 Windows 平台應用程式的物件組合
7.2.1 UWP 應用程式的物件組合
7.2.2 範例:建立一個商品管理 app
7.2.3 在UWP 應用程式中實作組合根
7.3 ASP.NET 核心 MVC 框架應用程式的物件組合
7.3.1 自訂一個 Controller 啟動器
7.3.2 在單純DI 架構建立自訂的中介層
7.4 小結
重點回顧
Chapter 8 物件生命週期
8.1 管理依賴對象的生命週期
8.1.1 生命週期的管理
8.1.2 在單純 DI 架構下管理生命週期
8.2 處理依賴的廢棄問題
8.2.1 處理可廢棄依賴對象
8.2.2 管理可廢棄的依賴對象
8.3 生命週期型態彙整
8.3.1 單例型態
8.3.2 一次性型態
8.3.3 作用域型態
8.4 不良生命週期型態
8.4.1 被綁架的依賴
8.4.2 抽象漏洞造成的生命週期型態資訊洩漏
8.4.3 與執行緒生命週期綁定的物件會造成並行上的問題
8.5 小結
重點回顧
Chapter 9 介入攔截
9.1 關於攔截
9.1.1 裝飾者設計模式
9.1.2 範例:以裝飾者模式實作稽核機制
9.2 實作橫切關切點
9.2.1 以攔截實作斷路器設計模式
9.2.2 在回報例外錯誤時利用裝飾者模式
9.2.3 在保護機敏功能避免非法存取時利用裝飾者模式
9.3 小結
重點回顧
Chapter 10 設計面上的剖面導向程式設計
10.1 何謂剖面導向程式設計
10.2 關於 SOLID 五原則
10.2.1 單一職責原則(SRP)
10.2.2 開放封閉原則(OCP)
10.2.3 里氏替換原則(LSP)
10.2.4 介面切離原則(ISP)
10.2.5 依賴反轉原則(DIP)
10.2.6 攔截與 SOLID 五原則之間的關係
10.3 透過 SOLID 五原則達成AOP
10.3.1 範例:以 IProductService 實作商品相關功能項目
10.3.2 以 SOLID 五原則的觀點分析 IProductService
10.3.3 遵循 SOLID 五原則改善設計
10.3.4 添加更多橫切關切點機制
10.3.5 本章結語
10.4 小結
重點回顧
Chapter 11 以工具實作的剖面導向程式設計
11.1 動態攔截
11.1.1 範例:以 Castle Dynamic Proxy 實作攔截
11.1.2 對動態攔截的分析
11.2 後編譯織入
11.2.1 範例:利用後編譯織入實作交易階段剖面
11.2.2 對後編譯織入的分析
11.3 小結
重點回顧
PART IV DI 容器技術
Chapter 12 DI 容器
12.1 關於 DI 容器技術
12.1.1 關於容器技術的解析 API
12.1.2 自動裝配
12.1.3 範例:實作自動裝配功能的簡易 DI 容器
12.2 設定 DI 容器
12.2.1 以設定檔來設定容器
12.2.2 以程式化設定來設定容器
12.2.3 以自動註冊功能達到規範先於設定的容器設定方式
12.2.4 不同設定方式之間的搭配
12.3 採用 DI 容器技術的時機
12.3.1 引入第三方函式庫的成本與風險
12.3.2 單純 DI 架構能有更快的回饋循環
12.3.3 採用 DI 容器技術的確切時機
12.4 小結
重點回顧
Chapter 13 DI 容器介紹:Autofac
13.1 介紹 Autofac
13.1.1 物件解析
13.1.2 對 ContainerBuilder 的設定
13.2 管理生命週期
13.2.1 設定物件作用域
13.2.2 釋放元件
13.3 以進階 API 執行註冊
13.3.1 設定基本型別的依賴關係
13.3.2 指定物件產生來源的註冊方式
13.4 多重註冊關係的處理方式
13.4.1 多個對映選項下的抉擇方式
13.4.2 對序列的裝配
13.4.3 裝飾元件的裝配
13.4.4 合成元件的裝配
13.5 小結
重點回顧
Chapter 14 DI 容器介紹:Simple Injector
14.1 介紹 Simple Injector
14.1.1 物件解析
14.1.2 對 Container 的設定
14.2 管理生命週期
14.2.1 設定生命週期型態
14.2.2 釋放元件
14.2.3 作用域的全域管理
14.2.4 對常見生命週期議題的偵測分析
14.3 以進階 API 執行註冊
14.3.1 設定基本型別的依賴關係
14.3.2 將基本型別依賴轉為參數物件
14.3.3 指定物件產生來源的註冊方式
14.4 多重註冊關係的處理方式
14.4.1 多個對映選項下的抉擇方式
14.4.2 對序列的裝配
14.4.3 裝飾元件的裝配
14.4.4 合成元件的裝配
14.4.5 其實有著串流內在的序列
14.5 小結
重點回顧
Chapter 15 DI 容器介紹:Microsoft.Extensions.DependencyInjection
15.1 介紹Microsoft.Extensions.DependencyInjection
15.1.1 物件解析
15.1.2 對 ServiceCollection 的設定
15.2 管理生命週期
15.2.1 設定生命週期型態
15.2.2 釋放元件
15.3 以進階 API 執行註冊
15.3.1 設定基本型別的依賴關係
15.3.2 將基本型別依賴轉為參數物件
15.3.3 指定物件產生來源的註冊方式
15.4 多重註冊關係的處理方式
15.4.1 多個對映選項下的抉擇方式
15.4.2 對序列的裝配
15.4.3 裝飾元件的裝配
15.4.4 合成元件的裝配
15.5 小結
重點回顧
術語表
參考文獻
作者介紹
Steven van Deursen
自2002年起,便於荷蘭從事自由聘僱的.NET開發者與軟體架構設計師至今。生活於荷蘭奈美亨市,不論是基於興趣或出於謀生,他都很享受編寫程式的生涯。但除了編寫程式之外,Steven 也會透過武術鍛鍊身心、出門享受美食、並且還是醇美威士忌的愛好者。
Mark Seemann
居住於丹麥哥本哈根市,是一名程式設計師、軟體架構設計師、以及講師。自1995年起他便從事軟體業界至今,而後於2003年起投身於TDD測試驅動開發推動,而後在Microsoft中任職顧問、開發者、以及架構設計師有六年職涯。Mark如今在哥本哈根持續發揮其專業進行軟體開發。他熱愛閱讀、繪畫、彈奏吉他、品嚐美酒與美食。