當前位置:名人名言大全網 - 笑話大全 - 什麽是軟件設計?

什麽是軟件設計?

面向對象技術,尤其是C++,似乎給軟件行業帶來了不小的震動。出現了大量的論文和書籍來描述如何應用這項新技術。總的來說,關於面向對象技術是否只是壹個騙局的問題已經被那些關於如何以最小的努力獲得利益的問題所取代。面向對象技術已經存在了壹段時間,但是這種爆炸性的流行似乎有點不尋常。為什麽會突然有人關註?對於這個問題,人們給出了各種各樣的解釋。事實上,原因可能不止壹個。或許,各種因素綜合起來,終於可以有所突破,這項工作正在進行中。然而,在軟件革命的最新階段,C++本身似乎是壹個主要因素。同樣,這個問題大概也有很多原因,但我想從壹個稍微不同的角度給出壹個答案:C++之所以變得流行,是因為它讓軟件設計變得更容易,同時也讓編程變得更容易。

這個解釋雖然看起來很奇怪,但卻是深思熟慮的結果。本文只是想關註壹下編程和編程的關系。近10年來,我壹直覺得整個軟件行業都沒有意識到做壹個軟件設計和什麽是真正的軟件設計之間的細微差別。只要看到這壹點,我想我們就能從C++成長的流行趨勢中學到如何成為更好的軟件工程師的深刻知識。這個知識就是編程不是構建軟件,而是設計軟件。

幾年前,我參加了壹個研討會,討論軟件開發是不是工程學科。雖然我不記得討論的結果,但我記得它是如何讓我意識到軟件行業與硬件工程做了壹些錯誤的比較,而忽略了壹些絕對正確的。其實我覺得我們不是軟件工程師,因為我們沒有意識到什麽是真正的軟件設計。現在,我更加確信這壹點。

任何工程活動的最終目標都是某些類型的文檔。當設計工作完成後,設計文件移交給制造團隊。團隊和設計團隊是完全不同的群體,技能也和設計團隊完全不同。如果設計文檔正確地描述了壹個完整的設計,那麽制造團隊就可以開始制造產品了。事實上,他們可以開始構建產品的許多物理對象,而無需設計師的任何進壹步幹預。根據我的理解回顧軟件開發的生命周期後,我得出壹個結論:真正符合工程設計標準的軟件文檔只有源代碼清單。

關於這個觀點,人們已經有過很多爭論,贊成和反對的都足以寫下無數的論文。本文假設最終的源代碼是真正的軟件設計,然後仔細研究這種假設帶來的壹些結果。我可能無法證明這個觀點是正確的,但我想證明它確實解釋了軟件行業的壹些觀察到的事實,包括C++的流行。

在將代碼視為軟件設計的結果時,壹個結果完全蓋過了所有其他結果。它是非常重要和明顯的,正因為如此,它完全是大多數軟件組織的盲點。結果是軟件的構建成本很低。它根本不具備昂貴的資質;很便宜,幾乎免費。如果源代碼是軟件設計,那麽實際的軟件構造是由編譯器和連接器完成的。我們經常把編譯和連接壹個完整的軟件系統的過程稱為“壹次構建”。軟件構建設備的主要投資非常少——所需要的只是壹臺計算機、壹個編輯器、壹個編譯器和壹個連接器。壹旦妳有了壹個構建環境,實際的軟件構建只需要壹點時間。編譯壹個50000行的C++程序可能需要很長時間,但是要建立壹個和50000行C++程序設計復雜度壹樣的硬件系統需要多久呢?

將源代碼視為軟件設計的另壹個結果是,軟件設計相對容易創建,至少在機械意義上是如此。通常只需要幾天的時間就可以編寫(也就是設計)出壹個有代表性的軟件模塊(50到100行代碼)(完全調試它是另壹個話題,後面會詳細討論)。我很想問是否有其他學科能在這麽短的時間內產生出和軟件壹樣復雜的設計,但首先我們必須弄清楚如何衡量和比較復雜性。然而,很明顯,軟件設計可以很快變得非常龐大。

假設軟件設計相對容易創建並且本質上構建起來不貴,那麽發現軟件設計通常非常龐大和復雜就不足為奇了。這似乎是顯而易見的,但問題的重要性往往被忽視。學校裏的項目通常有幾千行代碼。具有10 000行代碼(設計)的軟件產品也被其設計者丟棄。我們早已不再關註簡單的軟件。典型的商業軟件的設計是由成千上萬行代碼組成的。許多軟件設計達到數百萬行代碼。此外,軟件設計幾乎總是在進化。雖然目前的設計可能只有幾千行代碼,但在產品的生命周期中,妳可能實際上要寫很多倍的代碼。

雖然有壹些硬件設計看起來像軟件設計壹樣復雜,但請註意關於現代硬件的兩個事實。首先,復雜的硬件工程結果可能並不總是無錯的。在這壹點上,並沒有我們像軟件壹樣相信的評判標準。大多數微處理器在出售時都會出現壹些邏輯錯誤:橋梁倒塌、大壩決堤、飛機失事以及數以千計的汽車和其他消費品被召回——所有這些都讓我們記憶猶新,所有這些都是設計錯誤造成的結果。其次,復雜的硬件設計有壹個相應的復雜和昂貴的建設階段。因此,制造這種系統所需的能力限制了能夠真正生產復雜硬件設計的公司數量。對於軟件來說,沒有這樣的限制。目前,有數百個軟件組織和數千個非常復雜的軟件系統,並且數量和復雜性每天都在增加。這意味著軟件行業不可能通過模仿硬件開發者來找到解決自身問題的方法。如果說有什麽共同點的話,那就是當CAD和CAM可以幫助硬件設計師創造出越來越復雜的設計時,硬件工程會變得越來越類似於軟件開發。

設計軟件是壹項管理復雜性的活動。復雜性存在於軟件設計本身,存在於公司的軟件組織,存在於整個軟件行業。軟件設計和系統設計非常相似。它可以跨越許多技術,並且經常涉及許多學科分支。軟件規範通常不是固定的,並且經常快速變化,這種情況經常發生在軟件設計過程中。同樣,軟件開發團隊也往往不穩定,經常在設計過程中變動。在許多方面,軟件比硬件更像壹個復雜的社會或有機系統。所有這些都使得軟件設計成為壹個困難且容易出錯的過程。雖然所有這些都不是創造性的想法,但在軟件工程革命開始近30年後的今天,與其他工程行業相比,軟件開發看起來仍然像是壹項未經訓練的技能。

人們普遍認為,當真正的工程師完成壹個設計時,不管它有多復雜,他們都非常有信心這個設計能夠工作。他們也非常有信心,可以使用公認的技術來構建設計。為了做到這壹點,硬件工程師花費大量時間來驗證和改進他們的設計。例如,考慮壹個橋梁設計。在這樣的設計實際建造之前,工程師將進行結構分析——他們將建立計算機模型並進行模擬,他們將建立比例模型並在風洞中或以其他方式進行測試。總之,在施工之前,設計師會用壹切能想到的方法來證明設計是正確的。對於新客機的設計來說,情況更為嚴重;需要造壹個和原來壹樣大小的樣機,必須進行飛行試驗,驗證設計中的各種預期。

對於大多數人來說,軟件方面顯然沒有硬件設計這麽嚴格的項目。但是,如果我們把源代碼看成壹個設計,我們會發現,軟件工程師其實已經對他們的設計做了很多驗證和改進。軟件工程師稱之為測試和調試,而不是工程。大多數人都沒有把測試和調試當成壹個真正的“項目”——在軟件行業肯定沒有。這種觀點的原因更多是因為軟件行業拒絕將代碼視為設計,而不是任何實際的工程差異。事實上,測試模型、原型和電路測試板已經成為其他工程學科公認的組成部分。軟件設計者之所以沒有或者沒有使用更形式化的方法來驗證自己的設計,是因為軟件構建周期這壹簡單的經濟規律。

第壹個啟示:僅僅構建壹個設計並測試它比做其他任何事情都要便宜和簡單。我們不關心構建了多少個構建——這些構建在時間上的成本幾乎為零,如果我們丟棄該構建,它所使用的資源可以完全重用。請註意,測試不僅僅是讓當前的設計正確,它也是改進設計過程的壹部分。復雜系統的硬件工程師經常建立模型(或者,至少,他們用計算機圖形可視化設計)。這讓他們對設計有了壹種“感覺”,但僅僅通過檢查設計是不可能得到這種感覺的。軟件既不可能也沒有必要建立這樣的模型。我們只是制造產品本身。即使正式的軟件驗證可以像編譯器壹樣自動完成,我們仍然會經歷構建/測試周期。所以形式驗證對於軟件行業來說從來沒有太大的實際意義。

這就是當前軟件開發過程的現實。越來越多的人和組織正在創造更復雜的軟件設計。這些設計將用壹些編程語言編寫,然後通過構建/測試周期進行驗證和改進。這個過程容易出錯,也不是特別嚴格。相當多的軟件開發人員不願意相信這就是流程的工作方式,這使得問題變得更加復雜。

目前,大多數軟件過程試圖將軟件設計的不同階段分成不同的類別。頂層設計完成凍結後才能開始編碼。測試和調試只是為了消除構造錯誤。程序員在中間。他們是軟件行業的建築工人。很多人認為,如果我們能讓程序員停止“黑客”行為,按照給他們的設計進行構建(並在過程中少犯錯誤),那麽軟件開發就可以變得成熟,成為真正的工程學科。然而,只要該過程忽略工程和經濟事實,這種情況就不會發生。

舉個例子,任何壹個現代工業都無法忍受其制造過程中超過100%的返工率。如果壹個建築工人第壹次經常做不好,他很快就會失業。但是在軟件行業,即使是最小的壹段代碼也有可能在測試和調試過程中被修改或完全重寫。在壹個創造性的過程中(比如設計),我們認識到這種改進不是制造過程的壹部分。沒有人指望工程師第壹次就能創造出完美的設計。即使她做到了,她仍然必須經歷改進過程,以證明它是完美的。

即使我們沒有從日本的管理方法中學到什麽,也要知道,把過程中的錯誤歸咎於工人是不利於提高生產率的。我們不應該總是強迫軟件開發遵循不正確的過程模型。相反,我們需要改進過程來幫助而不是阻礙更好軟件的生產。這是軟件工程的試金石。工程是關於妳如何實現過程,而不是關於妳是否需要壹個CAD系統來產生最終的設計文檔。

關於軟件開發有壹個壓倒性的問題,那就是壹切都是設計過程的壹部分。編碼是設計,測試和調試是設計的壹部分,我們通常認為的設計仍然是設計的壹部分。盡管軟件的構建成本很低,但設計成本卻高得令人難以置信。軟件非常復雜,有許多不同方面的設計內容和設計考慮。問題是所有不同的方面都是相互關聯的(就像硬件工程壹樣)。我們希望頂層設計者可以忽略模塊算法設計的細節。同樣,我們希望程序員在設計模塊內部算法時不必考慮頂層設計問題。不幸的是,壹個設計層次的問題會侵入其他層次。對於整個軟件系統的成功來說,為特定的模塊選擇壹個算法可能和任何更高層次的設計問題壹樣重要。在軟件設計的不同方面沒有重要性的等級。最低模塊中的錯誤設計可能與最高模塊中的錯誤壹樣致命。軟件設計必須是完整的,各方面都是正確的,否則,所有基於這個設計的軟件都是錯誤的。

為了管理復雜性,軟件是分層設計的。當壹個程序員在考慮壹個模塊的詳細設計時,可能有幾百個其他模塊,幾千個細節,他不可能同時考慮到。比如在軟件設計中,有壹些重要的方面並不完全屬於數據結構和算法的範疇。理想情況下,程序員在設計代碼時不應該考慮設計的其他方面。

然而,設計不是這樣工作的,原因開始變得清晰。軟件設計在編寫和測試之前是不完整的。測試是設計驗證和改進過程的基本部分。高層結構的設計不是壹個完整的軟件設計;它只是詳細設計的結構框架。我們嚴格驗證高層設計的能力非常有限。詳細設計最終對高層次設計的影響至少和其他因素壹樣大(或者應該允許這種影響)。改進設計的各個方面是壹個應該貫穿整個設計周期的過程。如果設計的任何方面被凍結在改進過程之外,那麽最終的設計會很糟糕甚至無法工作也就不足為奇了。

如果高級軟件設計能成為壹個更嚴謹的工程過程就太好了,但是軟件系統的真實情況並不嚴謹。軟件很復雜,它依賴於太多其他東西。也許,壹些硬件並不像設計者想的那樣工作,或者壹個庫例程有壹個在文檔中沒有解釋的限制。每個軟件項目遲早都會遇到這類問題。這幾類問題都會在測試的時候發現(如果我們做好測試的話),因為沒有辦法早期發現。當它們被發現時,它們會強制修改設計。如果我們幸運的話,對設計的改變是局部的。往往變更會影響到整個軟件設計的壹些重要部分(墨菲定律)。當受影響的設計的壹部分由於某種原因無法改變時,那麽為了適應這種影響,就必須破壞設計的其他部分。這通常會導致管理者認為的“隨機編碼”,但這就是軟件開發的現實。

例如,在我最近參與的壹個項目中,我發現了模塊A的內部結構與另壹個模塊B之間的時間依賴關系,不幸的是,模塊A的內部結構隱藏在壹個抽象體的後面,該抽象體不允許以任何方式將對模塊B的調用組合到其正確的調用序列中。發現問題的時候,當然錯過了改變A的抽象體的機會。正如預期的那樣,所發生的事情是將越來越多的復雜“修正”應用於A的內部設計。當我們還沒有安裝完1版本的時候,普遍感覺設計在走下坡路。每壹次新的改版都有可能毀掉壹些舊的。這是壹個正式的軟件開發項目。最後,我和同事們決定更改設計,但為了得到管理層的批準,我們不得不自願加班,而且沒有報酬。

在任何大規模的軟件項目中,這樣的問題都是不可避免的。雖然人們已經用了各種方法來阻止它的出現,但還是忽略了壹些重要的細節。這就是技術和工程的區別。如果經驗能把我們引向正確的方向,這就是技術。如果經驗只會帶我們進入未知的領域,那麽我們必須使用我們在開始時使用的方法,並通過受控的改進過程使其變得更好,這就是工程。

讓我們來看看吧。作為其中很小的壹部分,所有程序員都知道,在編碼之後而不是之前寫軟件設計文檔,會產生更準確的文檔。原因很明顯。由代碼表示的最終設計是構建/測試周期中唯壹改進的東西。在這個周期中,初始設計保持不變的可能性與項目中模塊的數量和程序員的數量成反比。很快就會變得壹文不值。

在軟件工程中,我們需要各個層面的優秀設計。我們尤其需要優秀的頂層設計。初始設計越好,詳細設計就越容易。設計師應該使用任何有幫助的東西。結構圖、布奇圖、狀態表、PDL等。-如果有幫助,就用吧。但是,我們必須記住,這些工具和符號不是軟件設計。最後,我們必須創建壹個真正的軟件設計,而且是用編程語言完成的。因此,當我們開始設計時,我們不應該害怕編碼。我們必須願意在必要時改進它們。

到目前為止,還沒有壹種設計符號可以同時適用於頂層設計和詳細設計。設計最終將被表達為用編程語言編寫的代碼。這意味著在詳細設計開始之前,頂層設計符號必須轉換成目標編程語言。這壹轉換步驟需要時間並會引入誤差。程序員往往會審核需求並重新設計頂層設計,然後根據自己的實際情況進行編碼,而不是從壹個可能與所選編程語言不完全映射的符號進行轉換。這也是軟件開發現實的壹部分。

也許,如果設計者自己寫初始代碼,而不是讓別人在後面改造語言無關的設計,效果會更好。我們需要的是壹個適合各個層次設計的統壹符號。換句話說,我們需要壹種編程語言,這種語言也適合捕捉高層次的設計概念。c++正好可以滿足這個要求。C++是壹種適合真實項目的編程語言,也是壹種非常有表現力的軟件設計語言。C++允許我們直接表達關於設計組件的高級信息。這樣,可以更容易地進行設計,並且在將來可以更容易地改進設計。因為它有更強大的類型檢查機制,所以它也有助於檢測設計中的錯誤。這導致更穩健的設計,這實際上是更好的工程設計。

最後,軟件設計必須用編程語言來表達,然後通過構建/測試周期來驗證和改進。除此之外的任何其他想法都是完全沒有用的。請考慮什麽軟件開發工具和技術是流行的。結構化編程在當時被認為是壹種創造性的技術。帕斯卡讓它流行起來,自己也因此變得流行起來。面向對象設計是壹門新興的熱門技術,C++是其核心。現在,請考慮那些無效的事情。案例工具,流行嗎?有;具有普遍性嗎?沒有。結構圖怎麽樣?情況是壹樣的。同樣,還有華納-奧爾圖、布奇圖、對象圖以及妳能想到的壹切。每壹個都有自己的優勢,只有壹個根本的弱點——它不是壹個真正的軟件設計。事實上,唯壹被普遍認可的軟件設計符號是PDL,它看起來像什麽?

這說明在軟件行業共同的潛意識裏,本能地知道編程技術的提高,尤其是實際開發中使用的編程語言,與軟件行業的其他任何事情相比,都具有壓倒性的重要性。也說明程序員是在乎設計的。當更具表現力的編程語言出現時,軟件開發人員會使用它們。

同樣,請考慮軟件開發過程是如何變化的。從前,我們使用瀑布過程。現在,我們討論的是螺旋開發和快速原型。雖然這些技術經常被認為是“消除風險”和“縮短產品的交付時間”,但它們實際上只是為了在軟件生命周期中更早地開始編碼。這是好事。這允許構建/測試周期更早地開始驗證和改進設計。這也意味著頂級軟件設計師很可能會進行詳細設計。

如上所述,工程更多的是關於如何實現過程,而不是最終產品是什麽樣子。在軟件行業,我們已經接近工程師的標準,但是需要壹些認知上的改變。編程和構建/測試周期是工程軟件過程的中心。我們需要以這種方式管理它們。構建/測試周期的經濟規律,加上軟件系統幾乎可以代表任何東西的事實,使得我們完全不可能找到壹種通用的方法來驗證軟件設計。我們可以改進這個過程,但不能脫離它。

最後壹點:任何工程設計項目的目標都是壹些文檔產品。顯然,實際設計的文檔是最重要的,但它們不是唯壹要制作的文檔。最終,有人會使用這個軟件。同樣,該系統很可能需要後續的修改和增強。這意味著輔助文檔對於軟件項目和硬件項目壹樣重要。雖然暫時忽略了用戶手冊、安裝指南等與設計過程沒有直接關系的文檔,但是仍然有兩個重要的需求需要利用輔助設計文檔來解決。

輔助文檔的第壹個目的是從問題空間捕捉重要信息,這些信息不能直接用於設計。軟件設計需要創建壹些軟件概念來對問題空間中的概念進行建模。這個過程要求我們理解問題空間中的概念。通常,這種理解會包含壹些不會在軟件空間中直接建模的信息,但是這些信息仍然會幫助設計者確定什麽是基本概念以及如何最好地對它們建模。這些信息應該記錄在某個地方,以防您以後想要更改模型。

輔助文檔的第二個重要需求是記錄設計的某些方面,這些方面很難直接從設計本身提取。它們可以是高級內容,也可以是低級內容。對於其中的許多方面,圖形是描述它們的最佳方式。這使得它們很難作為註釋包含在代碼中。這並不是說應該使用圖形化的軟件設計符號來代替編程語言。這和用壹些文字描述來補充硬件科目的平面設計文檔沒什麽區別。

永遠不要忘記,決定實際設計真實面貌的是源代碼,而不是輔助文檔。理想情況下,可以使用軟件工具對源代碼進行後處理,生成輔助文檔。我們可能對此期望過高。接下來,程序員(或技術作者)可以使用壹些工具從源代碼中提取壹些特定的信息,然後他們可以用其他方式記錄這些信息。毫無疑問,手動更新這種文檔是很困難的。這是支持需要更具表現力的編程語言的另壹個原因。同樣,這也是支持將這個輔助文檔保持在最低限度,並在項目中盡可能晚地將其正式化的壹個原因。同樣,我們可以使用壹些好的工具;否則,我們不得不求助於鉛筆、紙和黑板。

總結如下:

實際的軟件在計算機中運行。它是存儲在某種磁介質中的0和1的序列。它不是用C++(或任何其他編程語言)編寫的程序。

程序列表是代表軟件設計的文檔。事實上,是編譯器和連接器構建了軟件設計。

令人難以置信的是,構建壹個實際的軟件設計是多麽便宜,而且隨著計算機速度的加快,它總是變得更便宜。

設計實際軟件的成本令人難以置信,因為軟件的復雜程度令人難以置信,軟件項目的幾乎所有步驟都是設計過程的壹部分。

編程是壹種設計活動——壹個好的軟件設計過程認識到了這壹點,當編碼有意義時,就會毫不猶豫地編碼。

編碼比我們想象的更頻繁地顯示出它的意義。通常,用代碼表達設計的過程會暴露出壹些遺漏和額外的設計需求。這種情況越早發生,設計就越好。

因為軟件構建起來非常便宜,所以正式的工程驗證方法在實際的軟件開發中用處不大。僅僅構建壹個設計並測試它比試圖證明它更簡單也更便宜。

測試和調試是設計活動——對於軟件來說,它們相當於其他工程學科中的設計驗證和改進過程。壹個好的軟件設計過程認識到了這壹點,並且不會試圖減少這些步驟。

還有其他的設計活動——稱之為高層設計、模塊設計、結構設計、架構設計之類的。壹個好的軟件設計過程認識到這壹點,並仔細包括這些步驟。

所有的設計活動都是互動的。當不同的設計步驟顯示出必要性時,壹個好的軟件設計過程認識到這壹點,並允許設計變更,有時甚至是根本性的變更。

許多不同的軟件設計符號可能是有用的——它們可以作為輔助文檔和工具來幫助簡化設計過程。它們不是軟件設計。

軟件開發仍然是壹門手藝,而不是壹門工程學科。主要是在驗證和改進設計的關鍵過程中不夠嚴謹。

最後,軟件開發的真正進步取決於編程技術的進步,而編程技術的進步又意味著編程語言的進步。C++就是這樣壹個改進。它獲得了爆炸性的流行,因為它是壹種直接支持更好的軟件設計的主流編程語言。

C++已經朝著正確的方向邁出了壹步,但還需要更多的進步。