軟體腐化的原因:--可維護性才是王道
1過於僵硬 相反:要使軟體具有 可擴充性(新效能可以很容易加入系統)
2過於脆弱 靈活性(修改不會波及其它)
3複用率低
4粘度過高 可插入性(新功能容易加入系統(氣囊加入方向盤))
解釋:
過於僵硬、過於脆弱、複用率低、粘度過高的系統都必然導致可維護性的減弱。反過來,可擴充、可插入、靈活的設計是提高可維護性的基礎,但不一定能夠保證可維護性。
有些人開發的系統高度靈活,所有資料庫欄位都可以動態添加、刪除,表也可以動態構建。可以說靈活性高、可插入、可擴充性也很強。但導致代碼超級複雜,讀起來根本就找不到北,更不用說修改了。這時候,可維護性就顯得很低。甚至在維護代碼時,不小心觸動一些關鍵組件造成系統出現問題。
有時候我提倡為開發人員寫代碼(注意:不是注釋)。有些代碼不是給客戶用的,而是給開發人員用的。包括必要的錯誤定位工具,內部調試斷點,效能計數器等等。這些代碼可以協助提高系統的可維護性。
總之,可維護性是一個綜合的概念,任何人都無法預料客戶需求會發生什麼樣的變化,“未雨綢繆”和“亡羊補牢”都是提高可維護性的一個很好切入點。測試驅動開發以及契約式開發對提高可維護性也有不少協助。
提高系統可複用性的幾點原則:
傳統複用:
1. 代碼的粘帖複用
2. 演算法的複用
3. 資料結構的複用
* 可維護性與可複用性並不完全一致
應用下面原則可以調高程式的可維護性:
一、 "開放-封閉"原則(OCP)
Open-Closed Principle原則講的是:一個軟體實體應當對擴充開放,對修改關閉。
二、 裡氏代換原則(LSP)
Liskov Substitution Principle(裡氏代換原則):子類型(subtype)必須能夠替換它們的基底類型。
三、 依賴倒置原則(DIP)
四、 介面隔離原則(ISP)
五、 合成/彙總複用原則(CARP)
六、 迪米特法則(LoD)
一、 "開放-封閉"原則(OCP)
要求我們在設計軟體的時候,應儘可能使軟體有擴充性,封閉性
Open-Closed Principle原則講的是:一個軟體實體應當對擴充開放,對修改關閉。
優點:
通過擴充已有軟體系統,可以提供新的行為,以滿足對軟體的新的需求,使變化中的軟體有一定的適應性和靈活性。
已有軟體模組,特別是最重要的抽象層模組不能再修改,這使變化中的軟體系統有一定的穩定性和延續性。
生動的例子:
例子:玉帝招安美猴王
當年大鬧天宮便是美猴王對玉帝的新挑戰。美猴王說:"'皇帝輪流做,明年到我家。'只教他搬出去,將天宮讓於我!"對於這項挑戰,太白金星給玉皇大帝提出的建議是:"降一道招安聖旨,宣上界來…,一則不勞師動眾,二則收仙有道也。"
換而言之,不勞師動眾、不破壞天規便是"閉",收仙有道便是"開"。招安之道便是玉帝天庭的"開放-封閉"原則。
招招安之法的關鍵便是不允許更改現有的天庭秩序,但允許將妖猴納入現有秩序中,從而擴充了這一秩序。用物件導向的語言來講,不允許更改的是系統的抽象層,而允許更改的是系統的實現層。
二、 裡氏代換原則(LSP)
Liskov Substitution Principle(裡氏代換原則):子類型(subtype)必須能夠替換它們的基底類型。
反過來的代換不成立
《墨子·小取》說:"娣,美人也,愛娣,非愛美人也……"娣便是妹妹,哥哥喜愛妹妹,是因為兩人是兄妹關係,而不是因為妹妹是個美人。因此,喜愛妹妹不等同於喜愛美人。用物件導向語言描述,美人是基類,妹妹是美人的子類。哥哥作為一個有"喜愛()"方法,接受妹妹作為參數。那麼,這個"喜愛()"方法一般不能接受美人的執行個體。
三、?依賴倒置原則(DIP)
依賴倒置(Dependence Inversion Principle)原則講的是:要依賴於抽象,不要依賴於具體。
簡單的說,依賴倒置原則要求用戶端依賴於抽象耦合。原則表述:
抽象不應當依賴於細節;細節應當依賴於抽象;
要針對介面編程,不針對實現編程。
反面例子:
缺點:耦合太緊密,Light發生變化將影響ToggleSwitch。
解決辦法一:
將Light作成Abstract,然後具體類繼承自Light。
優點:ToggleSwitch依賴於抽象類別Light,具有更高的穩定性,而BulbLight與TubeLight繼承自Light,可以根據"開放-封閉"原則進行擴充。只要Light不發生變化,BulbLight與TubeLight的變化就不會波及ToggleSwitch。缺點:如果用ToggleSwitch控制一台電視就很困難了。總不能讓TV繼承自Light吧。
解決方案二:
?
優點:更為通用、更為穩定。
結論:
使用傳統過程化程式設計所建立的依賴關係,策略依賴於細節,這是糟糕的,因為策略受到細節改變的影響。依賴倒置原則使細節和策略都依賴於抽象,抽象的穩定性決定了系統的穩定性。
四、?介面隔離原則(ISP)
介面隔離原則(Interface Segregation Principle)講的是:使用多個專門的介面比使用單一的總介面總要好。換而言之,從一個客戶類的角度來講:一個類對另外一個類的依賴性應當是建立在最小介面上的。
過於臃腫的介面是對介面的汙染。不應該強迫客戶依賴於它們不用的方法。
五、?合成/彙總複用原則(CARP)
合成/彙總複用原則(Composite/Aggregate Reuse Principle或CARP)經常又叫做合成複用原則(Composite Reuse Principle或CRP),就是在一個新的對象裡面使用一些已有的對象,使之成為新對象的一部分;新對象通過向這些對象的委派達到複用已有功能的目的。
簡而言之,要盡量使用合成/彙總,盡量不要使用繼承。
六、?迪米特法則(LoD)
迪米特法則(Law of Demeter或簡寫LoD)又叫最少知識原則(Least Knowledge Principle或簡寫為LKP),也就是說,一個對象應當對其它對象有儘可能少的瞭解。
其它表述:
??只與你直接的朋友們通訊
??不要跟"陌生人"說話
??每一個軟體單位對其它的單位都只有最少的知識,而且局限於那些與本單位密切相關的軟體單位。
迪米特法則與設計模式
Facade模式、Mediator模式
使民無知
《老子》第三章曰:"是以聖人之治,虛其心,實其腹,弱其志,常使民無知無欲。"使被"統治"的對象"愚昧"化,處於"無知"的狀態,可以使"統治"的成本降低。
所謂"最少知識"原則,實際上便是老子的"使民無知"的統治之術。
不相往來
《老子》云:"小國寡民……鄰國相望,雞犬之聲相聞,民至老死,不相往來。"將被統治的對象隔離開來,使它們沒有直接的通訊,可以達到分化瓦解,繼而分而治之的效果。迪米特法則與老子的"小國寡民"的統治之術不謀而合。