系列文章|源碼
https://github.com/tyronczt/design-mode-learn
概述
軟件項(xiàng)目中莲兢,需求是不斷變化的冬竟,需求也是項(xiàng)目中最難把控的哲思,需求的變更也是無(wú)法避免的。我們寫的軟件程序佳鳖,如何能實(shí)現(xiàn)擁抱變化霍殴,使我們的軟件達(dá)到 可維護(hù) 和 可復(fù)用 ,這是一代代軟件工程師不斷追尋的真理系吩。
導(dǎo)致一個(gè)軟件的可維護(hù)性較低的原因有四個(gè):
- 過于僵硬(Rigidity)
很難在一個(gè)軟件系統(tǒng)里加入新的特性来庭,一旦加入新的特性就會(huì)影響到其他模塊的功能,最后會(huì)變成跨越幾個(gè)模塊的改動(dòng)穿挨,由于設(shè)計(jì)上的缺陷月弛,導(dǎo)致不敢輕易往原有的系統(tǒng)中添加新的特性的僵硬化的情況。
- 過于脆弱(Fragility)
與過于僵硬同時(shí)存在科盛。對(duì)一個(gè)地方的修改帽衙,往往會(huì)導(dǎo)致看起來沒有什么關(guān)系的另一個(gè)地方發(fā)生故障,盡管在修改前土涝,設(shè)計(jì)師會(huì)竭盡所能預(yù)測(cè)可能的故障點(diǎn)佛寿,但是在修改完成之前幌墓,系統(tǒng)的原始設(shè)計(jì)師甚至都無(wú)法預(yù)測(cè)到可能會(huì)波及的地方但壮,這種一碰就碎的情況,就是軟件系統(tǒng)過于脆弱常侣。
- 復(fù)用率低(Immobility)
所謂復(fù)用蜡饵,就是指一個(gè)軟件的組成部分,可以在一個(gè)項(xiàng)目的不同地方甚至不同的項(xiàng)目中重復(fù)使用胳施。每當(dāng)程序員發(fā)現(xiàn)一段代碼溯祸、函數(shù)、模塊的功能可以在新模塊或者新系統(tǒng)中使用舞肆,但是發(fā)現(xiàn)這些現(xiàn)存的代碼焦辅、函數(shù)、模塊依賴于一大堆其他的東西椿胯,以至于很難將他們分開筷登。最后,他們發(fā)現(xiàn)最好的辦法就是不去碰這些東西哩盲,而是重寫自己的代碼前方。
這樣的系統(tǒng)存在復(fù)用率低的問題狈醉。
- 黏度過高(Viscosity)
對(duì)系統(tǒng)的改動(dòng)可以采取保存原始設(shè)計(jì)意圖和設(shè)計(jì)框架的方式,也可以以破壞原始意圖和框架的方式進(jìn)行惠险。前者對(duì)系統(tǒng)未來有利苗傅,而后者是權(quán)宜之計(jì),可以解決短期問題班巩,但會(huì)犧牲中長(zhǎng)期利益渣慕。如果一個(gè)系統(tǒng)設(shè)計(jì),總是使得第二種辦法比第一種容易抱慌,就叫黏度過高摇庙。
一個(gè)好的系統(tǒng)設(shè)計(jì)應(yīng)該具備如下性質(zhì):
- 可擴(kuò)展性(Extensibility)
新的特性很容易加入到系統(tǒng)中去,就是可擴(kuò)展性遥缕,就是“過于僵硬”反面卫袒。
- 靈活性(Flexibility)
可以允許代碼修改平穩(wěn)地發(fā)生,而不會(huì)波及到很多其他的模塊单匣。靈活性就是“過于脆弱”的反面夕凝。
- 可插入性(Pluggability)
可以很容易的將一個(gè)類抽出去,同時(shí)將一個(gè)有同樣接口的類加入進(jìn)來户秤,這就是可插入性码秉。
提高系統(tǒng)可維護(hù)性和可復(fù)用性的設(shè)計(jì)原則
面向?qū)ο笤O(shè)計(jì)原則為支持可維護(hù)性復(fù)用而誕生,這些原則蘊(yùn)含在很多設(shè)計(jì)模式中鸡号,它們是從許多設(shè)計(jì)方案中總結(jié)出的指導(dǎo)性原則转砖。面向?qū)ο笤O(shè)計(jì)原則也是我們用于評(píng)價(jià)一個(gè)設(shè)計(jì)模式的使用效果的重要指標(biāo)之一。
單一職責(zé)原則(Single Responsibility Principle, SRP)
一個(gè)類只負(fù)責(zé)一個(gè)功能領(lǐng)域中的相應(yīng)職責(zé)
開閉原則(Open-Closed Principle, OCP)
軟件實(shí)體應(yīng)對(duì)擴(kuò)展開放鲸伴,而對(duì)修改關(guān)閉
里氏代換原則(Liskov Substitution Principle, LSP)
所有引用基類對(duì)象的地方能夠透明地使用其子類的對(duì)象
依賴倒轉(zhuǎn)原則(Dependence Inversion Principle, DIP)
抽象不應(yīng)該依賴于細(xì)節(jié)府蔗,細(xì)節(jié)應(yīng)該依賴于抽象
接口隔離原則(Interface Segregation Principle, ISP)
使用多個(gè)專門的接口,而不使用單一的總接口
合成復(fù)用原則(Composite Reuse Principle, CRP)
盡量使用對(duì)象組合汞窗,而不是繼承來達(dá)到復(fù)用的目的
迪米特法則(Law of Demeter, LoD)
一個(gè)軟件實(shí)體應(yīng)當(dāng)盡可能少地與其他實(shí)體發(fā)生相互作用
軟件的可復(fù)用性
復(fù)用的重要性
較高的生產(chǎn)率姓赤,較高的軟件質(zhì)量,恰當(dāng)?shù)膹?fù)用可以改善系統(tǒng)的可維護(hù)性仲吏。
傳統(tǒng)的復(fù)用
代碼的剪貼復(fù)用不铆,算法的復(fù)用,數(shù)據(jù)結(jié)構(gòu)的復(fù)用裹唆。
面向?qū)ο蟮脑O(shè)計(jì)的復(fù)用
面向?qū)ο蟮恼Z(yǔ)言中誓斥,數(shù)據(jù)的抽象化、繼承许帐、封裝和多態(tài)的特性是幾項(xiàng)最重要的語(yǔ)言特性劳坑,這些特性使得一個(gè)系統(tǒng)可以在更高的層次上提供可復(fù)用性。數(shù)據(jù)的抽象化和繼承可以使得概念和定義得以復(fù)用舞吭,多態(tài)性使得實(shí)現(xiàn)和應(yīng)用可以復(fù)用泡垃,而抽象化和封裝可以保持和促進(jìn)系統(tǒng)的可維護(hù)性析珊。這樣,復(fù)用的焦點(diǎn)不再集中在函數(shù)蔑穴、算法等具體的實(shí)現(xiàn)細(xì)節(jié)上忠寻,而是集中在最重要的具有宏觀商業(yè)邏輯的抽象層次上。
抽象層是一個(gè)應(yīng)用系統(tǒng)做戰(zhàn)略性判斷和決定的地方存和,那么抽象層次應(yīng)當(dāng)是較為穩(wěn)定的奕剃,應(yīng)當(dāng)是復(fù)用的重點(diǎn)。如果抽象層次的模塊相對(duì)獨(dú)立于具體層次的模塊捐腿,那么具體層次的變化不會(huì)影響到抽象層次的纵朋,所以抽象層次模塊的復(fù)用會(huì)比較容易。
在面向?qū)ο蟮脑O(shè)計(jì)里茄袖,可維護(hù)性復(fù)用是以設(shè)計(jì)原則和設(shè)計(jì)模式為基礎(chǔ)的操软。
對(duì)可維護(hù)性的支持
首先,適當(dāng)?shù)靥岣呦到y(tǒng)的可復(fù)用性宪祥,可以提高系統(tǒng)的可擴(kuò)展性聂薪。允許一個(gè)具有同樣接口新類代替舊的類,是對(duì)抽象接口的復(fù)用蝗羊〔匕模客戶端依賴于一個(gè)抽象的接口,而不是一個(gè)具體的實(shí)現(xiàn)類耀找,使得這個(gè)具體的類可以被其他的類取代翔悠,而不需要修改客戶端的代碼。
系統(tǒng)的可擴(kuò)展性是由開閉原則野芒、里氏代換原則蓄愁、依賴倒轉(zhuǎn)原則和合成復(fù)用原則實(shí)現(xiàn)的。
其次复罐,適當(dāng)?shù)靥岣呦到y(tǒng)的可復(fù)用性涝登,可以提高系統(tǒng)的靈活性雄家。在一個(gè)設(shè)計(jì)得當(dāng)?shù)南到y(tǒng)中效诅,每一個(gè)模塊都相對(duì)于其他模塊獨(dú)立存在,并且保持與其他模塊盡可能少的通信趟济。這樣一來乱投,在其中一個(gè)模塊的代碼發(fā)生修改的時(shí)候,這個(gè)修改的壓力不會(huì)傳遞到其他模塊顷编。
系統(tǒng)的靈活性是有開閉原則戚炫、迪米特法則、接口隔離原則保證的媳纬。
最后双肤,適當(dāng)?shù)靥岣呦到y(tǒng)的可復(fù)用性施掏,可以提高系統(tǒng)的可插入性,在一個(gè)符合“開-閉“原則的系統(tǒng)中茅糜,抽象層封裝了與商業(yè)邏輯有關(guān)的重要行為七芭,這些行為的具體實(shí)現(xiàn)由實(shí)現(xiàn)層給出。當(dāng)一個(gè)實(shí)現(xiàn)類再滿足需要蔑赘,需要以另一個(gè)實(shí)現(xiàn)類取代的時(shí)候狸驳,系統(tǒng)的設(shè)計(jì)就可以保證舊的類可被拔出,新類可以被插入缩赛。
可插入性有開閉原則耙箍、里氏代換原則、合成復(fù)用原則酥馍、依賴倒轉(zhuǎn)原則保證辩昆。