重新認(rèn)識開閉原則(OCP)
什么是開閉原則(OCP)?
軟件實體(模塊,類,函數(shù)等)應(yīng)該對于功能擴展是開放的,但對于修改是封閉的。
那怎么改動代碼才算是擴展,怎么改動代碼才算是修改 ?
其實這要看情況的,開閉原則可以應(yīng)用在不同粒度的代碼中,可以是模塊,也可以是類,還可以是方法及其屬性。同樣一個代碼改動,在粗代碼粒度下,被認(rèn)定為修改,在細(xì)代碼粒度下,又可以被認(rèn)定為擴展。
可以簡單的這么理解,添加或修改業(yè)務(wù)功能,就添加或修改對應(yīng)的模塊(類或函數(shù)),但不會影響其余模塊的單元測試,不影響其他模塊的正常運行,這就屬于擴展,反之就是修改,也并不是說完全杜絕修改,而是以最小的修改代碼的代價來完成新功能的開發(fā)。
而且,我們要認(rèn)識到,添加一個新功能,不可能任何模塊、類、方法的代碼都不修改,這個是做不到的。類需要創(chuàng)建、組裝、并且做一些初始化操作,才能構(gòu)建成可運行的的程序,這部分代碼的修改是在所難免的。我們要做的是盡量讓修改操作更集中、更少、更上層,盡量讓最核心、最復(fù)雜的那部分邏輯代碼滿足開閉原則。
如何做到對擴展開放,對修改關(guān)閉?
一個軟件產(chǎn)品只要在其生命周期內(nèi),都會不斷發(fā)生變化。變化是一個事實,所以我們需要讓軟件去適應(yīng)變化。我們應(yīng)該在設(shè)計時盡量適應(yīng)這些變化,以提高項目的穩(wěn)定性和靈活性,真正實現(xiàn) “擁抱變化”。開閉原則告訴我們,應(yīng)盡量通過擴展軟件實體的行為來應(yīng)對變化,滿足新的需求,而不是通過修改現(xiàn)有代碼來完成變化,它是為軟件實體的未來事件而制定的對現(xiàn)行開發(fā)設(shè)計進行約束的一個原則。
與其修改模塊的業(yè)務(wù),不如實現(xiàn)一個新業(yè)務(wù)。只要業(yè)務(wù)的分解一直被正確執(zhí)行的話,實現(xiàn)一個新的業(yè)務(wù)模塊來完成新的業(yè)務(wù)范疇,是一件極其輕松的事情。從這個角度來說,開閉原則鼓勵寫 “只讀” 的業(yè)務(wù)模塊,一經(jīng)設(shè)計就不可修改,如果要修改業(yè)務(wù)就直接廢棄它,轉(zhuǎn)而實現(xiàn)新的業(yè)務(wù)模塊。
舉幾個開閉原則的例子:
1、馮·諾依曼體系的中央處理器(CPU)的設(shè)計完美體現(xiàn)了 “開閉原則” 的架構(gòu)思想。它表現(xiàn)在:指令是穩(wěn)定的,但指令序列是變化的,只有這樣計算機才能夠?qū)崿F(xiàn) “解決一切可以用 ‘計算’ 來解決的問題” 這個目標(biāo)。計算是穩(wěn)定的,但數(shù)據(jù)交換是多變的,只有這樣才能夠讓計算機不必修改基礎(chǔ)架構(gòu)卻可以適應(yīng)不斷發(fā)展變化的交互技術(shù)革命。
2、插件機制,比如 VSCode、PyCharm、Chrome 瀏覽器,都可以添加插件的形式添加新的功能。
3、活字印刷術(shù),也是開閉原則應(yīng)用的一個例子。字是穩(wěn)定的,字的排序是變化的。
從需求分析角度來說,關(guān)鍵要抓住需求的穩(wěn)定點和變化點。需求的穩(wěn)定點,往往是系統(tǒng)的核心價值點;而需求的變化點,則往往需要相應(yīng)去做開放性設(shè)計。
在代碼設(shè)計角度來說,我們要多花點時間往前多思考一下,這段代碼未來可能有哪些需求變更、如何設(shè)計代碼結(jié)構(gòu),事先留好擴展點,以便在未來需求變更的時候,不需要改動代碼整體結(jié)構(gòu)、做到最小代碼改動的情況下,新的代碼能夠很靈活地插入到擴展點上,做到“對擴展開放、對修改關(guān)閉”。還有,在識別出代碼可變部分和不可變部分之后,我們要將可變部分封裝起來,隔離變化,提供抽象化的不可變接口,給上層系統(tǒng)使用。當(dāng)具體的實現(xiàn)發(fā)生變化的時候,我們只需要基于相同的抽象接口,擴展一個新的實現(xiàn),替換掉老的實現(xiàn)即可,上游系統(tǒng)的代碼幾乎不需要修改。
最后
開閉原則對擴展開放是為了應(yīng)對變化(需求),對修改關(guān)閉是為了保證已有代碼的穩(wěn)定性,最終結(jié)果是為了讓系統(tǒng)更有彈性。不過擴展性越好的代碼,可讀性會有所下降,也不可對簡單的需求進行過度設(shè)計從而犧牲了可讀性,要做好權(quán)衡,其實編程就是在權(quán)衡的藝術(shù),為什么用這個不用那個,為什么這樣設(shè)計而不是那樣設(shè)計。
以上是我學(xué)習(xí)王爭《設(shè)計模式之美》的學(xué)習(xí)筆記,每次看都有新的收獲,??闯P?,強烈推薦我的程序員朋友們加入學(xué)習(xí):
掃碼購買加好友「somenzz」備注「入群」,一起學(xué)習(xí)交流哈
