作為一個程式設計師,我們都希望程式越寫越好,而其中物件導向是最為重要之一的概念。
物件導向遵從著 SOLID 的原則來執行,遵循 SOLID 原則,基本上可以提升整體程式的可維護性、可讀性以及可擴充性。
本篇主題 Dependency Injection 依賴注入,將會實現 SOLID 中的 Dependency Inversion Principle(DIP) 依賴反轉與 Inversion of Control(IoC) 控制反轉,並藉由 ASP.NET Core (.NET 5)的簡單實作來示範導入 DI 的好處。
在強耦合的程式當中,High-Level 的 Function 必須依賴 Low-Level 的 Function 才可實現功能需求,而 DIP 原則則是將兩者的依賴關係變成都依賴著抽象,以此來達到解耦合的目的。
e.g.
public class GetSchoolService
{
DAO Dao = new DAO();
DTO Dto = Dao.GetById(id);
// 一些對 SQL Server 的操作邏輯
Dao.Save(Dto);
}
public class DAO // 對 SQL Server 進行操作
{
public DTO GetById(int id)
{
// 一些邏輯
}
public void Save(DTO dto)
{
// 一些邏輯
}
}
此處的 GetSchoolService
依賴著 DAO
Class 的實作,現在 DAO
的整體實作都是針對 SQL Server 進行撰寫,如果現在換成了 MariaDB 或是換成假資料,那麼 GetSchoolService
的整體邏輯則需要重寫。
進行改寫:
public class GetSchoolService
{
private DAO _dao;
public GetSchoolService(IDAO dao) // 透過介面傳入
{
_dao = dao;
}
}
public interface IDAO
{
public DTO GetById(int id);
public void Save(DTO dto);
}
public class SqlServerDao : IDAO
{
public DTO GetById(int id)
{
// 一些邏輯
}
public void Save(DTO dto)
{
// 一些邏輯
}
}
經過改寫後可以發現,High-Level 的 GetSchoolService
function 現在依賴著抽象的介面,而 Low-Level 的 DAO 也依賴著抽象的介面。
以結果來看,其實就是把 function 中,new (實體化)的部分清掉,就是在解耦合。
IoC 目的與 DIP 差不多,都是為了解耦合以及易於擴充、維護,而 IoC 的概念為:「將依賴關係交由第三方容器(container)控制。」
e.g.:
小明今天想請個秘書來管理公司的雜事,於是他自己去網路上各大社團徵才與聯繫,好不容易來了一個秘書,但卻在三個月後離職,此時小明又要去各大社團徵才了,找人、聯繫這些事情都在小明身上(強耦合),假設今天網路壞掉或是徵才網站維修,小明不就找不到祕書了。
而 IoC 就像在這篇故事中加入一個人力仲介公司(Container)的腳色,變成小明與人力仲介公司合作,說他現在缺人,請人力仲介公司指派一位秘書過來,而未來若秘書離職了,找人與聯繫的事情也不會在小明身上,而是人力仲介公司的事情,小明輕鬆多了。
而 DI 其實就是 IoC 的實現化,不同程式語言、框架,也有適用於它們的 DI Framework,而 .NET 5(.NET Core)內建了微軟自己的 DI Framework。
https://www.tutorialsteacher.com/ioc/introduction
https://coolshell.cn/articles/9949.html
https://lotabout.me/2018/Dependency-Inversion-Principle/
https://dotblogs.com.tw/daniel/2018/01/17/140435
https://gunnarpeipman.com/using-dependency-injection-with-view-components