或许我们做错了,但绝非一无是处
是的,過度設計的現(xiàn)象普遍存在。回到90年代中期,當我開始入行開發(fā)者行業(yè)時,我的目標就是成為一個架構(gòu)師。任何認真的開發(fā)者都不會在選定自己喜歡的設計模式之前就開始寫代碼。我們會在選好設計模式之后才開始思考怎樣將業(yè)務需求融合進去。是的,我們會先弄出架構(gòu),然后是宏設計(層)和域模型(包括UML圖表),接下來才思考業(yè)務需求和詳細的用例。沒錯,那個時代,用例真的不是什么大事。我們的基本流程和眾多可選流程中有一長串的用例。
90年代是開發(fā)者們?nèi)呵檎駣^的時期。70和80年代還在學術(shù)論文層面上的一些結(jié)構(gòu)化設計,以及互聯(lián)網(wǎng),最終都在90年代實現(xiàn)了。那個時期里,還出版了基本面向?qū)ο缶幊痰臅?#xff0c;至今在很多領(lǐng)域里還是新鮮的概念。
我依然記得我們撲在畫類、序列、組件、部署和很多其他圖表上的無數(shù)個月,我們總在嘗試想出未來某天我們將打造出的軟件的最佳設計。我們也建立了一些原型,因此我不能說在規(guī)劃階段我們沒有做任何的編程或試驗。當然,所有來自于原型的經(jīng)驗教訓最終都會反饋到我們的圖表中。
除了內(nèi)部設計,90年代還是分布式系統(tǒng)大爆炸的時期。我們有了CORBA(公共對象請求代理體系結(jié)構(gòu))和DCOM(分布式組件對象模型),有了客戶端/服務器(C/S)和多層級架構(gòu)。我們在使用數(shù)據(jù)庫作為應用程序間通信點上學到了單點故障。是的,我們在這上面栽過大跟頭。我們學會了怎樣創(chuàng)建“服務”——SOA(面向服務架構(gòu))概念迅速興起。我們學會了考慮可擴展性和安全性。很多政府和銀行以外的項目也變得非常巨大和復雜了。
大多數(shù)充滿激情的軟件開發(fā)者的目標,都是創(chuàng)造出一個超棒的設計;這也是通往架構(gòu)師和職業(yè)升華的道路。我們必須學習,要在軟件設計上做到最好。我們必須對結(jié)構(gòu)化設計和面向?qū)ο笤O計都有著深度理解。我們必須了解分布式系統(tǒng)的基本原則。我們必須非常熟悉所有層級的內(nèi)聚和耦合。我們必須理解協(xié)變與逆變。我們必須學會設計包含了契約與不變量的組件邊界。我們必須學會理解業(yè)務語言中的動詞和名詞,并將它們映射進軟件中。如果不知道怎樣在關(guān)系數(shù)據(jù)庫中對數(shù)據(jù)建模,不知道怎樣讓查詢表現(xiàn)良好,那就根本過不了入職面試那一關(guān)。我們必須能在合適的粒度定義自己的專有協(xié)議,以便能讓其他系統(tǒng)更容易地使用它們,同時,還要能處理輸入輸出(I/O)和帶寬問題。是的,我們花費大量的時間來干這事兒。
90年代 的軟件開發(fā)基本圍繞設計和架構(gòu)展開。而且,還必須用UML來完成。
但是,雖然我們學會了怎樣設計,卻敗在了很多其他方面。我們開發(fā)得不夠快。事實上,在某些項目中,我們根本沒能產(chǎn)出任何東西。大多數(shù)時候,我們花費在拿出一份完美設計上的所有腦力勞動都完全打了水漂——缺乏快速反饋以及對業(yè)務發(fā)展的無力應對。我依然記得在一行代碼都還沒開始寫之前就用來控制需求變更的巨大電子表格。是的,我們報銷了大量的時間。很多很多次地報銷掉了。
快進20年,我們中的有些人意識到了之前所做的是錯的。于是,我們在工作方式中引入了敏捷開發(fā)(Agile)、精益開發(fā)(Lean)和其他多種開發(fā)原則和實踐。我們的工具包中加進了很多新的設計和架構(gòu)技巧。我們引入了新的技術(shù)。我們?nèi)诤狭伺c業(yè)務協(xié)作的不同方式,開發(fā)團隊構(gòu)建方式也有了創(chuàng)新。我們認識到,盡管設計非常重要,但沒有什么東西比持續(xù)推出軟件更重要的。我們學會了怎樣獲得反饋并進行迭代。我們明白了自己有責任測試自己的代碼。我們懂得了必須在生產(chǎn)中為軟件提供支持。我們知曉了創(chuàng)建原型再摒棄的價值。我們了解了實驗的重要性。但是,我們同樣深深領(lǐng)會到,即便要以更好的方式工作,這些年來我們所獲得的所有設計技巧也不用全都扔掉。我們沒必要放棄我們那個時代,70、80、90年代軟件設計上的眾多出色成果。但,我們學到的最重要的一課,就是:上下文才是決定性的,軟件設計就是在權(quán)衡而已。沒有產(chǎn)品,設計毫無意義。那么,我們就要不斷產(chǎn)出沒有堅實的設計基礎(chǔ)的代碼嗎?我可不這么認為。
今天的軟件設計中,我所看出的最大的問題,就是二元思維。如果X不行,那么Y必然很好。如果X適用于A公司,那我們也一定能用。如果某個著名人物在一場45分鐘的演講里說了什么東西,或者我們在博客里看到了什么東西,那肯定是真的。例子太多,不勝枚舉。
二元思維引發(fā)的另一個常見錯誤,就是堅信軟件項目的所有功能都具有同等的復雜度,一個設計選擇就能通吃。但真相是:某些功能相當簡單,某些十分復雜,其他跟多的則處于兩者之間。有時候,復雜性存在于實現(xiàn)階段;其他時候則會在理解和建模階段出現(xiàn)。有時候復雜性在于弄清我們應該做出個什么東西。其他時候則在于與別的系統(tǒng)的集成上。就算是同一個功能,不同部分在復雜性上也有很大的區(qū)別:一些部分可能很小,可以快速實現(xiàn),而其他部門有可能極端復雜,需要預先考慮很多。某些功能很淺,幾行代碼就搞定,其他則很深,要用到多個模塊,上千行代碼。非功能性需求也會讓簡單功能的部署變得相當復雜。而有趣的是,以上種種都在同一個軟件項目中碰上。因此,如果我們認同軟件項目中不同功能有著不同的復雜度和規(guī)模,那么,我們就不能將二元思維應用到軟件設計上——一個相當復雜的軟件項目是不可能用單一設計方法搞定的。
我們生活在一個信息觸手可及的世界。谷歌搜索一下,我們就能搜到很多現(xiàn)成的解決方案。我所恐懼的是,作為一個產(chǎn)業(yè),我們正在喪失思考的能力。我們正在喪失研究并作出我們自己的選擇的能力。我們越來越多地依賴于現(xiàn)成的解決方案。我們總是在走捷徑。要我說的話,我會把這些所謂的捷徑稱作“Stack Overflow(一個與程序相關(guān)的IT技術(shù)問答網(wǎng)站)”解決方案。
對某些人而言,軟件設計就是過度設計的同義詞,這讓我很傷心。另一個讓我傷心的認知是,“根本沒有設計”正成為敏捷開發(fā)、精益創(chuàng)業(yè)和快速交付的同義詞。我不覺得良好軟件設計、敏捷開發(fā)和精益原則的發(fā)起人和倡導者們的本意是這樣的。過度設計不是件好事,但沒有設計不也很糟么?簡單不意味著扯淡。簡單代表的是我們當下所知道的剛剛好的設計,而不是少到可憐或者根本沒有的設計。套用愛因斯坦的話:軟件設計應該盡可能簡單,但不能過于簡單了。或者,另一種表達方式:代碼應該是良好設計的,而不是過度設計的。
過去幾年里我與很多開發(fā)者聊過,也復查了很多的代碼,我主要擔心的是,我們正在發(fā)展一種黑客文化。我見過的從業(yè)不足10年的很多開發(fā)者,都幾乎沒有什么良好軟件設計的知識。當然,他們自己不那么認為。如果你覺得我是在夸大其詞,那就去讓你團隊中的開發(fā)人員解釋一下什么是內(nèi)聚,以及內(nèi)聚的不同層級。問問他們共生性、協(xié)變、逆變的含義。問他們耦合的不同等級和類型。問他們什么是契約式設計和不變量設計。對那些聽說過面向?qū)ο笤O計SOLID原則的人,問他們SOLID原則的出處。今天的很多開發(fā)者認為設計模式不好。那就讓他們描述幾個模式,說出它們的異同,以及什么情況下應該或不應該用某種模式。問問他們不同的模式分類法。讓他們說出橋接模式、適配器模式和中介模式的差異。訪問者預期要解決什么問題?問問他們什么是備忘錄模式。如果他們解釋不出,那他們又怎能稱設計模式不好呢?
今天的很多開發(fā)者都沒有意識到軟件設計基礎(chǔ)都是在70、80、90年代鋪設的。其他開發(fā)者則傾向于無視這一事實:這就是過度設計,我們不需要。好吧,我尊重個人意愿。那我們?yōu)槭裁匆廊槐A袅四切┰阃噶说能浖?#xff1f;難道今天的做出的軟件就真的比20年前做出的好嗎?為什么開發(fā)者今天依然在用測試驅(qū)動開發(fā)模式(TDD)艱難設計代碼?為什么我們依然在討論遺留代碼?對我而言,遺留代碼就是設計很爛、難以測試和維護的代碼的代名詞。
我絕非在為過度設計或浪費時間畫UML圖表辯護。我想說的是,我不會花幾個小時去設計核心領(lǐng)域內(nèi)部類,也不會試圖在開始編碼之前不考慮整體設計就去打造一個企業(yè)應用并一次次測試。設計是軟件開發(fā)中的重要一環(huán)。如果我要打造一個與其他很多應用共存于同一個生態(tài)系統(tǒng)內(nèi)的應用程序,或者一個背負沉重非功能性需求的應用,又或者一個需要遵從很多規(guī)則的應用,好吧,我當然會在動工之前認真考慮它的整體架構(gòu)(宏設計),但我也會邊開發(fā)邊測試它的功能(“微層級”)。設計存在于各個層級:從前期的架構(gòu)層級,到即時的作為我TDD流一部分的微層級。決定設計的量是個技術(shù)活兒——關(guān)鍵就在找到拐點。
軟件設計是軟件開發(fā)中最重要的技術(shù)之一。好的設計能讓開發(fā)者相互協(xié)作,業(yè)務功能可以隨時增加和改變,還能擁有可靠的自動化測試。隨著經(jīng)驗的積累,我們會學會怎樣快速找到問題點,估算出應該花費在解決問題上的時間。我們還明白,大多數(shù)設計決策應該在最后時刻再做出,這意味著,在還沒掌握問題的足夠情報前,我們盡量不過早地綁定到某個設計上。
這就是為什么我說我們90年代所做的是并非都是無用功的原因。盡管我們過度設計,盡管我們產(chǎn)出不多,但我們學會了怎樣設計。我們學會了怎樣為我們自己考慮。我們學會了怎樣研究。我們學會了怎樣思考權(quán)衡。花了些時間,但我們確實學會了怎樣避免二元思維,節(jié)制我們對于新潮流的過度興奮。強大的軟件設計基礎(chǔ)和敏捷開發(fā)及精益開發(fā)原則和實踐的結(jié)合,讓我們不僅可以快速拿出軟件,還能持續(xù)推出軟件。
我們的目標是支持業(yè)務敏捷性,而這能通過可以持續(xù)部署到產(chǎn)品中的軟件來達到。一次性部署軟件沒什么難的,但想要幾個月甚至幾年時間里保持每天都往產(chǎn)品中部署軟件,就沒那么簡單了。我們需要很多守則和工程設計來達到持續(xù)部署的目標,也就讓軟件設計和TDD成為了我們必須掌握的兩大重要技術(shù)原則。
作者:桑德羅·曼卡索(Sandro Mancuso),軟件工藝師,作家,倫敦軟件工藝社區(qū)(LSCC)創(chuàng)始人。幼年即開始寫代碼,但直到1996年才正式入行。曾為初創(chuàng)公司、軟件作坊、產(chǎn)品公司、國際咨詢公司和投資銀行工作。
其職業(yè)生涯中曾有機會參與多種多樣的項目,用過不同編程語言、技術(shù),跨越很多不同行業(yè)。桑德羅在向不同規(guī)模的公司企業(yè)引入軟件工藝理念和極限編程實踐上有著豐富的經(jīng)驗。由于在發(fā)展和傳播軟件工藝上的杰出工作,桑德羅蜚聲國際,常被邀請參與各種全球性會議并發(fā)表演講。他的職業(yè)抱負,是通過幫助開發(fā)者進一步關(guān)注和改善自身技藝,來促使軟件產(chǎn)業(yè)向前發(fā)展
原文地址:http://www.lindukj.cn/news/archives/829
總結(jié)
以上是生活随笔為你收集整理的或许我们做错了,但绝非一无是处的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Manjaro 安装 Wacom 驱动
- 下一篇: 排序算法详解(Java实现 + 动画演示