是的,過分設計的現象廣泛存在。回到90年代中期,當我開始入行開發者行業時,個人目標就是成爲一個架構師。任何認真的開發者都不會在選定本身喜歡的設計模式以前就開始寫代碼。咱們會在選好設計模式以後纔開始思考怎樣將業務需求融合進去。是的,咱們會先弄出架構,而後是宏設計(層)和域模型(包括UML圖表),接下來才思考業務需求和詳細的用例。沒錯,那個時代,用例真的不是什麼大事。咱們的基本流程和衆多可選流程中有一長串的用例。面試
90年代是開發者們羣情振奮的時期。70和80年代還在學術論文層面上的一些結構化設計,以及互聯網,最終都在90年代實現了。那個時期裏,還出版了基本面向對象編程的書,至今在不少領域裏仍是新鮮的概念。數據庫
我依然記得咱們撲在畫類、序列、組件、部署和不少其餘圖表上的無數個月,咱們總在嘗試想出將來某天咱們將打造出的軟件的最佳設計。咱們也創建了一些原型,所以我不能說在規劃階段咱們沒有作任何的編程或試驗。固然,全部來自於原型的經驗教訓最終都會反饋到咱們的圖表中。編程
除了內部設計,90年代仍是分佈式系統大爆炸的時期。咱們有了CORBA(公共對象請求代理體系結構)和DCOM(分佈式組件對象模型),有了客戶端/服務器(C/S)和多層級架構。咱們在使用數據庫做爲應用程序間通訊點上學到了單點故障。是的,咱們在這上面栽過大跟頭。咱們學會了怎樣建立「服務」——SOA(面向服務架構)概念迅速興起。咱們學會了考慮可擴展性和安全性。不少政府和銀行之外的項目也變得很是巨大和複雜了。設計模式
大多數充滿激情的軟件開發者的目標,都是創造出一個超棒的設計;這也是通往架構師和職業昇華的道路。咱們必須學習,要在軟件設計上作到最好。咱們必須對結構化設計和麪向對象設計都有着深度理解。咱們必須瞭解分佈式系統的基本原則。咱們必須很是熟悉全部層級的內聚和耦合。咱們必須理解協變與逆變。咱們必須學會設計包含了契約與不變量的組件邊界。咱們必須學會理解業務語言中的動詞和名詞,並將它們映射進軟件中。若是不知道怎樣在關係數據庫中對數據建模,不知道怎樣讓查詢表現良好,那就根本過不了入職面試那一關。咱們必須能在合適的粒度定義本身的專有協議,以便能讓其餘系統更容易地使用它們,同時,還要能處理輸入輸出(I/O)和帶寬問題。是的,咱們花費大量的時間來幹這事兒。安全
90年代 的軟件開發基本圍繞設計和架構展開。並且,還必須用UML來完成。服務器
可是,雖然咱們學會了怎樣設計,卻敗在了不少其餘方面。咱們開發得不夠快。事實上,在某些項目中,咱們根本沒能產出任何東西。大多數時候,咱們花費在拿出一份完美設計上的全部腦力勞動都徹底打了水漂——缺少快速反饋以及對業務發展的無力應對。我依然記得在一行代碼都還沒開始寫以前就用來控制需求變動的巨大電子表格。是的,咱們報銷了大量的時間。不少不少次地報銷掉了。架構
快進20年,咱們中的有些人意識到了以前所作的是錯的。因而,咱們在工做方式中引入了敏捷開發(Agile)、精益開發(Lean)和其餘多種開發原則和實踐。咱們的工具包中加進了不少新的設計和架構技巧。咱們引入了新的技術。咱們融合了與業務協做的不一樣方式,開發團隊構建方式也有了創新。咱們認識到,儘管設計很是重要,但沒有什麼東西比持續推出軟件更重要的。咱們學會了怎樣得到反饋並進行迭代。咱們明白了本身有責任測試本身的代碼。咱們懂得了必須在生產中爲軟件提供支持。咱們知曉了建立原型再摒棄的價值。咱們瞭解了實驗的重要性。可是,咱們一樣深深領會到,即使要以更好的方式工做,這些年來咱們所得到的全部設計技巧也不用全都扔掉。咱們不必放棄咱們那個時代,70、80、90年代軟件設計上的衆多出色成果。但,咱們學到的最重要的一課,就是:上下文才是決定性的,軟件設計就是在權衡而已。沒有產品,設計毫無心義。那麼,咱們就要不斷產出沒有堅實的設計基礎的代碼嗎?我可不這麼認爲。併發
今天的軟件設計中,我所看出的最大的問題,就是二元思惟。若是X不行,那麼Y必然很好。若是X適用於A公司,那咱們也必定能用。若是某個著名人物在一場45分鐘的演講裏說了什麼東西,或者咱們在博客裏看到了什麼東西,那確定是真的。例子太多,不勝枚舉。編程語言
二元思惟引起的另外一個常見錯誤,就是堅信軟件項目的全部功能都具備同等的複雜度,一個設計選擇就能通吃。但真相是:某些功能至關簡單,某些十分複雜,其餘跟多的則處於二者之間。有時候,複雜性存在於實現階段;其餘時候則會在理解和建模階段出現。有時候複雜性在於弄清咱們應該作出個什麼東西。其餘時候則在於與別的系統的集成上。就算是同一個功能,不一樣部分在複雜性上也有很大的區別:一些部分可能很小,能夠快速實現,而其餘部門有可能極端複雜,須要預先考慮不少。某些功能很淺,幾行代碼就搞定,其餘則很深,要用到多個模塊,上千行代碼。非功能性需求也會讓簡單功能的部署變得至關複雜。而有趣的是,以上種種都在同一個軟件項目中碰上。所以,若是咱們認同軟件項目中不一樣功能有着不一樣的複雜度和規模,那麼,咱們就不能將二元思惟應用到軟件設計上——一個至關複雜的軟件項目是不可能用單一設計方法搞定的。分佈式
咱們生活在一個信息觸手可及的世界。谷歌搜索一下,咱們就能搜到不少現成的解決方案。我所恐懼的是,做爲一個產業,咱們正在喪失思考的能力。咱們正在喪失研究並做出咱們本身的選擇的能力。咱們愈來愈多地依賴於現成的解決方案。咱們老是在走捷徑。要我說的話,我會把這些所謂的捷徑稱做「Stack Overflow(一個與程序相關的IT技術問答網站)」解決方案。
對某些人而言,軟件設計就是過分設計的同義詞,這讓我很傷心。另外一個讓我傷心的認知是,「根本沒有設計」正成爲敏捷開發、精益創業和快速交付的同義詞。我不以爲良好軟件設計、敏捷開發和精益原則的發起人和倡導者們的本意是這樣的。過分設計不是件好事,但沒有設計不也很糟麼?簡單不意味着扯淡。簡單表明的是咱們當下所知道的剛恰好的設計,而不是少到可憐或者根本沒有的設計。套用愛因斯坦的話:軟件設計應該儘量簡單,但不能過於簡單了。或者,另外一種表達方式:代碼應該是良好設計的,而不是過分設計的。
過去幾年裏我與不少開發者聊過,也複查了不少的代碼,我主要擔憂的是,咱們正在發展一種黑客文化。我見過的從業不足10年的不少開發者,都幾乎沒有什麼良好軟件設計的知識。固然,他們本身不那麼認爲。若是你以爲我是在誇大其詞,那就去讓你團隊中的開發人員解釋一下什麼是內聚,以及內聚的不一樣層級。問問他們共生性、協變、逆變的含義。問他們耦合的不一樣等級和類型。問他們什麼是契約式設計和不變量設計。對那些據說過面向對象設計SOLID原則的人,問他們SOLID原則的出處。今天的不少開發者認爲設計模式很差。那就讓他們描述幾個模式,說出它們的異同,以及什麼狀況下應該或不該該用某種模式。問問他們不一樣的模式分類法。讓他們說出橋接模式、適配器模式和中介模式的差別。訪問者預期要解決什麼問題?問問他們什麼是備忘錄模式。若是他們解釋不出,那他們又怎能稱設計模式很差呢?
今天的不少開發者都沒有意識到軟件設計基礎都是在70、80、90年代鋪設的。其餘開發者則傾向於無視這一事實:這就是過分設計,咱們不須要。好吧,我尊重我的意願。那咱們爲何依然保留了那些糟透了的軟件呢?難道今天的作出的軟件就真的比20年前作出的好嗎?爲何開發者今天依然在用測試驅動開發模式(TDD)艱難設計代碼?爲何咱們依然在討論遺留代碼?對我而言,遺留代碼就是設計很爛、難以測試和維護的代碼的代名詞。
我絕非在爲過分設計或浪費時間畫UML圖表辯護。我想說的是,我不會花幾個小時去設計核心領域內部類,也不會試圖在開始編碼以前不考慮總體設計就去打造一個企業應用並一次次測試。設計是軟件開發中的重要一環。若是我要打造一個與其餘不少應用共存於同一個生態系統內的應用程序,或者一個揹負沉重非功能性需求的應用,又或者一個須要聽從不少規則的應用,好吧,我固然會在動工以前認真考慮它的總體架構(宏設計),但我也會邊開發邊測試它的功能(「微層級」)。設計存在於各個層級:從前期的架構層級,到即時的做爲我TDD流一部分的微層級。決定設計的量是個技術活兒——關鍵就在找到拐點。
軟件設計是軟件開發中最重要的技術之一。好的設計能讓開發者相互協做,業務功能能夠隨時增長和改變,還能擁有可靠的自動化測試。隨着經驗的積累,咱們會學會怎樣快速找到問題點,估算出應該花費在解決問題上的時間。咱們還明白,大多數設計決策應該在最後時刻再作出,這意味着,在還沒掌握問題的足夠情報前,咱們儘可能不過早地綁定到某個設計上。
這就是爲何我說咱們90年代所作的是並不是都是無用功的緣由。儘管咱們過分設計,儘管咱們產出很少,但咱們學會了怎樣設計。咱們學會了怎樣爲咱們本身考慮。咱們學會了怎樣研究。咱們學會了怎樣思考權衡。花了些時間,但咱們確實學會了怎樣避免二元思惟,節制咱們對於新潮流的過分興奮。強大的軟件設計基礎和敏捷開發及精益開發原則和實踐的結合,讓咱們不只能夠快速拿出軟件,還能持續推出軟件。
咱們的目標是支持業務敏捷性,而這能經過能夠持續部署到產品中的軟件來達到。一次性部署軟件沒什麼難的,但想要幾個月甚至幾年時間裏保持天天都往產品中部署軟件,就沒那麼簡單了。咱們須要不少守則和工程設計來達到持續部署的目標,也就讓軟件設計和TDD成爲了咱們必須掌握的兩大重要技術原則。
做者:桑德羅·曼卡索(Sandro Mancuso),軟件工藝師,做家,倫敦軟件工藝社區(LSCC)創始人。幼年即開始寫代碼,但直到1996年才正式入行。曾爲初創公司、軟件做坊、產品公司、國際諮詢公司和投資銀行工做。
其職業生涯中曾有機會參與多種多樣的項目,用過不一樣編程語言、技術,跨越不少不一樣行業。桑德羅在向不一樣規模的公司企業引入軟件工藝理念和極限編程實踐上有着豐富的經驗。因爲在發展和傳播軟件工藝上的傑出工做,桑德羅蜚聲國際,常被邀請參與各類全球性會議並發表演講。他的職業抱負,是經過幫助開發者進一步關注和改善自身技藝,來促使軟件產業向前發展。