軟件設計原則介紹:
軟件設計的目的:代碼複用性、可擴展性、可維護性。
高內聚低耦合(High Cohesion & Low coupling)
高內聚,就是對軟件系統中元素職責相關性和集中度高的功能放一起。在編寫代碼時,代碼內的功能職責相關性高的放在一起。
與之相反 - 低耦合,低耦合是對元素與元素之間的連接、依賴的程度輕重描述。這裏元素是指函數、類(對象),也可以指功能,系統,子系統,組件,模塊等。
低耦合就是在編寫軟件時,儘量做到類與類、文件與文件、模塊與模塊,系統與系統之間儘量的獨立存在,互不干擾。
DRY原則(Don't Repeat Yourself)
DRY 原則是指在代碼設計編寫中避免重複代碼。
在代碼編寫中不應該出現重複的邏輯、屬性等,對某些功能已存在代碼應該重複使用,不應該在多個實例中拷貝相同的代碼片段。
避免重複代碼可以提高代碼的可維護性,當需求變更時只需要在一處修改就能生效。
關注點分離(Separation of concerns,SoC)
在計算機編程裏,關注點分離(Separation of concerns,SoC),是將計算機程序分隔爲不同部分的設計原則,每一部分會有自己關注的焦點,圍繞焦點來進行內容的聚集。
在編碼設計中,體現關注點分離原則的有程序的模塊化。區分關注的焦點,圍繞與焦點相關的操作,把它們封裝在具有明確邊界的程序代碼段中。
還有分層設計也體現了關注點分離這一原則,比如 MVC 分層,M 模型層、V 表示層、C 控制層 。
關注點分離的目的是要簡化程序開發和維護。
KISS原則(Keep It Simple, Stupid)
kiss 原則(Keep It Simple, Stupid)就是簡單優於複雜。
不管是程序設計還是系統設計都應該儘量保持簡單,不要過度設計,不要增加無用功能,因爲這些都可能導致系統複雜度增加。
面向對象的SOLID原則
單一職責原則(Single Responsible Principle, SRP)
單一職責原則(Single Responsibility Principle,SRP)又稱單一功能原則,一個類或模塊只負責一項功能和業務邏輯。馬丁把這裏的職責指引起類變化的原因,單一職責規定一個類有且只有一個引起它變化的原因,否則類應該被拆分。
這個原則提出是由羅伯特·C·馬丁(Robert Cecil Martin)在他的《敏捷軟件開發,原則,模式和實踐》一書中,一篇名爲〈面向對象設計原則〉的文章中給出。馬丁表述該原則是基於《結構化分析和系統規格》一書中的內聚原則(Cohesion)上。
該原則提出了一個類不應該承擔太多職責。如果一個類承擔太多職責,那麼類中一個職責的變化也可能引起其它職責的變化。承擔太多職責也會導致類過於複雜,不利於程序變更和維護。
開閉原則(Open Closed Principle,OCP)
開閉原則(Open Closed Principle,OCP):軟件實體應該對擴展開放,對修改關閉。
這個原則是說當應用的需求改變時,優先通過擴展現有代碼功能,使其滿足需求。也即是說當增加或修改需求時,可以通過增加代碼來滿足需求的變化,而不是修改原來的代碼滿足需求變化。
實現方法的話,可以通過 “抽象約束、封裝變化”,即是通過接口或抽象類來爲軟件實體定義一個相對穩定的抽象層,將相同的可變因素封裝在相同的具體實現類中。因爲抽象靈活適應強,進行合理的抽象,可以保持程序軟件架構的穩定。把易變的程序部分,用繼承擴展抽象的實現類來進行擴展,當需求變化時,從抽象來實現一個擴展功能就可以了。
里氏替換原則(Liskov Substitution Principle,LSP)
里氏替換原則(Liskov Substitution Principle,LSP):繼承必須確保超類所擁有的性質在子類中仍然成立。
這個原則說明了使用繼承的原則,反映了父類和子類的關係。子類可以擴展父類的功能,而不應該改變父類原有的功能。父類可以被子類替換。它也是實現開閉原則的重要方式之一。也是保證類擴展後不會給已有的程序系統引入新的錯誤。
具體實現方法的話,需求變化時,子類繼承父類,在子類中添加新的方法應對需求變化,儘量不要重寫父類中的方法。
依賴倒置原則(Dependence Inversion Principle,DIP)
依賴倒置原則(Dependence Inversion Principle,DIP):上層模塊不應該依賴下層模塊,兩者應該依賴抽象;抽象不應該依賴細節,細節應該依賴抽象。
對上面這句話直接理解就是:面向接口(抽象)編程,不要面向實現編程
。通過引入抽象來減少程序間依賴,降低模塊與模塊、程序與程序之間的耦合。這也是上面 “高內聚低耦合” 原則中低耦合實現的重要方式。
在程序設計中,細節往往易變多變(實際上是需求變化多端引起程序細節變化),而良好抽象則相對穩定。因此通過良好的抽象來進行程序設計,比以細節爲基礎來進行程序設計往往要穩定。當然這是一個辯證關係,對細節瞭解足夠多,才能進行良好抽象。
具體到面嚮對象語言設計中,抽象指的就是接口或抽象類,細節則是具體的實現類。利用接口或抽象類來制定規範或契約,而不涉及具體操作細節,把實現細節的任務交給實現類來完成。
接口隔離原則(Interface Segregation Principle,ISP)
接口隔離原則(Interface Segregation Principle,ISP):一個類對另一個類的依賴應該建立在最小的接口上。另外的定義就是程序不應該被迫依賴它不需要的方法。
建立在最小接口上,那可以對接口進行拆分處理,把龐大的接口拆分成更小接口和更具體的接口,讓類實現僅依賴它需要的接口。而不是建立一個龐大的接口供所有依賴它的類去使用。拆分時候也要遵循高內聚低耦合原則和單一職責原則。
具體實現方法,就是上面說的接口拆分儘量小,但也不要無限小還是要掌握好度。一個接口只服務於一個業務邏輯,只提供調用者需要的方法。遵循內聚性,儘量減少與外界交互。
迪米特法則(Law of Demeter,LoD)
迪米特法則(Law of Demeter,LoD)又叫最少知道原則,只與你直接的朋友談,不要跟陌生人說話。它的含義就是如果兩個軟件實體能不直接通信,就不要相互調用,可以通過第三方來實現調用。這個與前面的 “低耦合” 又相關,就是降低類與類、模塊與模塊之間的耦合度。
迪米特法則就是降低類與類之間的耦合度,提高類的相對獨立性,提高複用性。
合成複用原則(Composite Reuse Principle,CRP)
合成複用原則(Composite Reuse Principle,CRP),它又叫聚合/組合原則。在程序設計時,儘量使用組合/聚合關係來實現程序功能,其次才考慮使用繼承關係來實現功能。
合成複用同里氏替換兩者相輔相成,都是開閉原則的具體實現規範。
爲什麼建議先用組合,後用繼承,繼承的一些缺點:
- 子類與父類耦合高。子類與父類具有某種連接,父類的實現細節繼承給了子類,它們之間就出現連接,就耦合了。
- 限制了複用的靈活性。從父類繼承而來的實現是靜態,編譯時已經定義,在運行時不可能發生改變。
控制反轉IoC/依賴注入DI
控制反轉(Inversion of Control,IoC),這個原則也是 “高內聚低耦合” 中低耦合的一種實現。
在面向對象程序設計中,應用程序都是通過兩個或更多類,通過彼此合作來實現業務邏輯,這使得每個對象都需要獲取與其合作的對象(也就是它依賴的對象)的引用,如果獲取這個對象是靠自身實現,那麼代碼耦合度將變高。
具體實現方式有:依賴注入DI和依賴查找。
依賴注入在 Spring 框架中使用廣泛,依賴注入實現方式又有好多種:
- 基於接口。實現特定接口以供外部容器注入所依賴類型的對象。
- 基於 set 方法。
- 基於構造函數。
- 基於註解。
依賴查找的方式,比如將框架提供的方法集中放在某個文件中,使用時在進行調用。
依賴穩定原則
前面提高的依賴接口,依賴抽象,都是依賴穩定的原則。
軟件系統的構建要依賴穩定、可靠、變化小的程序。