簡(jiǎn)單設(shè)計(jì)

Everything should be made as simple as possible, but not simpler.
-- Albert Einstein

我們一直在談簡(jiǎn)單設(shè)計(jì)扳肛,但究竟什么是簡(jiǎn)單設(shè)計(jì)此改?更具體的說(shuō),對(duì)于同一個(gè)問(wèn)題狼忱,設(shè)計(jì)決策A和B,究竟哪一個(gè)更符合簡(jiǎn)單設(shè)計(jì)的要求他巨?

對(duì)于這類(lèi)問(wèn)題澡匪,如果沒(méi)有一個(gè)明確的標(biāo)尺,那么"簡(jiǎn)單設(shè)計(jì)"就不免會(huì)成為一句無(wú)法評(píng)判的空洞口號(hào)拆融,讓程序設(shè)計(jì)者無(wú)從判斷和遵守蠢琳。

對(duì)此啊终,Kent Beck給出了清晰的答案:

  1. 通過(guò)所有測(cè)試(Passes its tests)
  2. 盡可能消除重復(fù) (Minimizes duplication)
  3. 盡可能清晰表達(dá) (Maximizes clarity)
  4. 更少代碼元素 (Has fewer elements)
  5. 以上四個(gè)原則的重要程度依次降低。

這組定義被稱(chēng)做簡(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ò)程。識(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)的類(lè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后的部分談到。

更少代碼元素

這一條是點(diǎn)睛之筆败徊,正是因?yàn)樗拇嬖谥愫簦@組原則才被稱(chēng)做簡(jiǎn)單設(shè)計(jì)原則,從而區(qū)別于其它設(shè)計(jì)原則皱蹦。

在這里,常量眷蜈,變量沪哺,函數(shù),類(lèi)酌儒,包 …… 都屬于代碼元素辜妓。代碼元素的數(shù)量,通常反映了設(shè)計(jì)的復(fù)雜度忌怎。因而籍滴,這句話強(qiáng)調(diào)的是:盡可能降低復(fù)雜度,保持簡(jiǎn)單榴啸。

重要程度排序

這一句最容易讓人忽視孽惰,卻恰恰最為重要。如果第四條是點(diǎn)睛之筆鸥印,那么第五條就是將之前四條貫穿起來(lái)的那條龍勋功。正是這一句,讓你知道當(dāng)以上四條發(fā)生沖突時(shí)库说,應(yīng)該如何取舍狂鞋。

我們已經(jīng)知道,第四條潜的,是簡(jiǎn)單設(shè)計(jì)的精髓骚揍,但是,它在前四條原則卻最不重要啰挪。

對(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)文章和書(shū)籍)卵牍。

而對(duì)于第二條果港,比如,我們現(xiàn)在有兩個(gè)類(lèi):它們之間有一部分重復(fù)代碼糊昙。為了消除掉這個(gè)重復(fù)辛掠,我們將重復(fù)代碼提取到一個(gè)新的類(lèi)里。于是兩個(gè)類(lèi)變?yōu)槿齻€(gè)類(lèi)释牺,增加了一個(gè)新的代碼元素萝衩。這當(dāng)然讓設(shè)計(jì)變得更復(fù)雜了。但這種復(fù)雜度產(chǎn)生了更重要的價(jià)值(讓軟件更具備正交性没咙,從而讓軟件更易于修改)猩谊,所以,不能為了保持簡(jiǎn)單祭刚,而不去消除這個(gè)重復(fù)牌捷。

對(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à)值

而簡(jiǎn)單設(shè)計(jì)的價(jià)值锯梁,也可以從相反的角度來(lái)看:如果新增的一條代碼元素即碗,不能產(chǎn)生上述三個(gè)價(jià)值,它就不應(yīng)該存在陌凳。

對(duì)于第一條剥懒,你不應(yīng)該去實(shí)現(xiàn)一個(gè)客戶還不需要的需求,因?yàn)槟菚?huì)增加系統(tǒng)的復(fù)雜度合敦。

對(duì)于第二條初橘,你不應(yīng)該為還沒(méi)有出現(xiàn)的重復(fù),或者為尚未出現(xiàn)的變化方向,去增加任何額外的復(fù)雜度保檐。比如建立一個(gè)抽象接口耕蝉,卻只有一個(gè)對(duì)應(yīng)的實(shí)現(xiàn)。

而第四條對(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à)值踢关,那么它就應(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)雅)介袜。

最具爭(zhēng)議話題的解決

我們經(jīng)常能夠聽(tīng)到一種爭(zhēng)議:一些人認(rèn)為甫何,放在一起的長(zhǎng)篇累牘的大塊流程代碼,反而更容易理解遇伞。因?yàn)橄貜?fù)而導(dǎo)致的單一職責(zé)辙喂,會(huì)將一大段代碼分布到不同的類(lèi)或者模塊,為了理解它,就不得不在類(lèi)或者模塊間跳來(lái)跳去巍耗,反而不容理解了秋麸。

另外一部分人并不認(rèn)同這種看法。他們認(rèn)為炬太,由于模塊或類(lèi)的單一職責(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)生非常顯著的幫助辞居。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末楷怒,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子瓦灶,更是在濱河造成了極大的恐慌率寡,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,126評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件倚搬,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡乾蛤,警方通過(guò)查閱死者的電腦和手機(jī)每界,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,254評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)家卖,“玉大人眨层,你說(shuō)我怎么就攤上這事∩系矗” “怎么了趴樱?”我有些...
    開(kāi)封第一講書(shū)人閱讀 152,445評(píng)論 0 341
  • 文/不壞的土叔 我叫張陵馒闷,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我叁征,道長(zhǎng)纳账,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 55,185評(píng)論 1 278
  • 正文 為了忘掉前任捺疼,我火速辦了婚禮疏虫,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘啤呼。我一直安慰自己卧秘,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,178評(píng)論 5 371
  • 文/花漫 我一把揭開(kāi)白布官扣。 她就那樣靜靜地躺著翅敌,像睡著了一般。 火紅的嫁衣襯著肌膚如雪惕蹄。 梳的紋絲不亂的頭發(fā)上蚯涮,一...
    開(kāi)封第一講書(shū)人閱讀 48,970評(píng)論 1 284
  • 那天,我揣著相機(jī)與錄音焊唬,去河邊找鬼恋昼。 笑死,一個(gè)胖子當(dāng)著我的面吹牛赶促,可吹牛的內(nèi)容都是我干的液肌。 我是一名探鬼主播,決...
    沈念sama閱讀 38,276評(píng)論 3 399
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼鸥滨,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼嗦哆!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起婿滓,我...
    開(kāi)封第一講書(shū)人閱讀 36,927評(píng)論 0 259
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤老速,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后凸主,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體橘券,經(jīng)...
    沈念sama閱讀 43,400評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,883評(píng)論 2 323
  • 正文 我和宋清朗相戀三年卿吐,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了旁舰。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 37,997評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡嗡官,死狀恐怖箭窜,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情衍腥,我是刑警寧澤磺樱,帶...
    沈念sama閱讀 33,646評(píng)論 4 322
  • 正文 年R本政府宣布纳猫,位于F島的核電站,受9級(jí)特大地震影響竹捉,放射性物質(zhì)發(fā)生泄漏芜辕。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,213評(píng)論 3 307
  • 文/蒙蒙 一活孩、第九天 我趴在偏房一處隱蔽的房頂上張望物遇。 院中可真熱鬧,春花似錦憾儒、人聲如沸询兴。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,204評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)诗舰。三九已至,卻和暖如春训裆,著一層夾襖步出監(jiān)牢的瞬間眶根,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,423評(píng)論 1 260
  • 我被黑心中介騙來(lái)泰國(guó)打工边琉, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留属百,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 45,423評(píng)論 2 352
  • 正文 我出身青樓变姨,卻偏偏與公主長(zhǎng)得像族扰,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子定欧,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,722評(píng)論 2 345

推薦閱讀更多精彩內(nèi)容

  • 博爾赫斯說(shuō):“寫(xiě)散文體的短文——寓言渔呵、神話、短故事——給了我某種神秘的滿足砍鸠。想起這些篇章扩氢,就仿佛想到硬幣:實(shí)在、結(jié)...
    _張逸_閱讀 2,353評(píng)論 0 2
  • Android 自定義View的各種姿勢(shì)1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 171,498評(píng)論 25 707
  • 或許在外人看來(lái)爷辱,有時(shí)候覺(jué)得讀心理學(xué)的都是變態(tài)录豺,又或者是算命的。 就像心理學(xué)專(zhuān)業(yè)孩子無(wú)法直面的一個(gè)永恒的問(wèn)題饭弓,每次聽(tīng)...
    野草一一閱讀 323評(píng)論 0 2
  • 晚飯后巩检,臻臻邀請(qǐng)我一起玩“吸氣”游戲。 何謂吸氣示启?原來(lái),愛(ài)吃番茄醬的他领舰,請(qǐng)爸爸買(mǎi)來(lái)了一罐夫嗓,160克的圓柱形瓶子迟螺,大...
    紫軒悅讀閱讀 284評(píng)論 0 3
  • [預(yù)定資料流程庫(kù)]-微博營(yíng)銷(xiāo)技巧 以下是總結(jié)出來(lái)的有效技巧 1、粉絲增長(zhǎng)吸收 一個(gè)微博的質(zhì)量舍咖,關(guān)鍵在于看這個(gè)微博人...
    北京大數(shù)據(jù)蘇煥之閱讀 440評(píng)論 0 4