設(shè)計或者是一種解謎睡蟋,世界就在眼前踏幻,然而它卻是未知的,神秘的戳杀,我們試圖通過分析建立一個普適的模型该面,去解構(gòu)這個已經(jīng)存在的世界。這個謎題如此引人入勝信卡,它沒有標(biāo)準(zhǔn)答案隔缀,卻又真實的呈現(xiàn)在我們面前。
設(shè)計就好像是研究電信號頻譜結(jié)構(gòu)的頻譜分析儀傍菇,通過掃描和偵測信號猾瘸,再利用我們已經(jīng)充分證明的算法例如快速傅里葉變換(FFT)去獲得頻譜分布圖,然后工程師就可以借助經(jīng)驗與頻譜知識甄別信號特征桥嗤,從而判斷電子設(shè)備是否出現(xiàn)異常须妻。這種設(shè)計方式,我稱之為“分析式設(shè)計”泛领。
分析式設(shè)計##
分析式設(shè)計常常起源于對研究領(lǐng)域的假想與猜測荒吏,進而對海量的信息進行篩選和甄別,提煉出對解決該問題有幫助的信息渊鞋,再利用設(shè)計經(jīng)驗去推導(dǎo)合理的設(shè)計模型绰更。人類對于宇宙的探索,就是這樣的分析式設(shè)計锡宋。在史蒂芬.霍金的著作《時間簡史》中談到了古希臘哲學(xué)家亞里士多德對地球形狀的論證儡湾。
早在公元前340年,希臘哲學(xué)家亞里士多德在他的《論天》一書中执俩,就能夠?qū)τ诘厍蚴且粋€圓球而不是一個平板這個信念提出兩個有力的論證徐钠。第一,他意識到役首,月食是由于地球運行到太陽與月亮之間引起的尝丐。地球在月亮上的影子總是圓的,這只有在地球本身為球形的前提下才成立衡奥。如果地球是一塊平坦的圓盤爹袁,除非月食總是發(fā)生在太陽正好位于這個圓盤中心的正下方的時刻,否則地球的影子就會被拉長而成為橢圓形矮固。第二失息,希臘人從旅行中知道,在南方觀測北極星,比在較北地區(qū)盹兢,北極星在天空中顯得較低邻梆。
亞里士多德采用的兩個論證就是他利用智慧與知識篩選出來的有用信息,這有利于他建立“地球是一個圓球”的天體模型蛤迎。
這種分析式設(shè)計常常體現(xiàn)為一種漸進的設(shè)計方式确虱,原因在于我們總是以局部去推測整體含友,就難免陷入一葉障目的困境替裆。從亞里士多德到托勒密的設(shè)想,再到哥白尼的日心說寸谜,開普勒的天體模型读规,牛頓的萬有引力定律恰起,直至愛因斯坦的相對論,整體天體模型都在不斷的批謬中披荊斬棘把鉴,艱難發(fā)展,并逐漸趨向事實的真理儿咱。然而無論正繆庭砍,這些哲學(xué)與思想先驅(qū)們都是在對靜默存在的宇宙進行的一種分析,通過把握某種內(nèi)在的如脈搏跳動的規(guī)律混埠,設(shè)計為嚴(yán)謹(jǐn)?shù)哪P汀?/p>
在軟件領(lǐng)域怠缸,諸多問題已經(jīng)現(xiàn)實存在,但這種存在如沙礫藏身于溪流钳宪,奇石隱匿于幽谷揭北,沒有敏銳的洞察力,很難明察問題的真相吏颖。設(shè)計者需要對繁雜紛亂的需求進行梳理和甄別搔体,分析軟件目標(biāo)或愿景,逐步建立模型半醉,并通過原型或真實實現(xiàn)去驗證其模型疚俱,根據(jù)反饋的結(jié)果進行改進、打磨缩多,或增或刪呆奕,以求最簡的方式滿足需求,從而獲得良好的解決方案去指導(dǎo)具體的實現(xiàn)瞧壮。
例如在大數(shù)據(jù)處理領(lǐng)域登馒,我們面臨的問題是數(shù)據(jù)的海量與性能之間的博弈,非結(jié)構(gòu)性關(guān)系與分析結(jié)果之間隱藏的線索咆槽,還有諸如因果推論陈轿、分布式存儲、實時處理等多個問題雜糅在一起,就構(gòu)筑了一個復(fù)雜的外部世界麦射。我們需要去深入探索數(shù)據(jù)分析的問題域蛾娶,挖掘數(shù)據(jù)與數(shù)據(jù)之間的隱含關(guān)系,架構(gòu)或重現(xiàn)各種復(fù)雜多變的應(yīng)用場景潜秋,小心求證蛔琅,實驗探索,才能分析獲得以當(dāng)前場景而論為最優(yōu)的解決方案峻呛,得出設(shè)計模型罗售。
分析還可以逐步添加約束的方式來推導(dǎo)設(shè)計。Roy Thomas Fielding博士在推導(dǎo)REST架構(gòu)風(fēng)格時钩述,正是采用了這種方式寨躁。在Fielding的論文《架構(gòu)風(fēng)格與基于網(wǎng)絡(luò)的軟件架構(gòu)設(shè)計》,他寫道:
Web架構(gòu)背后的設(shè)計基本原理牙勘,能夠被描述為由一組應(yīng)用于架構(gòu)中元素之上的約束組成的架構(gòu)風(fēng)格职恳。當(dāng)將每個約束添加到進化中的風(fēng)格時,會產(chǎn)生一些影響方面。通過檢查這些影響放钦,我們就能夠識別出Web的約束所導(dǎo)致的屬性。然后就能夠應(yīng)用額外的約束來形成一種新的架構(gòu)風(fēng)格恭金,這種風(fēng)格能夠更好地反映出現(xiàn)代Web架構(gòu)所期待的屬性操禀。
Fielding從一個沒有任何約束的“空”風(fēng)格開始,通過逐步施加分離關(guān)注點蔚叨、通信無狀態(tài)床蜘、緩存、統(tǒng)一接口蔑水、分層邢锯、定制化等約束,整個架構(gòu)就像洞穴中的原上猿逐步進化為人類一般搀别,從“空”風(fēng)格的混沌架構(gòu)演化為最終的REST風(fēng)格丹擎。相較于直接設(shè)計一個嚴(yán)謹(jǐn)?shù)哪P停@種逐步添加約束的方式更加自然流暢歇父,更符合人類的知識積累模式蒂培。設(shè)計軟件時,我們可以通過識別系統(tǒng)的風(fēng)險榜苫,驅(qū)動我們?nèi)ナ┘蛹s束护戳,然后漸進地形成針對性的解決方案,以降低風(fēng)險垂睬。這即為George Fairbanks提出的風(fēng)險驅(qū)動模型媳荒。
創(chuàng)造式設(shè)計##
設(shè)計或者是一種創(chuàng)造抗悍,無中生有地將一個事物美輪美奐地創(chuàng)造出來。此時钳枕,設(shè)計者就像是造物主缴渊,他要設(shè)計的軟件就是一個獨立的星球,可以按照他認(rèn)為最好的方式去設(shè)計星球的風(fēng)景鱼炒,安排萬物遵循生長的秩序衔沼。即使是從無到有創(chuàng)造出一顆星球,依舊可以從亙古存在的遙遠星球獲得靈感昔瞧,作為參考物或原型幫助新的設(shè)計指蚁。我將這種設(shè)計方式稱為“創(chuàng)造式設(shè)計”,它考察的是設(shè)計者的經(jīng)驗硬爆、巧思與創(chuàng)意欣舵。
作家在寫作時擎鸠,整個構(gòu)思的過程就是一種創(chuàng)造式設(shè)計缀磕。偶然經(jīng)歷的一件事情可能會在內(nèi)心觸動作家創(chuàng)作的神經(jīng),以此為靈感作為創(chuàng)造的契機劣光,然后逐漸豐富袜蚕,按照作品人物的性格、職業(yè)以及身處的環(huán)境開始推動情節(jié)的發(fā)展绢涡。這種創(chuàng)造未必是“硬”推出來的牲剃,相反,它可能極為自然流暢雄可,如蘇東坡云:“大略如行云流水凿傅,初無定質(zhì),但常行于所當(dāng)行数苫,常止于所不可不止聪舒,文理自然,姿態(tài)橫生虐急∠洳校”
創(chuàng)造式設(shè)計雖為無中生有,但并非徹底的無止吁,可能是一種發(fā)現(xiàn)被辑。斯蒂芬.金在接受《紐約客》的一次采訪時,說道:
我對采訪我的馬克.辛格說敬惦,我相信故事猶如埋在地下的化石盼理,是被人們發(fā)掘出來的,他說他不相信我的話俄删。我回答說這沒關(guān)系宏怔,只要他相信我這么相信就夠了勾哩。我確實這么認(rèn)為。故事不是紀(jì)念T恤衫或是掌上游戲機举哟,它們是遺跡思劳,屬于一個未被發(fā)現(xiàn)但已經(jīng)存在的世界。作家的工作就是利用他/她工具箱里的工具把每個故事盡量完好無損地從地里挖出來妨猩。有時候你發(fā)掘的化石很小潜叛,可能只是顆貝殼。有時候很巨大壶硅,是頭骨架龐大牙齒凌厲的霸王龍威兜。不論哪種,短篇小說或是一千多頁的小說巨著庐椒,挖掘的技術(shù)大致上相同椒舵。
創(chuàng)造式的設(shè)計在一開始可能并不明確它所要創(chuàng)造的目標(biāo),而是像斯蒂芬.金的方式如發(fā)掘遺跡一般慢慢將泥土剔除约谈,逐漸顯現(xiàn)笔宿。這會讓人產(chǎn)生不經(jīng)意創(chuàng)造出來的感覺。Spring之父Rod Johnson從一開始就不是要創(chuàng)造一個框架棱诱,他是在J2EE項目中通過對EJB的反思逐步演化出來的Spring泼橘。這種創(chuàng)造其實是一種“循證式創(chuàng)造”,它遵循的是應(yīng)用場景迈勋,而非不切實際的空想炬灭。
2004年,當(dāng)哥本哈根商學(xué)院的大三學(xué)生David Heinemeier Hansson(人稱DHH)接到37signals公司電話時靡菇,不會有人想到這會是Ruby On Rails誕生的導(dǎo)火線重归。顯然RoR并非DHH有意創(chuàng)造出來的,它只是為了打造Basecamp產(chǎn)品而自然而然衍生出來的框架厦凤。就連DHH創(chuàng)造用的工具也經(jīng)歷了變更鼻吮,從最初選擇的PHP,轉(zhuǎn)向了更靈活泳唠、更簡單的Ruby狈网。正是Ruby對元數(shù)據(jù)編程的超強支持,Rails才能做到如此的精簡笨腥。
創(chuàng)造式設(shè)計出來的產(chǎn)品常常凸顯了設(shè)計者的意圖與態(tài)度拓哺,就仿佛上帝的意志。這種態(tài)度徹頭徹尾地體現(xiàn)了設(shè)計者的善惡論脖母,甚至可以說是一種信仰士鸥。如果將設(shè)計者視為產(chǎn)品的上帝,則這種設(shè)計意圖與態(tài)度就是一種自然法谆级。正如中世紀(jì)的神學(xué)家阿奎那所說:“自然法已不再是最高的法烤礁,而且巧妙地將自然法與上帝的永恒法結(jié)合在一起讼积,認(rèn)為我們賴以辨別善惡的自然理性之光,即自然法脚仔,不外乎是神的榮光在我們身上留下的痕跡”勤众。
在編程語言的設(shè)計中,尤其體現(xiàn)了這種意志與法規(guī)的結(jié)合鲤脏。Go語言的設(shè)計者就對在面向?qū)ο箢I(lǐng)域中繼承的濫用表達了足夠的憂慮和擔(dān)心们颜。Rob Pike在《Go在谷歌:以軟件工程為目的的語言設(shè)計》提及Go語言設(shè)計者對類型結(jié)構(gòu)的考慮:
類型層次結(jié)構(gòu)這種模型會促成早期的過度設(shè)計,因為程序員要盡力對軟件可能需要的各種可能的用法進行預(yù)測猎醇,不斷地為了避免掛一漏萬窥突,不斷的增加類型和抽象的層次。這種做法有點顛倒了硫嘶,系統(tǒng)各個部分之間交互的方式本應(yīng)該隨著系統(tǒng)的發(fā)展而做出相應(yīng)的改變阻问,而不應(yīng)該在一開始就固定下來。
因而沦疾,在Go語言中并未提供繼承的特性称近,而是利用接口(包括對Duke Type的支持)來支持OO中的多態(tài),而以組合來保證邏輯的復(fù)用曹鸠。
設(shè)計態(tài)度甚至體現(xiàn)為設(shè)計者對所要創(chuàng)造的世界所持有的世界觀煌茬。面向?qū)ο笈c函數(shù)編程陣營就是兩種截然不同的世界觀。面向?qū)ο笫敲~的世界彻桃,而函數(shù)式的思想則以動詞為準(zhǔn),從而將函數(shù)提升為一等公民晾蜘。觀察世界的角度不同邻眷,設(shè)計的途徑也就不同。OO的模式與原則在函數(shù)式語言中剔交,幾乎都可以用函數(shù)來表示肆饶。Scott Wlaschin在演講Functional Design Patterns中比較了這兩種不同的編程范式:
設(shè)計的演進##
無論是分析式設(shè)計,還是創(chuàng)造式設(shè)計岖常,目的都是為了要解決問題驯镊,即針對問題域(Problem Domain)尋求解決方案(Solution)。問題域可大可小竭鞍,設(shè)計可復(fù)雜可簡單板惑。設(shè)計者往往難以一蹴而就獲得最佳的解決方案,而需要在不斷的演化中改進設(shè)計偎快。2004年冯乘,Martin Fowler撰寫文章《Is Design Dead》,將設(shè)計劃分為計劃式設(shè)計和演進式設(shè)計(Planned and Evolutionary Design)晒夹。我認(rèn)為裆馒,這二種設(shè)計方式都需要遵循設(shè)計的基本原則姊氓,區(qū)別只在于設(shè)計的目標(biāo)。演進的設(shè)計提倡滿足客戶現(xiàn)有的需求喷好;而計劃的設(shè)計則需要考慮未來的功能擴展翔横。演進的設(shè)計推崇盡快地實現(xiàn),追求快速確定解決方案梗搅,快速編碼以及快速實現(xiàn)棕孙;而計劃的設(shè)計則需要考慮計劃的周密性,架構(gòu)的完整性并保證開發(fā)過程的有條不紊些膨。
Neal Ford提出的Emergent Design實則就是一種演進式設(shè)計蟀俊,在他撰寫的系列文章中,開篇就提出:“演化架構(gòu)(evolutionary architecture)和緊急設(shè)計(emergent design)都是將重要的決策推遲到最后責(zé)任時刻(Last Responsible Moment)的敏捷技術(shù)”订雾。他建議肢预,通過工具獲得質(zhì)量指標(biāo),并利用測試驅(qū)動設(shè)計追求簡單設(shè)計洼哎,進而對設(shè)計進行重構(gòu)烫映,在重構(gòu)過程中積累慣用模式來指導(dǎo)重構(gòu)的方向,從而完成架構(gòu)的演進噩峦。
George Fairbanks認(rèn)為除了計劃式設(shè)計和演進式設(shè)計之外锭沟,還包含第三種設(shè)計方式,稱之為最小計劃式設(shè)計(Minimal planned design)识补,或可稱為是中庸之道的選擇族淮。書中認(rèn)為,“演進式設(shè)計需要與一些敏捷實踐配合凭涂,包括重構(gòu)祝辣、測試驅(qū)動設(shè)計與持續(xù)集成。而計劃式設(shè)計背后隱藏的思想是在構(gòu)造開始之前切油,制訂的計劃可以設(shè)計出很好的細節(jié)蝙斜。”至于最小計劃式設(shè)計澎胡,則介乎于演進式設(shè)計與計劃式設(shè)計之間孕荠。支持這種設(shè)計的人認(rèn)為:如果完全采取演進式設(shè)計,可能會使得設(shè)計走向死胡同攻谁;而計劃式設(shè)計又非常難稚伍,因為事先對系統(tǒng)并沒有全面的了解,可能導(dǎo)致設(shè)計錯誤巢株。在2002年Bill Venners對Martin Fowler的采訪中槐瑞,Martin Fowler認(rèn)為,最合理的分配是20%的計劃式設(shè)計阁苞,80%的演進式設(shè)計困檩。George認(rèn)為需要權(quán)衡計劃式與演進式設(shè)計祠挫。一種做法是在項目初期進行計劃式設(shè)計,確保架構(gòu)能夠處理最大的風(fēng)險悼沿。之后等舔,就可以通過局部的設(shè)計來應(yīng)對需求的變化,或者采用演進式設(shè)計糟趾,通過推行重構(gòu)慌植、測試驅(qū)動設(shè)計與持續(xù)集成對架構(gòu)進行演化。
整體而言义郑,這三種方式的設(shè)計各有優(yōu)劣蝶柿,我們應(yīng)根據(jù)具體的場景,具體的項目非驮,具體的團隊進行針對性地分析交汤。應(yīng)該把握“因地制宜”的原則,認(rèn)識到不同的項目需要不同的設(shè)計方式劫笙。對于不同的開發(fā)團隊芙扎,做出的選擇也會不同。例如填大,如果開發(fā)團隊精于重構(gòu)戒洼、測試驅(qū)動設(shè)計,并能很好地實施持續(xù)集成允华,就可以考慮采用演進式設(shè)計或最小計劃設(shè)計圈浇。
顯然,無論采取何種設(shè)計方式例获,我們都應(yīng)該追求恰如其分汉额,而非臻至完美。設(shè)計之美需要以演進的方式逐漸打磨而成榨汤,它需要保持簡單,避免重復(fù)怎茫,擁抱變化收壕。故而要保證設(shè)計的清晰意圖表達,干脆利落轨蛤,善于留白來保證虛實相間蜜宪,簡約平衡,尋求整體的美感祥山。