>> 物件導向設計的演進:SOLID與Dependency Injection
2014 / 07 / 11 by 程式開發管理者
以往在發展物件導向程式時,大多是直接取用物件 (new Object()) 的作法,它是物件導向最基本的操作方式,許多開發人員也都很習慣這樣的作法,只不過直接取用物件有個很大的缺點,就是物件的相依性 (Dependency),這一new下去,代表著用戶端程式永遠無法脫離這個物件的掌握。而近年來由Java陣營吹向.NET的一股浪潮,讓.NET社群開始思考物件是否一定要使用new的作法,相依性是軟體擴充性的絆腳石之一,若沒有在程式開發時將相依性切斷的話,日後要維護可就難了。想像一下若程式中new出的物件有新版,或是有更好的作法能取代原有的物件,那麼光是要修改那些new,就夠大家受的了。

想要解決相依性的問題,我們需要回頭看一下自己的程式,是否有夠高的內聚力以及夠低的耦合度,高內聚力代表物件不必依賴外部物件;低耦合代表物件和其他外部物件的相依性較低,也不會因為外部物件的影響而異動。但要符合高內聚與低耦合的條件並不容易,但我們可以參考一下由Uncle Bob (Robert C. Martin) 提出的SOLID原則,它可以給我們一些重要的指引。

SOLID分別代表五個不同的原則:
  • 單一職責原則 (Single Responsibility Principle, SRP):物件內的每個成員都只負責一項職責,有兩個以上時切割為兩個以上的不同方法,有利於方法的共用與內部流程的重組。
  • 開放封閉原則 (Open-Close Principle, OCP):對擴充能力保持開放,但對修改內部流程封閉,符合OCP的程式的穩定度會較高,外部程式也不會因為元件的更替而受影響。
  • 子物件替換原則 (Liskov’s Substitution Principle, LSP):任何與父物件有繼承關係的子物件,都可隨時替換父物件,而且用戶端程式不會因為替換而有所影響。 
  • 介面隔離原則 (Interface Segmentation Principle, ISP):元件應該提供給個別用戶端專屬介面,以避免不同用戶端在共用同一個元件時的相互干擾,間接提升穩定性。
  • 相依反轉原則 (Dependency Inversion Principle, DIP):程式存取元件時應該相依於抽象 (abstract),而非實作 (concrete),抽象可由不同的實作抽換,而且抽換實作時用戶端也不會因為相依於抽象而有所變動,抽象可以是抽象類別 (abstract class) 或是介面 (interface),一般而言,抽象通常泛指介面,因為抽象類別還是有一小部份的實作,除非抽象類別本身並沒有任何實作碼。

其中的DIP原則現在已被Java與.NET陣營廣泛使用,DIP原則確保了程式的可抽換性 (pluggable),在用戶端相依於抽象的情況下,可透過程式或是組態檔 (configuration) 的方式抽換預設的實作,對軟體的可擴充性有顯著的幫助,同時也允許了使用者能自行發展自己的模組,然後加到現有的系統內,在不更動用戶端程式的情況下啟用自己的模組,提供客制化的能力。

不過有趣的是,物件導向程式並沒有辦法將抽象實體化,因為抽象本身是沒有實作的,這表示我們要讓DIP原則能成功,勢必一定要有抽象和實作的對應,這個對應表會幫我們處理好抽象的生成,開發人員也不用傷腦筋它的實作細節,只要告訴這個對應表抽象與實作的關係,以及在必要時傳給它必要的參數即可。這個表稱為Dependency Injection (相依注射, DI)。透過DI的實作,程式才能真正達到DIP原則的要求,所有的程式都能利用DI來取得相應的物件實體,而開發人員也能利用程式或是組態檔的方式來抽換不同的模組-只要確保它們有實作抽象的部份即可。

DIP原則與DI的應用,介面導向程式設計 (Interface Oriented Programming) 的應用更加的廣泛,介面代表了元件與模組開放給外部程式的規格,外部程式只要依照這份規格就能取用服務,而不必擔心元件是怎麼樣提供服務的,在下一代的ASP.NET (ASP.NET vNext) 中,DI扮演著相當吃重的核心角色,ASP.NET使用DI實現了相當強大的模組可抽換能力,包括OWIN、MVC、Entity Framework、SignalR等都能看到DI的活躍,甚至於用戶端的AngularJS也都擁抱了DI來實作模組的抽換,可見DI的重要性。

目前DI的實作有幾種,包括眾所週知的Spring.NET、Autofac、StructureMap、Unity Application Block、Ninject以及Windsor等,它們都擁有相同的功能,並提供了更多像物件生命週期 (Lifetime)、泛型、單一個體容器等功能,以支援整合Design Patterns的實作,未來我們會看到更多.NET以及其他大型的Framework對DI的充份支援,就如同技術的時尚一般。
其他趨勢文章
>>
Google 的新演算法 — Rankbrain
2016.06.27 by 小朱
>>
被技術服務導向綁架的資訊服務業
2016.05.18 by J.T Wang
>>
物件導向設計的演進:SOLID與Dependency Injection
2014.07.11 by 小朱
Top

高雄 Kaohsiung

TEL : 07-5583368
FAX : 07-5585696
ADD:高雄市左營區裕誠路394號9樓之2

台北 Taipei

TEL : 02-77192489
FAX : 02-27478929
ADD:台北市信義區基隆路一段141號4樓之10

奇豐資訊科技版權所有
© 2015 KINGFOR All Rights Reserved