設計原則為提高可維護性和可復用性而生,每一種設計模式都符合一個或多個設計原則,因此設計原則也是評價一個設計模式使用效果的重要指標之一。 ...
經典設計原則除了 SOLID 之外,常見的還包括 KISS、YAGNI、DRY、LOD、CRP 等幾種:
- KISS(Keep It Simple & Stupid, 儘量保持簡單)
- YAGNI(You Ain't Gonna Need It, 你不會需要它)
- DRY(Don't Repeat Yourself, 不要重覆自己)
- LOD(Law Of Demeter, 迪米特法則)
- CRP(Composite Reuse Principle, 合成復用原則)
KISS 原則
理解
KISS 原則的英文描述有很多版本,如下:
- Keep It Simple & Stupid
- Keep It Sweet & Simple
- Keep It Short & Simple
- Keep It Simple & Straightforward
它們的含義都差不多,其實就是“儘量保持簡單”。
但是,並不是代碼行數越少就越“簡單”,還要考慮邏輯複雜度、實現難度、代碼的可讀性等。並且,有些本身就複雜的問題,用複雜的方法解決,並不能算是違背 KISS 原則。
優點
遵循 KISS 原則,將會有以下的優點:
- 簡單地編寫代碼,理解該代碼不會有任何困難,將更容易修改,而且花費的時間也會大大減少
最佳實踐
在實際開發中,可以通過以下情況判斷代碼是否滿足 KISS 原則:
- 不要使用協作者可能不懂的技術來實現代碼
- 不要重覆造輪子,要善於使用已經有的工具類
- 不要過度優化,犧牲代碼的可讀性
YAGNI 原則
理解
YAGNI 原則的核心思想就是不要過度設計,即不要去設計當前用不到的功能,不要去編寫當前用不到的代碼。
優點
遵循 YAGNI 原則,將會有以下的優點:
- 過度設計往往會延緩開發的迭代速度,減少過度設計將能支持創業公司的快速迭代
- 編寫只符合當前場景的代碼質量可能會更高,這也是 KISS 原則的另一種實踐
最佳實踐
雖然說,在不需要某功能前,不要提前去實現此功能。但是,在可預見的情況下,需要預留好擴展點,等到實現此功能時能無縫接入。
比如,系統在當前只需要使用 Redis 存儲配置信息,以後有可能會用到 ZooKeeper 存儲配置信息。根據 YAGNI 原則,當前沒有必要編寫 ZooKeeper 的代碼,但是可以通過抽象出統一的配置存儲介面作為擴展點,方便後續可以快速接入。
DRY 原則
理解
DRY 原則可以理解成不要寫重覆的代碼,解決的是代碼的復用性問題。
優點
遵循 DRY 原則,將會有以下的優點:
- 對於頻繁更改需求的情況,重覆代碼將會增加修改代碼的痛苦
- 遵循 DRY 原則要求開發者具備高度抽象思維,高度抽象的代碼具備高可維護性、高擴展性
最佳實踐
常見代碼重覆情況
實現邏輯重覆,但功能語義不重覆的代碼,並不違反 DRY 原則。
比如說,一個檢驗用戶名和檢驗密碼的代碼在編寫上完全一致,因此寫了 isValidUserName()
和 isValidPassword()
兩個函數,但其實這兩個函數並不能算作違反 DRY 原則。
功能語義重覆,但實現邏輯不重覆的代碼,視為違反 DRY 原則。
其原則在於,對於完全相同的功能,不允許出現兩個及其以上的對外介面,更不允許出現不同的代碼表示同一個功能。
隱藏的執行重覆被認定違反 DRY 原則。
即當運行完一個代碼流程之後,出現相同的函數被無意義地執行過兩次及其以上,則被稱為執行重覆,這是一種隱藏的違反 DRY 原則的行為。
代碼復用性
總結有以下方法可以提高代碼的可復用性:
- 減少代碼耦合
- 滿足單一職責原則
- 善於模塊化
- 業務與非業務邏輯分離
- 通用代碼下沉
- 善用面向對象的特性
- 應用設計模式
事不過三
“3”是一個非常神奇的數字,“事不過三”是它的一種特殊用法,這個原則可以應用在編寫可復用代碼的時候。
可以這麼理解:第一次寫代碼時,如果當下沒有復用的需求,而未來的復用需求也不是很明確,並且開發可復用代碼的成本比較高,那就不需要考慮代碼的復用性;第二次遇到復用場景的時候,再進行重構使其變得可復用。
LOD 原則
理解
LOD(迪米特) 原則也被叫作最小知識法則(Least Knowledge Principle, LKP),其含義是不該有依賴的模塊之間不要有依賴,有依賴關係的模塊之間儘量只依賴必要的介面。
迪米特原則有點類似於介面隔離原則,希望能減少類之間的耦合,讓類越獨立越好。
優點
遵循迪米特原則,將會有以下的優點:
- 降低類之間的耦合度,提高了模塊的相對獨立性
- 提高類的可復用率和系統的擴展性
最佳實踐
迪米特原則還有幾種定義形式:不要和陌生人“說話”,只與你的直接朋友通信等。
在迪米特原則中,對於一個對象,其“朋友”包括以下幾類:
- 當前對象本身
- 以參數形式傳入到當前對象方法中的對象
- 當前對象的成員對象
- 如果當前對象的成員對象是一個集合,那麼集合中的對象也都是朋友
- 當前對象所創建的對象
CRP 原則
理解
CRP 原則又稱為組合/聚合復用原則,其含義是,儘量使用對象組合,而不是繼承來達到復用的目的。
通過繼承來進行復用的主要問題在於,繼承復用會破壞系統的封裝性。當基類發生了改變,繼承基類的子類也會不可避免地發生改變,從基類繼承而來的實現是靜態的,不可能在運行時發生變化,沒有足夠的靈活性。
通過組合或聚合關係可以將已有的對象納入新對象中,使之成為新對象的一部分,因此新對象可以調用已有對象的功能,這樣關係不會將已有對象的實現細節暴露給新對象。
相對繼承而言,組合和聚合復用的耦合度更低,相互之間的影響不大,實際開發中可以有選擇性地調用需要的功能。
優點
遵循 CRP 原則,將會有以下的優點:
- 系統更加靈活,降低了類與類之間的耦合度,一個類的變化對其他類造成的影響相對較小
最佳實踐
一般而言,如果兩個類之間是“Has-A”的關係,應使用組合或聚合;如果是“Is-A”的關係,可以使用繼承。