DI Anti Patterns - Service Locator

前言: 在前一篇的 Anti-Pattern 中我們介紹了最經典的反模式:Control Freak 。而在這篇我們要介紹的另外一個常見的反模式可以說是他的進化版本,尤其是這個模式是知名的架構師 Martin Fowler 提出的。不過在數年後有人挑戰了這個想法,該文章的討論串比正文還要長,但思辨的過程還是值得一看。 常見類型 Anti-pattern Description Control Freak 依賴反轉(Inversion of Control)的對立面,直接控制實體 Service Locator 使用一個內隱服務提供依賴給呼叫端 Ambient Context 使用靜態存取子,提供單一的依賴 Constrained Construction 讓建構子有一個特定的方法簽章 Service Locator 定義 是一種軟體開發中的設計模式,通過一個集中註冊表(通常會是 Singleton)來處理請求並返回處理特定任務所需的必要訊息。最常見的實做方式通常就是利用 Static Factory 來實做這個註冊表。而系統中可以在系統進入點以外的地方呼叫這個註冊表的方法取得指定的實做。 表準案例 1 2 3 4 5 6 7 8 9 10 11 12 13 14 public class HomeController : Controller { public HomeController() { } public ViewResult Index() { IProductService service = Locator.GetService<IProductService>(); var products = service.GetProducts(); return this.View(products); } } 1 2 3 4 5 6 7 8 9 10 11 public class ProductService : IProductService { private readonly IProductRepository repository; public ProductService() { this.repository = Locator.GetService<IProductRepository>(); } public IEnumerable<Product> GetProducts() { return this.repository.GetProducts(); } } 這邊可以看到當要使用 IProductService 時,就呼叫註冊表的方法來取得實做,但這個依賴關係因為不是在建構時給予因此從外部會不容易知道他們兩者之間會有這樣的關係存在。另外這個作法同樣也會遇到 Static Factory 會遇到的問題,只是 Service Locator 將原本呼叫與依賴關係建立的那一層做了一個包裝。原本的 Static Factory 會與實做相同介面的類別緊緊的綁在一個 Factory 類別中,而包裝起來之後變成所有類型的依賴與實做會都綁在 Service Locator 這個類別裡,它變得與更多依賴有關。同時,在使用上每個需要取得依賴的地方都需要能存取 Service Locator 。 ...

February 17, 2019 · 2 分鐘 · 373 字

DI Anti Patterns - Control Freak

前言 現在很多系統在撰寫時都會使用到一些常見 DI Container 尤其在使用一些編譯式語言(ex. .Net, Java)時(Autofac for .Net, Unity for .Net, guice for Java, di-ninja for NodeJS 等族繁不及備載…)。不過系統即使用上這些 container 只要使用方式不正確,還是可以寫出強耦合性的程式,因此這邊要來介紹一些常見的 Anti-patterns,避免自己寫出高耦合性的程式。 這一篇基本上是 Dependency Injection in .Net 這本書第二版在第五章的心得 (第二版叫 Dependency Injection Principles, Practices, and Patterns)。雖然他連簡體中文的翻譯都還沒有出來,不過還是相當推薦買來看看。 常見類型 Anti-pattern Description Control Freak 依賴反轉(Inversion of Control)的對立面,直接控制實體 Service Locator 使用一個內隱服務提供依賴給呼叫端 Ambient Context 使用靜態存取子,提供單一的依賴 Constrained Construction 讓建構子有一個特定的方法簽章 Control Freak 定義 就是直接了當的把你需要的實體給產生出來,這個與依賴反轉的原則剛好相違背。 案例 標準案例 1 2 3 4 5 6 7 8 9 public string GetContent(string fileName) { // 這個直接把要使用的實體寫在呼叫時 var saveService = new FileSaveService(); var fileContent = saveService.Read($"{fileName}.txt"); return fileContent; } 基本上這個寫法比較容易出現在所謂的 legacy code 裡,近年來 program to an interface 的意識抬頭,工程師應該都不會這樣寫了。 ...

January 20, 2019 · 3 分鐘 · 449 字