1. 程式人生 > >軟體設計:我們做錯了,但不是所有事情都是徒勞

軟體設計:我們做錯了,但不是所有事情都是徒勞

有些人承認,上世紀90年代創造了很多過於複雜和過度設計的軟體。其他人則表示,那些創新模式是必要的。無論怎麼說,我們從中有學到什麼嗎?

軟體設計

是的,很多軟體過度設計,過於複雜。早在90年代中期,當我作為一個開發人員開始我的職業生涯的時候,我的目標是成為一名架構師。認真的開發人員不會在選好更優的設計模式之前寫程式碼——因為只有在選好之後,我們才能決定如何將業務需求融入到設計模式中。是的,我們會先提出架構,然後是巨集觀設計(層)和域模型(包括UML圖表),之後我們再來考慮業務需求和詳細的使用案例。是的,使用者故事在當時還不成氣候。我們在具備基本流和許多備選流的同時有很長的使用者用例。

90年代對於開發者是一段很有意思的時期。我們終於有了網際網路,來自於70和80年代關於結構化設計的一些學術論文變得唾手可得。此外,一些關於面向物件程式設計的書籍開始普及,雖然在很多地方還是一個新事物。

我依然記得我們用無數個月的時間來畫類、序列、元件、部署、以及許多其他的圖表,試圖拿出最佳的軟體設計,以便於將來某一天去構建。我們也建立了一些原型,所以我不能說我們在精化階段沒有編碼或試驗。當然,所有從原型中學到的知識會反饋到我們的圖表中。

除了內部設計,90年代的我們還經歷了分散式系統的大爆炸。我們有CORBA和DCOM。我們有客戶/伺服器以及多層體系結構。我們瞭解在使用資料庫作為應用程式之間的通訊點時會發生的單點故障。是的,我們碰到過類似於那樣的討厭問題。我們學習如何建立“服務” ——SOA正在成為一種構建的理念。我們還要學習考慮可擴充套件性和安全性。許多政府和銀行以外的專案也變得非常龐大和複雜。

建立偉大設計是大多數最富有激情的軟體開發人員的目標:這也是成為架構師和職業進化的途徑。我們需要學習並善於軟體設計。我們需要深入理解結構化和麵向物件設計的原則。我們需要理解分散式系統的原則。我們需要深入瞭解內聚與耦合的各個層面。我們需要了解協變和逆變。我們需要學習如何設計元件的界限,包括合同和不變條件。我們需要學會如何理解動詞和名詞,商務語言,並將其對映到軟體。如果不知道如何在我們的關係資料庫中資料建模,那我們將永遠過不了面試,並且更為重要的是,我們還需要學習如何讓我們的查詢執行良好。我們需要在正確的粒度中定義我們的協定架構,以便於其他系統更容易地消費它們,並同時處理好I / O和頻寬問題。是的,我們花了很多時間去做這些事情。

90年代的軟體開發都是設計和架構方面的事情。當然,還需要UML。

然而,雖然我們知道如何設計,但是我們依然在很多其他方面敗走麥城。我們釋出得不夠快。事實上,在一些專案中,我們沒有釋出任何東西。大多數時候,所有試圖建立完美設計的想法都因為缺乏快速反饋和無力應付快速發展的業務而完全浪費。我還記得我們曾經用來控制改變請求的龐大臃腫的,甚至在編碼前就要製作完成的電子表單。是的,這真是天欲其亡,必先使其狂。而且是許多許多次瘋狂。

時間又過去了20年,我們中的一些人漸漸意識到我們正在做的事情是錯誤的。於是,敏捷,精益等諸多原則和實踐開始結合到我們的工作方式中。我們合併了許多新的設計和架構技術到我們的工具包中。我們吸納了新的技術。我們結合了不同的方式到業務中以及如何構建團隊中。我們知道雖然設計很重要,但沒有什麼比持續交付軟體更重要。我們學會了如何獲取反饋和迭代。我們知道我們需要負責地測試我們自己的程式碼。我們瞭解到我們需要支援我們的產品軟體。我們知道建立原型和丟棄原型的價值。我們知道試驗的重要性。但是,我們也明白了,為了用一種更好的方式工作,我們沒有必要扔掉所有這些年來我們掌握的設計技能。我們並不需要丟棄在我們那段時間以及那段時間之前所有偉大的工作,主要關於70、80、90年代的軟體設計。但是,我們學到的最重要的經驗教訓是,上下文才是王道,軟體設計就是權衡。與交付無關的設計是沒有意義的。那麼,我們可以保持交付程式碼而無需一個堅實的設計基礎嗎?我不認為如此。

軟體設計

在當今的軟體設計中,我看到的最大的問題之一是二元思維。如果X是壞的,那麼Y一定是好的。如果X在A公司可有效工作,那麼它也一定能在我們手裡工作。知名人士在45分鐘的會議談話中以及在寫在部落格中的內容,就一定是真的。就是這樣的思維模式。

二元思維導致的另一個常見錯誤是相信軟體專案中的所有功能都有同等的複雜度,並且認為單一的設計選擇都適用。但事實是,有些功能相當簡單,有一些則非常複雜,還有一些則處於兩者之間的某個複雜程度上,不一定一致。有的複雜在實現中,還有的則是因為在理解和模擬域時很複雜。有時,我們會覺得理解我們應該構建什麼是複雜的。但是有時,複雜在與其他系統整合時。同一個功能的不同部分也會具有不同的複雜程度:有的部分可能微不足道,並且可以快速實現,但其他有的部分可能會非常複雜,並且需要你絞盡腦汁地思考。有些功能比較淺顯(只要屈指可數的幾行程式碼即可),而有些則是深不可測(因為不同的模組而延伸了成千上萬行程式碼)。非功能性需求也可能會導致簡單功能(業務方面)的實現變得非常複雜。而且有趣的是,所有這些在同一個軟體專案中都可以找到。因此,如果我們贊同一個軟體專案中的不同功能有不同程度的複雜性和規模,那麼我們就不能應用二元思維到軟體設計中——沒有一種單一的設計方法可以有效工作於一個較為複雜的軟體專案。

我們生活在一個可以方便快捷地獲取資訊的世界裡。Google一下,我們就可以找到問題很多現成的解決方案。我的擔心是,作為一個行業,我們失去了思考的能力。我們正在失去研究的能力和自己選擇的能力。我們越來越趨向於尋找一個現成的方案。快捷的方式。我稱之為“Stack Overflow解決方案”。

讓我傷心的是,對某些人來說,軟體設計是過度設計的代名詞。讓我同樣傷心的是,“毫無設計可言”正成為敏捷、精益創業和快速交付的代名詞。我不認為好的軟體設計,敏捷和精益原則的發起人和主要支持者是這種意思。過度設計是壞的,但是一點都不設計同樣是壞的。簡單不等於廢話。簡單意味著設計得剛好夠用。改寫愛因斯坦的一句話,軟體設計應儘可能的簡單,但又不能簡化。或者可以這樣說:程式碼必須精心設計而不是過度設計。

在過去幾年時間裡,在面試了很多開發人員和審查了很多程式碼之後,我最關心的是,我們正在發展一種速成文化。許多我遇到的開發人員,雖然已經在這個行業淫浸多年,但對軟體設計知識所知甚少。當然他們不會承認。如果你覺得我誇張了點,那麼你可以去問問你團隊中的開發人員如何解釋內聚力和它的不同層次。問問他們共生、協變和逆變。問問他們耦合的不同程度和型別。問問他們關於合同和不變條件的設計。對於那些聽說過SOLID原則的人,就問問他們SOLID原則出自於哪裡。許多當今的開發人員說設計模式不好。那就請他們描述一些模式以及這些模式之間的區別,還有什麼時候應當或不應當應用這些模式。問問他們關於不同的模式分類。問他們橋接器Bridge,介面卡Adapter和中介者Mediator之間的區別。關於訪問者Visitor應該解決什麼問題?還可以問問他們:“備忘錄模式Memento是什麼?”。如果他們無法解釋,那麼他們怎麼能說模式是壞的呢?

現在的許多開發人員不知道20世紀70年代,80年代,90年代間的軟體設計基礎。還有人則傾向於忽略它:這些都是過度設計的,他們不需要。好吧,我尊重每個人的選擇。那麼為什麼我們仍然有很爛的軟體?現在生產的軟體真的比20年前出產的軟體更好嗎?為什麼開發人員仍然苦苦掙扎於用TDD設計程式碼?為什麼我們還在談論遺留程式碼?在我看來,遺留程式碼就是設計得很糟糕的代名詞,因為設計得很糟糕,所以程式碼才難以測試和維護。

我決不是在捍衛過度設計,也不是對浪費時間在UML中繪製圖表表示贊同。我想說的是,在同一時間,我不會花時間去預先設計核心區域內部的類,我也不會嘗試構建企業應用程式,一次一測試,不會在考慮其整體設計之前就開始編碼。設計對於軟體開發至關重要。如果我要構建的應用程式存在於旁邊有許多應用程式的生態系統中,或者有著大量非功能性需求,或者需要遵守規定,是的,那麼理所當然地我需要在開始編碼之前周密思考其整體結構(巨集觀—設計),儘管我依然會開發其功能(“微觀—層面”),一次一個測試。各個層面上都需要設計:從前期架構層面到作為TDD流程的一部分的即時微觀層面。決定有多少設計是一種技巧——這需要找拐點,這方面內容我以前的部落格中已經討論過。

軟體設計是軟體開發中最重要的技能之一。良好的設計能使得開發人員協作,允許頻繁新增和改變業務功能,並完成可靠的自動化測試。隨著經驗的積累,我們知道了如何快速識別問題並決定應該在這上面花費多少時間。我們還了解到,大多數的設計決策應在最後的責任時刻制定,也就是,我們最好不要在我們還沒有充分了解問題的時候提交設計。

這就是為什麼我會說我們在90年代所做的一切並非都是徒勞的。雖然我們過度設計了每一樣東西,沒有釋出太多程式碼,但是我們學會了如何設計。我們學會了如何自己思考。我們學會了如何研究。我們學會了如何有依據地權衡。我們還努力學會了如何避免二元思維,以及剋制對新趨勢的興奮。結合了敏捷和精益原則和實踐的強大軟體設計基礎,讓我們現在在快速提供軟體和持續釋出軟體方面處於更有利的地位。

我們的目標是使業務具備敏捷性,而這可以通過可連續部署到生產的軟體來實現。一次性將軟體部署到生產並不難,難的是要一天多次部署軟體到生產,然後幾個月甚至幾年下來一直保持著這個節奏,沒錯,這可不是一件簡單的事情。我們需要大量練習和精心設計才能實現持續交付,這使得軟體設計和TDD成為了兩種我們必須要掌握的最重要的技術學科。

譯文連結:http://www.codeceo.com/article/we-did-wrong-but-not-in-vain.html
英文原文:We Did It Wrong, But Not All Was In Vain
翻譯作者:碼農網 – 小峰