C++正交设计笔记2 简单设计
- 通過(guò)所有測(cè)試(需求)
- 盡可能消除重復(fù)(易重用,易修改性)
- 盡可能清晰表達(dá)(可理解性)
- 更少代碼元素(復(fù)雜性,無(wú)冗余)
- 重要程度排序
- 需求最大
- 第二 (易修改性 大于 可理解性?)
- 結(jié)論
原文 https://www.jianshu.com/p/0228d2dd90fe
Kent Beck給出了”簡(jiǎn)單設(shè)計(jì)”的明確標(biāo)尺 ,讓程序設(shè)計(jì)者判斷和遵守 :
- 通過(guò)所有測(cè)試(Passes its tests)
- 盡可能消除重復(fù) (Minimizes duplication)
- 盡可能清晰表達(dá) (Maximizes clarity)
- 更少代碼元素 (Has fewer elements)
- 以上四個(gè)原則的重要程度依次降低。
這組定義被稱做簡(jiǎn)單設(shè)計(jì)原則。
初看上去,這組原則平淡無(wú)奇,似乎是一組耳熟能詳?shù)脑瓌t的羅列。但只要細(xì)細(xì)品味,就會(huì)發(fā)現(xiàn)其精妙絕倫之處。
通過(guò)所有測(cè)試(需求)
直觀的看,這句話貌似在講測(cè)試:一個(gè)項(xiàng)目只有具備完善的自動(dòng)化測(cè)試,才算在做簡(jiǎn)單設(shè)計(jì)。但事實(shí)上并非如此。這里提到的測(cè)試,真正的意思是客戶驗(yàn)收。如果你的項(xiàng)目通過(guò)了客戶的所有驗(yàn)收條件(Acceptance Criteria),那就說(shuō)明你們已經(jīng)完成與客戶約定的全部需求。至于驗(yàn)收方式是靠人工還是靠自動(dòng)化測(cè)試則無(wú)關(guān)緊要。
所以,這句話強(qiáng)調(diào)的是對(duì)外部需求——包括功能性需求和非功能性需求——正確的完成。
盡可能消除重復(fù)(易重用,易修改性)
重復(fù),意味著低內(nèi)聚,高耦合。而消除重復(fù)的過(guò)程,也就意味著是讓軟件走向高內(nèi)聚,低耦合,達(dá)到良好正交性的過(guò)程。重復(fù)導(dǎo)致耦合度提高進(jìn)而導(dǎo)致難以修改(一個(gè)邏輯的改變就導(dǎo)致所有重復(fù)代碼都要修改) 識(shí)別和消除重復(fù),對(duì)于增強(qiáng)軟件應(yīng)對(duì)變化能力的重要程度,怎么強(qiáng)調(diào)都不為過(guò)。關(guān)于這一點(diǎn),我會(huì)另文說(shuō)明,這里就不再贅述。
不過(guò),并不是所有的重復(fù)都可以消除:比如,C++一個(gè)源文件里對(duì)外部公開(kāi)的類,其每個(gè)public方法原型,除了在源文件里定義時(shí),需要聲明一次,還需要在頭文件里再次聲明。這樣的重復(fù),是語(yǔ)言機(jī)制的要求,無(wú)法消除。
因而,這條原則被描述為最小化重復(fù),而不是消除重復(fù)。
盡可能清晰表達(dá)(可理解性)
清晰性,指的是一個(gè)設(shè)計(jì)容易理解的程度。注意:這不僅僅是對(duì)整潔代碼(Clean Code)及聲明式設(shè)計(jì)(Declarative Design)的強(qiáng)調(diào)。關(guān)于這一點(diǎn),有著非常有趣的部分,我們?cè)陔S后的部分談到。
更少代碼元素(復(fù)雜性,無(wú)冗余)
這一條是點(diǎn)睛之筆,正是因?yàn)樗拇嬖?#xff0c;這組原則才被稱做簡(jiǎn)單設(shè)計(jì)原則,從而區(qū)別于其它設(shè)計(jì)原則。
在這里,常量,變量,函數(shù),類,包 …… 都屬于代碼元素。代碼元素的數(shù)量,通常反映了設(shè)計(jì)的復(fù)雜度。因而,這句話強(qiáng)調(diào)的是:盡可能降低復(fù)雜度,保持簡(jiǎn)單。
重要程度排序
這一句最容易讓人忽視,卻恰恰最為重要。如果第四條是點(diǎn)睛之筆,那么第五條就是將之前四條貫穿起來(lái)的那條龍。正是這一句,讓你知道當(dāng)以上四條發(fā)生沖突時(shí),應(yīng)該如何取舍。(不能不做也不能過(guò)度做,而是要?jiǎng)倓偤?
對(duì)于第一條,它強(qiáng)調(diào):簡(jiǎn)單固然好,但你不能為了簡(jiǎn)單,而不去實(shí)現(xiàn)和客戶約定好的需求。(當(dāng)然,如果需求不合理,你應(yīng)該在前期通過(guò)和客戶協(xié)商拒絕,或修改。但那是關(guān)于需求管理這個(gè)話題有關(guān)的故事,感興趣者可以去查閱相關(guān)文章和書籍)。(反向價(jià)值: 你不應(yīng)該去實(shí)現(xiàn)一個(gè)客戶還不需要的需求,因?yàn)槟菚?huì)增加系統(tǒng)的復(fù)雜度。)
而對(duì)于第二條,比如,我們現(xiàn)在有兩個(gè)類:它們之間有一部分重復(fù)代碼。為了消除掉這個(gè)重復(fù),我們將重復(fù)代碼提取到一個(gè)新的類里。于是兩個(gè)類變?yōu)槿齻€(gè)類,增加了一個(gè)新的代碼元素。這當(dāng)然讓設(shè)計(jì)變得更復(fù)雜了。但這種復(fù)雜度產(chǎn)生了更重要的價(jià)值(讓軟件更具備正交性,從而讓軟件更易于修改,和重用),所以,不能為了保持簡(jiǎn)單,而不去消除這個(gè)重復(fù)。 (反向價(jià)值: 你不應(yīng)該為還沒(méi)有出現(xiàn)的重復(fù),或者為尚未出現(xiàn)的變化方向,去增加任何額外的復(fù)雜度。比如建立一個(gè)抽象接口,卻只有一個(gè)對(duì)應(yīng)的實(shí)現(xiàn).)
對(duì)于第三條也是如此,比如下面這句代碼中有一個(gè)magic number:a = 1000; 為了讓這段代碼更容易理解,我們將代碼修改為:
const int MAX_NUM_OF_CONNECTIONS = 1000;
a = MAX_NUM_OF_CONNECTIONS;
從而增加了一個(gè)新的代碼元素。因而也稍微增加了設(shè)計(jì)的復(fù)雜度。但由于這個(gè)新的代碼元素也產(chǎn)生了相對(duì)于簡(jiǎn)單更重要的價(jià)值,在簡(jiǎn)單和表達(dá)力之間,我們應(yīng)該選擇后者。不能為了保持簡(jiǎn)單,而丟失掉表達(dá)力.我們已經(jīng)知道,第四條,是簡(jiǎn)單設(shè)計(jì)的精髓,但是,它在前四條原則卻最不重要。 而第四條對(duì)于前兩條的約束,就是我們耳熟能祥的YAGNI(You Aren’t Gonna Need It)。它強(qiáng)調(diào),我們要著眼當(dāng)下,不去為自己猜想出的未來(lái)可能性去增加系統(tǒng)的復(fù)雜度。
總之,當(dāng)你看到一個(gè)代碼元素,沒(méi)有產(chǎn)生之前三條中的任何一條價(jià)值(滿足需求? 消除重復(fù)(耦合)? 清晰表達(dá)?),那么它就應(yīng)該被刪除掉。而這正是簡(jiǎn)單設(shè)計(jì)能夠簡(jiǎn)單的原因。
需求最大
拋開(kāi)第四條,單看前三條,它們之前的重要程度也是依次降低的。比如,
- 你不應(yīng)該因?yàn)榕庐a(chǎn)生很難消除、或干脆消除不掉的重復(fù)而放棄一個(gè)對(duì)客戶有價(jià)值的需求。換句話說(shuō),哪怕一個(gè)需求會(huì)導(dǎo)致重復(fù)代碼,你也要去實(shí)現(xiàn)它。
- 同樣的,如果一個(gè)需求,會(huì)導(dǎo)致你的設(shè)計(jì)更加晦澀,你卻不應(yīng)該因?yàn)樗鼡p害了清晰性、可理解性而拒絕它。
對(duì)于這兩點(diǎn),絕大多數(shù)人都沒(méi)有太多爭(zhēng)議。(也有一派認(rèn)為,不應(yīng)該讓需求破壞設(shè)計(jì)的優(yōu)雅,當(dāng)兩者發(fā)生沖突時(shí),選擇優(yōu)雅)。
第二 (易修改性 大于 可理解性?)
我們經(jīng)常能夠聽(tīng)到一種爭(zhēng)議:一些人認(rèn)為,放在一起的長(zhǎng)篇累牘的大塊流程代碼,反而更容易理解。因?yàn)橄貜?fù)而導(dǎo)致的單一職責(zé),會(huì)將一大段代碼分布到不同的類或者模塊,為了理解它,就不得不在類或者模塊間跳來(lái)跳去,反而不容理解了。
另外一部分人并不認(rèn)同這種看法。他們認(rèn)為,由于模塊或類的單一職責(zé)性,其每塊邏輯都更加簡(jiǎn)單清晰,然后在另外一個(gè)層面再去看它們之間的交互,就可以很快理解整個(gè)邏輯。 這比大坨的面條式代碼更容易理解。而對(duì)于SLAP(Single Level of Abstraction Priciple)的遵守,會(huì)更進(jìn)一步的增加可理解性。
由于可理解性屬于更加個(gè)人、更加主觀的事情,因而究竟哪種方式更容易理解,可能永遠(yuǎn)也不會(huì)有統(tǒng)一的答案。
而簡(jiǎn)單設(shè)計(jì)原則通過(guò)第二條和第三條之間的排序,給出了清晰的決策依據(jù):由于消除重復(fù),把一大塊代碼分隔到了不同的地方,即便團(tuán)隊(duì)認(rèn)為這確實(shí)損害了可理解性,但由于重復(fù)所導(dǎo)致的惡果更加嚴(yán)重,因而優(yōu)先選擇消除重復(fù)。
另外,關(guān)于簡(jiǎn)單設(shè)計(jì)原則,社區(qū)內(nèi)有多個(gè)版本,用詞不同,但意思大致相同。關(guān)鍵的差別是第二條和第三條的順序:即消除重復(fù)和提升表達(dá)力哪個(gè)更重要。有一些人認(rèn)為表達(dá)力比消除重復(fù)重要,因而把提升表達(dá)力放在第二條。但更多人認(rèn)同的是本文之前的版本。
對(duì)于這一點(diǎn),我個(gè)人的觀點(diǎn)是,越是主觀的東西,就越不具備可驗(yàn)證性或科學(xué)性,因而對(duì)于工程技術(shù)而言,重要程度就越低。
另外,回歸到具體項(xiàng)目里,為了避免爭(zhēng)議,在不違背前兩點(diǎn)原則的情況下,團(tuán)隊(duì)可以根據(jù)大多數(shù)人的審美和認(rèn)知,決定怎樣的設(shè)計(jì)才更具備可理解性。事實(shí)上,在重復(fù)已經(jīng)被消除殆盡的情況下,對(duì)于可理解性問(wèn)題,無(wú)論怎樣選擇,影響都是局部的。
因而,對(duì)于這個(gè)問(wèn)題,團(tuán)隊(duì)覺(jué)得舒服最重要。
結(jié)論
簡(jiǎn)單設(shè)計(jì)原則,通過(guò)對(duì)需求、易修改性、可理解性、復(fù)雜度,這四個(gè)在設(shè)計(jì)決策中最關(guān)鍵的因素給出了排序,讓簡(jiǎn)單設(shè)計(jì)不再一個(gè)語(yǔ)義模糊的口號(hào),而是對(duì)設(shè)計(jì)決策給出了清晰的guideline。
根據(jù)筆者經(jīng)驗(yàn),深入理解、并在項(xiàng)目中反復(fù)品味和應(yīng)用它,可以避免掉很多不必要的爭(zhēng)議,也會(huì)對(duì)設(shè)計(jì)質(zhì)量產(chǎn)生非常顯著的幫助。
作者:袁英杰
鏈接:https://www.jianshu.com/p/0228d2dd90fe
來(lái)源:簡(jiǎn)書
著作權(quán)歸作者所有。商業(yè)轉(zhuǎn)載請(qǐng)聯(lián)系作者獲得授權(quán),非商業(yè)轉(zhuǎn)載請(qǐng)注明出處。
總結(jié)
以上是生活随笔為你收集整理的C++正交设计笔记2 简单设计的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 【20210109期 AI周报】该重视
- 下一篇: secure boot具体关闭教程