再讀圖靈獎得主Brooks 沒有銀彈 什麼是卓越的設計者

Brooks本身就是個天才, 是那種爲數不多的學院派,又能客觀的面對軟件開發實踐中的獨特規律的天才。
和這樣的大牛生活在一個時代的軟件開發者是幸福的,總有一雙深邃的眼在關注着 軟件開發領域最本質的問題。
讀他的文章,如同是一劑清醒劑。

沒有銀彈並沒有否定人們尋找銀彈的所有努力,銀彈能解決一些次要問題;但是最關鍵的是,Brooks呼籲要重視 卓越的設計者。軟件開發最核心的問題需要這樣的人。

那什麼算是卓越的設計者呢?

翻譯中的“設計者”不是平面設計或者現在職位招聘中的產品經理什麼的,更不是一個項目管理的精英。
什麼算是卓越的設計者
卓越的設計者的量度,相對於優秀的設計者,卓越的設計者的成果高出一個數量級, 更快速,更簡潔。

依照現在的職位分解,可能很多人會越來越難以理解“設計者”到底是什麼。
簡單說,就是一個產品或者項目的靈魂,他能把握住 開發過程中概念的一致性。最好的情況就是對技術之外的其他能力也有所掌握。

品質
從卓越的設計者的品質來看, 他首先要具備 辨析需求階段的複雜概念,有效地面對軟件開發中最不確定最困難的 階段-----需求開發階段。
能力
他不一定是經驗最豐富的人選,也不一定具備了所有的能力。
但是至少,Brooks 的肯定是希望 卓越的設計者 至少能理解以下重要的建議:

● 仔細地進行市場調研,避免開發已上市的產品;
● 在獲取和制定軟件需求時,將快速原型開發作爲迭代計劃的一部分;
● 有機地更新軟件,隨着系統的運行、使用和測試,逐漸添加越來越多的功能;
● 不斷挑選和培養傑出新生代的概念設計人員。

軟件開發越來越崇尚閉環的開發,引入市場、商業模式的變量,這樣的綜合素質是中國軟件開發特別需要的。 短期內, 科技的原創能力和歐美還是有很大差距,但是在技術和應用領域結合方面, 有很大的創新餘地。

Brooks 大牛還特意的分享了他培養 人才的建議,值得大學和公司注意:
在這裏插入圖片描述

========================

沒有銀彈
by Frederick P. Brooks, Jr.
翻譯:未知
摘要[1]
所有軟件活動包括根本任務—— 打造構成抽象軟件實體的複雜概念結構,次要任務—— 使用編程語言表達這些抽象實體,在空間和時間限制內將它們映射成機器語言。軟件生產率在近年來取得的巨大進步來自對人爲障礙的突破,例如硬件的限制、笨拙的編程語言和機器時間的缺乏等等,這些障礙使次要任務實施起來異常艱難。相對根本任務而言,軟件工程師在次要任務上花費了多少時間和精力?除非它佔了所有工作的9/10,否則即使全部次要任務的時間縮減到零,也不會帶來生產率數量級上的提高。
因此,現在是關注軟件任務中的必要活動的時候了,也就是那些和構造異常複雜的抽象概念結構有關的部分。我建議:
● 仔細地進行市場調研,避免開發已上市的產品;
● 在獲取和制定軟件需求時,將快速原型開發作爲迭代計劃的一部分;
● 有機地更新軟件,隨着系統的運行、使用和測試,逐漸添加越來越多的功能;
● 不斷挑選和培養傑出新生代的概念設計人員。

介紹
在所有恐怖民間傳說的妖怪中,最可怕的是人狼,因爲它們可以完全出乎意料地從熟悉的面孔變成可怕的怪物。爲了對付人狼,我們在尋找可以消滅它們的銀彈。
大家熟悉的軟件項目具有一些人狼的特性(至少在非技術經理看來),常常看似簡單明瞭的東西,卻有可能變成一個落後進度、超出預算、存在大量缺陷的怪物。因此,我們聽到了近乎絕望的尋求銀彈的呼喚,尋求一種可以使軟件成本像計算機硬件成本一樣迅速降低的尚方寶劍。
但是,我們看看近十年來的情況,沒有發現銀彈的蹤跡。沒有任何技術或管理上的進展,能夠獨立地許諾在生產率、可靠性或簡潔性上取得數量級的提高。本章我們試圖通過分析軟件問題的本質和很多候選銀彈的特徵,來探索其原因。
不過,懷疑論者並不是悲觀主義者。儘管我們沒有看見令人驚異的突破,並認爲這種銀彈實際上是與軟件的內在特性相悖的,不過還是出現了一些令人振奮的革新。這些方法的規範化、持續地開拓、發展和傳播確實是可以在將來使生產率產生數量級的提高。雖然沒有通天大道,但是路就在腳下。
解決管理災難的第一步是將大塊的“巨無霸理論”替換成“微生物理論”,它的每一步—— 希望的誕生,本身就是對一蹴而就型解決方案的衝擊。它告訴工作者進步是逐步取得的,伴隨着辛勤的勞動,對規範化過程進行持續不懈的努力。由此,誕生了現在的軟件工程。
是否一定那麼困難呢?—— 根本困難
不僅僅是在目力所及的範圍內沒有發現銀彈,軟件的特性本身也導致不大可能有任何的發明創新—— 能夠像計算機硬件工業中的電子器件、晶體管、大規模集成一樣—— 提高軟件的生產率、可靠性和簡潔程度。我們甚至不能期望每兩年有兩倍的增長。
首先,我們必須看到這樣的畸形並不是由於軟件發展得太慢,而是因爲計算機硬件發展得太快。從人類文明開始,沒有任何其他產業技術的性價比,能在30年之內取得6個數量級的提高,也沒有任何一個產業可以在性能提高或者成本降低方面取得如此的進步。這些進步來自計算機制造產業的轉變,從裝配工業轉變成流水線工業。
其次,讓我們瞭解中間的困難,來看看我們能期待什麼樣的軟件技術產業發展速度。效仿亞里士多德,我將它們分成根本的(essence)—— 軟件特性中固有的困難,次要的(accident)—— 出現在目前生產中,但並非那些與生俱來的困難。
我們在下一節中討論次要問題。首先,來關注根本問題。
一個相互牽制關聯的概念結構是軟件實體必不可少的部分,它包括:數據集合、數據條目之間的關係、算法和功能調用等等。這些要素本身是抽象的,體現在不同的表現形式下的概念構造是相同的。儘管如此,它仍然是內容豐富和高度精確的。
我認爲軟件開發中困難的部分是規格說明、設計和測試這些概念上的結構,而不是對概念進行表達和對實現逼真程度進行驗證。當然,我們還是會犯一些語法錯誤,但是與絕大多數系統中的概念錯誤相比,它們是微不足道的。
如果這是事實,軟件開發總是非常困難的,天生就沒有銀彈。
讓我們來考慮現代軟件系統中這些無法規避的內在特性:複雜度、一致性、可變性和不可見性。
複雜度。規模上,軟件實體可能比任何由人類創造的其他實體更復雜,因爲沒有任何兩個軟件部分是相同的(至少在語句的級別上)。如果有相同的情況,我們會把它們合併成供調用的子函數。在這個方面,軟件系統與計算機、建築或者汽車大不相同,後者往往存在着大量重複的部分。
數字計算機本身就比人類建造的大多數東西複雜。計算機擁有大量的狀態,這使得構思、描述和測試都非常困難。軟件系統的狀態又比計算機的狀態多若干個數量級。
同樣,軟件實體的擴展也不僅僅是相同元素重複添加,而必須是不同元素實體的添加。大多數情況下,這些元素以非線性遞增的方式交互,因此整個軟件複雜度要比非線性增長多得多。
軟件的複雜度是根本屬性,不是次要因素。因此,抽掉複雜度的軟件實體描述常常也去掉了一些本質屬性。數學和物理學在過去三個世紀取得了巨大的進步,數學家和物理學家們爲複雜的現象建立了簡化的模型,從模型中抽取出各種特性,並通過試驗來驗證這些特性。這些方法之所以可行,是因爲模型中忽略的複雜度不是被研究現象的根本屬性。當複雜度是本質特性時,這些方法就行不通了。
上述軟件特有的複雜度造成了很多經典的軟件產品開發問題。由於複雜度,團隊成員之間的溝通非常困難,導致了產品瑕疵、成本超支和進度延遲;由於複雜度,使列舉(還遠遠不是理解)所有可能的狀態變得十分困難,影響了產品的可靠性;由於函數的複雜度,函數調用變得困難,導致程序難以使用;由於結構性複雜度,程序難以在不產生副作用的情況下用新函數擴充;由於結構性複雜度,造成很多安全機制狀態上的不可見性。
複雜度不僅僅導致技術產生困難,還引發了很多管理上的問題。它使全面理解問題變得困難,從而妨礙了概念上的完整性;它使所有離散出口難以尋找和控制;它引起了大量學習和理解上的負擔,使開發慢慢演變成了一場災難。
一致性。並不是只有軟件工程師才面對複雜度問題。物理學家甚至在非常“基礎”的級別上,也會面對異常複雜的事物。不過,物理學家堅信,必定存在着某種通用原理,或者在夸克中,或者在統一場論中。愛因斯坦曾不斷地重申自然界一定存在着簡化的解釋,因爲上帝不是專橫武斷或反覆無常的。
軟件工程師卻無法從類似的信念中獲得安慰,他必須掌握的很多複雜度是隨心所欲、毫無規則可言的,來自若干必須遵循的人爲慣例和系統。它們隨接口的不同而改變,隨時間的推移而變化,而且,這些變化不是必需的,僅僅由於它們是不同的人—— 而非上帝—— 設計的結果。
許多情況下,因爲是開發最新的軟件,它必須遵循各種接口。另一些情況下,軟件的開發目標就是兼容性。在上述的所有情況中,很多複雜性來自保持與其他接口的一致方面,對軟件的任何再設計,都無法簡化這些複雜特性。
可變性。軟件實體經常會遭受到持續的變更壓力。當然,建築、汽車、計算機也是如此。不過,工業製造的產品在出廠之後不會經常地發生修改,它們會被後續模型所取代,或者必要更改會被整合到具有相同基本設計的後續產品系列中。汽車的更改十分罕見,計算機的現場調整有時發生。然而,與軟件的現場修改比起來,它們都要少很多。
其中的部分原因是因爲系統中的軟件包含了很多功能,而功能是最容易感受變更壓力的部分。另外的原因是因爲軟件可以很容易地進行修改—— 它是純粹思維活動的產物,可以無限擴展。日常生活中,建築有可能發生變化,但衆所周知,建築修改的成本很高,從而打消了那些想提出修改的人的念頭。
所有成功的軟件都會發生變更。現實工作中,經常發生兩種情況。當人們發現軟件很有用時,會在原有應用範圍的邊界,或者在超越邊界的情況下使用軟件。功能擴展的壓力主要來自那些喜歡基本功能,又對軟件提出了很多新用法的用戶們。
其次,軟件一定是在某種計算機硬件平臺上開發,成功軟件的生命期通常比當初開發軟件所用的計算機硬件平臺要長。即使不是更換計算機,也有可能是換新型號的磁盤、顯示器或者打印機。軟件必須與各種新生事物保持一致。
簡言之,軟件產品紮根於文化的母體中,如各種應用、用戶、自然及社會規律、計算機硬件等等。後者持續不斷地變化着,這些變化無情地強迫着軟件也隨之變化。
不可見性。軟件是不可見的和無法可視化的。例如,幾何抽象是強大的工具。建築平面圖能幫助建築師和客戶一起評估空間佈局、進出的運輸流量和各個角度的視覺效果。這樣,矛盾變得突出,遺漏的地方可以捕捉到。同樣,機械製圖、化學分子模型儘管是抽象模型,但都起了相同的作用。總之,都可以通過幾何抽象來捕獲物理存在的幾何特性。
軟件的客觀存在不具有空間的形體特徵。因此,沒有已有的幾何表達方式,就像陸地海洋有地圖,硅片有膜片圖,計算機有電路圖一樣。當我們試圖用圖形來描述軟件結構時,發現它不僅僅包含一個,而是很多相互關聯、重疊在一起的圖形。這些圖形可能代表控制流程、數據流、依賴關係、時間序列和名字空間的相互關係等等。它們通常不是有較少層次的扁平結構。實際上,在上述結構上建立概念控制的一種方法是強制將關聯分割,直到可以層次化一個或多個圖形。[2]
除去軟件結構上的限制和簡化方面的進展,軟件仍然保持着無法可視化的固有特性,從而剝奪了一些具有強大功能的概念工具的構造創意。這種缺憾不僅限制了個人的設計過程,也嚴重地阻礙了思路相互之間的交流。
以往解決次要困難的一些突破
如果回顧一下軟件領域中取得的最富有成效的三次進步,我們會發現每一次都是解決了軟件構建上的巨大困難,但是這些是次要困難,不是本質屬性,也不是主要困難。同樣,我們可以對每一次進步進行外推,來了解它們的固有限制。
高級語言。毋庸置疑,軟件生產率、可靠性和簡潔性上最有力的突破是使用高級語言編程。大多數觀察者相信開發生產率至少提高了5倍,同時可靠性、簡潔性和理解程度也大爲提高。
那麼,高級語言取得了哪些進展呢?它減輕了一些次要的軟件複雜度。抽象程序包含了很多概念上的要素:操作、數據類型、流程和相互通訊,而具體的機器語言程序則關心位、寄存器、條件、分支、通道、磁盤等等。高級語言所達到的抽象程度體現了抽象程序所需要的要素,避免了更低級的元素,它消除了並不是程序所固有的整個級別的複雜度。
高級語言最可能實現的是爲所有編程人員在抽象程序中提供想到的要素。可以肯定的是,我們思考數據結構、數據類型和操作的複雜程度穩固提高,只不過是以非常緩慢的速度。另外,程序開發方法越來越接近用戶的複雜度。
然而,對於較少使用那些複雜深奧語言要素的用戶,高級語言在某種程度上增加而不是減少了腦力勞動的負擔。
分時。大多數觀察者相信,分時在提高程序員的生產率和產品質量方面起到了很大作用,儘管它產生的進步不如高級語言。
分時解決了完全不同的困難,保證了及時性,從而使我們能維持對複雜度的一個總體把握。批處理編程的較長週轉時間意味着不可避免會遺忘一些細枝末節。如果我們停下編程,調用編譯程序或者執行程序,思維上的中斷使我們不得不重新進行思考,它在時間上的代價非常高昂。最嚴重的結果可能是失去對複雜系統的掌握。
較長的週轉時間和機器語言的複雜度一樣,是軟件開發過程的次要困難,而不是本質困難。這直接導致分時作用非常有限。主要效果縮短了系統的響應時間。隨着它接近於零,超過人類可以辨識的基本能力—— 大概100毫秒時,所獲得的好處就接近於零了。
統一編程環境。第一個集成開發環境—— Unix和Interlisp,現在已經得到了廣泛應用,並且由於整合的因素使生產率提高。爲什麼?
它們主要通過提供集成庫、統一文件格式、管道和過濾器,解決了共同使用程序的次要困難。這樣,概念性結構理論上的相互調用、提供輸入和互相使用,在現實中可以非常容易地實現。
因爲每個新工具可以通過標準格式在任何一個程序中應用,這種突破接着又激發整個工具庫的開發。
由於這些成功,環境開發是當今軟件工程研究的主要題目。我們將在下節討論期望達到的目標和限制。
銀彈的希望
現在,讓我們來討論一下當今可能作爲潛在銀彈的最先進的技術進步。它們各自針對什麼樣的問題?它們是屬於必要問題,或者依然是解決我們剩下的次要困難?它們是提供了創新,還是僅僅是增量改進?
Ada和其他高級編程語言。近來,最被吹捧的開發進展之一是編程語言Ada,一種20世紀80年代的高級語言。Ada實際上不僅僅反映了語言概念上的突破性進展,而且蘊涵了鼓勵現代設計和模塊化概念運用的重要特性。由於Ada採用的是抽象數據類型、層次結構的模塊化理念,所以Ada理念可能比語言本身更加先進。Ada使用設計來承載需求,作爲這一過程的自然產物,它可能過於豐富了。不過,這並不是致命的,因爲它的詞彙子集可以解決學習問題,硬件的進展能提供更高的MIPS(每秒百萬指令集),減少編譯的成本。軟件系統結構化的先進理念實際上非常好地利用了MIPS上的進展。20世紀60年代,曾在內存和循環成本上廣受譴責的操作系統,如今已被證明是一種能使用某些MIPS和廉價內存的非常優秀的系統。
然而,Ada仍然不是消滅軟件生產率怪獸的銀彈。畢竟,它只是另一種高級語言,這類語言最大的回報來自出現時的衝擊,它通過使用更加抽象的語句來開發,降低了機器的次要複雜度。一旦這些難題被解決,就只剩下非常少的問題了,解決剩餘部分的獲益必然也要少一些。
我預言,在以後的十年中,當Ada的效率被大家評估認可時,它會產生相當大的變化,但並不是因爲任何特別的語言特性,不是由於這些語言特性被合併在一起,也不是因爲Ada開發環境會不斷髮展進步。Ada的最大貢獻在於編程人員培訓方式的轉變,即對開發人員需要進行現代軟件設計技術培訓。
面向對象編程。軟件專業的一些學生堅持面向對象編程是當今若干新潮技術中最富有希望的。[3]我也是其中之一。達特茅斯的Mark Sherman提出,必須仔細地區別兩個不同的概念:抽象數據類型和層次化類型,後者也被稱爲類(class)。抽象數據類型的概念是指對象類型應該通過一個名稱、一系列合適的值和操作來定義,而不是理應被隱藏的存儲結構。抽象數據類型的例子是Ada包(以及私有類型)和Modula的模塊。
層次化類型,如Simula-67的類,是允許通用接口的定義可以被後續子類型精化的。這兩個概念是互不相干的—— 可以只有層次化,沒有數據隱藏;也可能是隻有數據隱藏,而沒有層次化。兩種概念都體現了軟件開發領域的進步。
它們的出現都消除了開發過程中的非本質困難,允許設計人員表達自己設計的內在特性,而不需要表達大量句法上的內容,這些內容並沒有添加新的信息。對於抽象數據類型和層次化類型,它們都是解決了高級別的次要困難並允許採用較高層次的表現形式來表達設計。
不過,這些提高僅僅能消除所有設計表達上的次要困難。軟件的內在問題是設計的複雜度,上述方法並沒有對它有任何的促進。除非我們現在的編程語言中,不必要的低層次類型說明佔據了軟件產品設計的90%,面向對象編程才能帶來數量級上的提高。對面向對象編程這顆“銀彈”,我深表懷疑。
人工智能。很多人期望人工智能上的進展可以給軟件生產率和質量帶來數量級上的增長,[4]但我不這樣認爲。究其原因,我們必須剖析“人工智能”意味着什麼,以及它是如何應用的。
Parnas澄清了術語上的混亂:
現在有兩種差異非常大的AI定義被廣泛使用。AI-1:使用計算機來解決以前只能通過人類智慧解決的問題。AI-2:使用啓發式或基於規則的特定編程技術。在這種方法中,對人類專家進行了研究,判斷他們解決方法的啓發性思維或者經驗法則……程序被設計成以人類解決問題的方式來運作。
第一種定義的意義容易發生變化……今天可能適合AI-1定義的程序,一旦我們瞭解了它的運行方式,理解了問題,就不再認爲它是人工智能……遺憾的是,我無法識別這個領域的特定知識體系……絕大多數工作是針對問題域的,我們需要一些抽象或者創造性來解決上述問題。[5]
我完全同意這種批評意見。語音識別技術與圖像識別技術的共同點非常少,它們又都與專家系統中應用的技術不同。例如,我覺得很難去發現圖像識別技術能給編程開發實踐帶來什麼樣的差異。同樣,語音識別也差不多—— 軟件開發上的困難是決定說什麼,而不是如何說。表達的簡化僅僅能提供少量的促進作用。
至於AI-2專家系統技術,應該用專門的章節來討論。
專家系統。人工智能領域最先進的、被最廣範使用的部分,是開發專家系統的技術。很多軟件科學家正非常努力地工作着,想把這種技術應用在軟件的開發環境中。[6]那麼它的概念是什麼,前景如何?
專家系統是包含歸納推論引擎和規則基礎的程序,它接收輸入數據和假設條件,通過從基礎規則推導邏輯結果,提出結論和建議,向用戶展示前因後果,並解釋最終的結果。推論引擎除了處理推理邏輯以外,通常還包括複雜邏輯或者概率數據和規則。
對於解決相同的問題,這種系統明顯比傳統的程序算法要先進很多。
● 推論引擎技術的開發獨立於應用程序,因此可以有多種用途。在該引擎上付出較大的力氣是很合理的。實際上,這種引擎技術非常先進;
● 基於應用的、可變更的部分,在基礎規則中以一種統一的風格編碼,並且爲規則基礎的開發、更改、測試和文檔化提供了若干工具。這實際上對一些應用程序本身的複雜度進行了系統化。
Edward Feigenbaum指出,這種系統的能力不是來自某種前所未有的推導機制,而是來自非常豐富的知識積累基礎,這一基礎更加精確地反映了現實世界。我認爲這種技術提供的最重要進步是具體應用的複雜度與程序本身相分離。
如何把它應用在軟件開發工作中呢?可以通過很多途徑:建議接口規則、制定測試策略、記錄各種bug產生的頻率和提供優化建議,等等。
例如,考慮一個虛構的測試顧問系統。在最根本的級別,診斷專家系統和飛行員的檢查列表很相似,對困難可能的成因提供基本建議。建立基礎規則時,可以依據更多的複雜問題徵兆報告,從而使這些建議更加精確。可以想象,一種調試輔助程序起初提供的是一般化建議,隨着基礎規則包括越來越多的系統結構信息,它產生的推測和推薦的測試也越來越準確。這種類型的專家系統可能與傳統系統徹底分離,系統中的規則基礎可能與相應的軟件產品具有相同的層次模塊化結構,因此當對產品進行模塊化修改時,診斷規則也能相應地進行模塊化修改。
產生診斷規則也是在爲模塊和系統編制測試用例集時必須完成的任務。如果它以一種適當通用的方式來完成,對規則採用一致的結構,擁有一個良好可用的推測引擎,事實上它就可以減少測試用例設計的總體工作量,並幫助整個軟件生命週期的維護和修改測試。同樣,我們可以推測其他的顧問專家系統—— 可能是它們中的某一些,或者是較簡單的系統—— 能夠用在軟件開發的其他部分。
在較早實現的用於軟件開發的專家顧問系統中存在着很多困難。在我們假設的例子中,一個關鍵的問題是尋找一種簡單的方法,能從軟件結構的技術說明中,自動或者半自動地產生診斷規則。另外,更加重要也是更加困難的任務是:尋覓能夠清晰表達,深刻理解來龍去脈,前因後果事情的自我分析專家;開發有效的技術—— 抽取專家們所瞭解的知識,把它們精煉成基礎規則。這項工作的工作量是知識獲取工作量的兩倍。構建專家系統的必要前提條件是擁有專家。
專家系統最強有力的貢獻是給缺乏經驗的開發人員提供服務,用最優秀的開發者的經驗和知識積累爲他們提供指導,這是非常大的貢獻。最優秀和一般的軟件工程實踐之間的差距是非常大的,可能比其他工程領域中的差距都要大,一種傳播優秀實踐的工具特別重要。
“自動”編程。近四十年,人們一直在預言和編寫有關“自動編程”的文字,從問題的一段陳述說明自動產生解決問題的程序。現在,仍有一些人期望這樣的技術能夠成爲下一個突破點。[7]
Parnas暗示這是一個用於魔咒的術語,本身的語義是不完整的,並斷言:
一句話,自動編程總是成爲一種熱情,使用現在並不可用的更高級語言編程的熱情。[8]
他指出,大多數情況下所給出的技術說明本質上是問題的解決方法,而不是問題自身。
可以找到一些例外情況。例如,數據發生器的開發技術就非常實用,並經常地用於排序程序中。一些微積分方程系統也允許直接描述問題。系統評估若干參數,從問題解決方案庫中進行選擇,生成合適的程序。
這樣的應用具有非常良好的特性:
● 問題通過相對較少的參數迅速地描述特徵;
● 存在很多已知的解決方案,提供了可供選擇的庫;
● 在給定問題參數的前提下,大量廣泛的分析爲選擇具體的解決技術提供了清晰的規則。
具有上述簡潔屬性的系統是一個例外,除此之外很難看到該方法能普及到更廣泛的尋常軟件系統,甚至難以想象這種突破如何能夠進行推廣。
圖形化編程。在軟件工程的博士論文中,一個很受歡迎的主題是圖形化或可視化編程,計算機圖形在軟件設計上的應用。[9]這種方法的推測部分來自VLSI芯片設計的類比,計算機圖形化在該設計中扮演了高生產力的角色。部分源於—— 人們將流程圖作爲一種理想的設計介質,併爲構建它們提供了很多功能強大的實用程序—— 這證實了圖形化的可行性。
不過,上述方法中至今還沒有出現任何令人信服,更不用說令人激動的進步。我確信將來也不會出現。
首先,如同我先前所提出的,流程圖是一種非常差勁的軟件結構表達方法。[10]實際上,它最好被視爲是Burks,von Neumann和Gold stine試圖爲他們所設計的計算機提供的一種當時迫切需要的高級控制語言。如今的流程圖已經變得複雜了,一張圖有若干頁,有很多連接結點,這種表現形式實在令人同情。流程圖已經被證明是完全不必要的設計工具—— 程序員是在開發之後,而不是之前繪製描述程序的流程圖。
其次,現在的屏幕非常小,就像素級別,無法同時表現軟件圖形的所有正式、詳細的範圍和細節。現在所謂 “類似桌面”的工作站實際上像是“飛機坐艙座椅”。在飛機上任何坐在兩個肥胖乘客之間,反覆挪動一大兜文件的人都會意識到這中間的差別—— 每次只能看到很少的內容。真正的桌面提供了很多文件的總覽,讓大家可以隨意地使用它們。此外,當人們的創造力一陣陣地湧現時,開發人員大多數都會捨棄工作臺,使用空間更爲廣闊的地板。要使我們面對的工作空間滿足軟件開發工作的需要,硬件技術必須進一步發展。
更加基本的是,如同我們上面所討論的,軟件非常難以可視化。即使用圖形表達出了流程圖、變量範圍嵌套情況、變量交叉引用、數據流和層次化數據結構等等,也只是表達了某個方面,就像盲人摸象一樣。如果我們把很多相關的視圖疊加在所產生的圖形上,那麼很難再抽取出全局的總體視圖。對VLSI芯片設計方法的類推是一種誤導—— 芯片設計是對兩維對象的層次設計,幾何特性反映了它的本質特性,而軟件系統不是這樣。
程序驗證。現代編程的許多工作是測試和修復bug。是否有可能出現銀彈,能夠在系統設計階段、源代碼階段就消除bug?是否可以在大量工作被投入實現和測試之前,通過採用證實設計正確性的“深奧”策略,徹底提高軟件的生產率和產品的可靠性?
我並不認爲這裏能找到魔法。程序驗證的確是很先進的概念,它對安全操作系統內核等這類應用是非常重要的。不過,這項技術並不能保證節約勞動力。驗證要求如此多的工作量,最終卻只有少量的程序能夠真正得到驗證。
程序驗證並不意味着零缺陷的程序。這裏也沒有什麼魔術,數學驗證仍然可能是有錯誤的。因此,儘管驗證可能減少程序測試的工作量,卻不能省略程序測試。
更嚴肅地說,即使完美的程序驗證也只能建立滿足技術說明的程序。這時,軟件工作中最困難的部分已經接近完成,形成了完整和一致的說明。開發程序的一些必要工作實際上已經變成了對技術規格說明進行的測試。
環境和工具。向更好的編程開發環境研究中投入,我們可以期待得到多少回報呢?人的本能反應是首先着手解決高回報的問題:層次化文件系統,統一文件格式以獲得一致的編程接口和通用工具等。特定語言的智能化編輯器在現實中還沒有得到廣泛應用,不過它們最有希望實現的是消除語法錯誤和簡單的語義錯誤。
開發環境上,現在已經實現的最大成果可能是集成數據庫的使用,用來跟蹤大量的開發細節,供每個程序員精確地查閱信息,並在整個團隊協作開發中保持最新的狀態。
顯然,這樣的工作是非常有價值的,它能帶來軟件生產率和可靠性方面的一些提高。但是,由於自身的特性,目前它的回報應該很有限。
工作站。隨着工作站的處理能力和內存容量的穩固和快速提高,我們能期望在軟件領域取得多大的收穫呢?有多少MIPS可供自由使用呢?現在的運算速度已經可以完全滿足程序編制和文檔書寫的需要了。編譯還需要一些提高,不過一旦機器運算速度提高十倍,程序開發人員的思考活動將成爲日常工作的主要活動。實際上,這已經是現在的情況了。
我們當然歡迎更加強大的工作站,但是不能期望有魔術般的提高。
針對概念上根本問題的頗具前途的方法
雖然現在軟件上沒有技術上的突破能夠預示我們可以取得像在硬件領域上一樣的進展,但在現實的軟件領域中,既有大量優秀的工作,也有不引人注意的平穩進步。
所有針對軟件開發過程中次要困難的技術工作基本上能表達成以下的生產率公式:
任務時間=(頻率)i×(時間)i
如果和我所認爲的一樣,工作的創造性部分佔據了大部分時間,那些僅僅是表達概念的活動就並不能在很大程度上影響生產率。
因此,我們必須考慮那些解決軟件上必要困難的活動—— 即,準確地表達複雜概念結構。幸運的是,其中的一些非常有希望。
購買和自行開發。構建軟件 最可能的徹底解決方案是不開發任何軟件。
情況每一天都有些好轉,越來越多的軟件提供商爲各種眼花繚亂的應用程序提供了質量更好、數量更多的軟件產品。當我們的軟件工程師正忙於生產方法論時,個人計算機的驚天動地的變化爲軟件創造了廣闊的市場。每個報攤上都有大量的月刊,根據機器的類型,刊登着從幾美元到幾百美元的各種產品的廣告和評論。更多專業廠商爲工作站和Unix市場提供了很多非常有競爭力的產品,甚至很多工具軟件和開發環境軟件都可以隨時購買使用。對於獨立的軟件模塊市場,我已在其他地方提出了一些建議。
以上提到的任何軟件,購買都比重新開發要低廉一些。即使支付100 000美元,購買的軟件也僅僅是一個人年的成本。而且軟件是立即可用的!至少對於現有的產品,對於那些專注於該領域開發者的成果而言,它們是可以立刻投入使用的。並且,它們往往配備了書寫良好的文檔,在某種程度上比自行開發的軟件維護得更加完備。
我相信,這個大衆市場將是軟件工程領域意義最深遠的開發方向。軟件成本一直是開發的而非複製的成本,所以,即使只在少數使用者之間實現共享,也能在很大程度上減少每個用戶的成本。另一種看法是使用軟件系統的n個拷貝,將會使開發人員的生產率有效地提高n倍。這是一個領域和行業範圍的提高。
當然,關鍵的問題還是可用性。是否可以在自己的開發工作中使用商用的軟件包?這裏,有一個令人喫驚的問題。在20世紀50年代到20世紀60年代期間,一個接一個的研究顯示,用戶不會在工資系統、物流控制、賬務處理等系統中使用商用軟件包。需求往往過於專業,不同情況之間的差別太大。在20世紀80年代,我們發現這些軟件包的需求大爲增加,並得到了大規模的使用。是什麼導致了這樣的變化呢?
並不是軟件包發生了變化。它們可能比以前更加通用和更加定製化一些,但並不太多。同樣,也不是應用發生了變化。即使有,今天的商業和學術上的需要也比20年以前更加不同和複雜。
重大的變化在於計算機硬件/軟件成本比率。在1960年,200萬美元機器的購買者覺得他可以爲定製的薪資系統支付250 000美元,而這樣的系統很容易慢慢地變得不適用。現在,對50 000美元的辦公室機器購買者而言,很難想象能爲定製薪資系統再支付費用。因此,他們把上述系統的模塊進行調整,添加到可用的軟件包中。計算機現在如此的普遍,上述的改編和調整是發展的必然結果。
對於我的上述觀點也存在一些戲劇性的例外—— 軟件包的通用化方面並沒有發生什麼變化,如電子表格和簡單的數據庫系統。這些強大的工具出現得如此之晚並如此醒目,產生無數的應用,而其中的一些是非正統的。大量的文章甚至書籍講述瞭如何使用電子表格應付很多意想不到的問題。原先作爲客戶程序,使用Cobol或者報表生成程序編寫的大量應用,如今已經被這些工具所取代。
現在很多用戶天天操作計算機,使用着各種各樣的應用程序,但並不編寫代碼。事實上,他們中很多人無法爲自己的計算機編寫任何程序,不過他們非常熟練地使用計算機來解決新問題。
我認爲,對於現在的很多組織機構來說,最有效的軟件生產率策略是在生產一線配備很多個人計算機,安裝好通用的書寫、作圖、文件管理和電子表格程序以及配備能熟練使用它們的人員,並且把這些人員分配到各個崗位。類似的策略—— 通用的數學和統計軟件包以及一些簡單的編程能力,同樣適用於很多實驗室的科學工作者。
需求精煉和快速原型。開發軟件系統的過程中,最困難的部分是確切地決定搭建什麼樣的系統。概念性工作中,沒有其他任何一個部分比確定詳細的技術需求更加困難。詳細的需求包括了所有的人機界面,與機器和其他軟件系統的接口。如果失誤了,需求工作對系統的影響比其他任何一個部分都大,當然糾正需求的困難也比其他任何一個部分都要大。
因此,軟件開發人員爲客戶所承擔的最重要的職能不斷重複地抽取和細化產品的需求。事實上,客戶不知道自己需要什麼。他們通常不知道哪些問題是必須回答的。並且,連必須確定的問題細節常常根本不予考慮,甚至只是簡單地回答—— “開發一個類似於我們已有的手工信息處理過程的新軟件系統”—— 實際上都過於簡單。客戶決不會僅僅只要求這些。複雜的軟件系統往往是活動的、變化的系統。活動的動態部分是很難想象的。所以,在計劃任何軟件活動時,要讓客戶和設計人員之間進行多次廣泛的交流溝通,並將其作爲系統定義的一部分,這是非常必要的。
這裏,我將向前多走一步,下一個定論。在嘗試和開發一些客戶定製的系統之前,即使他們和軟件工程師一起工作,想要完整、精確、正確地抽取現代軟件產品的需求—— 這,實際上也是不可能的。
因此,現在的技術中最有希望的,並且解決了軟件的根本而非次要問題的技術,是開發作爲迭代需求過程的一部分—— 快速原型化系統的方法和工具。
軟件系統的快速原型對重要的系統界面進行模擬,並演示待開發系統的主要功能。同時,原型不必受到相同硬件速度、規模或者成本約束的限制。原型通常展示了應用程序的功能主線,但不處理任何如無效輸入、退出清除等異常情況。原型的目的是明確實際的概念結構,使客戶可以測試一致性和可用性。
現在的軟件開發流程是基於如下假設的—— 事先明確地闡述系統,爲系統開發競標,實際進行開發,最後安裝。我認爲這種假設根本上就是不正確的,很多軟件問題就來自這種謬誤。因此,如果不進行徹底地調整,就無法消除那些軟件問題。其中,一種改進是對產品和原型不斷反覆地進行開發和規格化。
增量開發—— 增長,而非搭建系統。我現在還記得,在1958年,當聽到一個朋友提及搭建(building),而不是編寫(writing)系統時,我所受到的震動。一瞬間,我的整個軟件開發流程的視野開闊了。這種暗喻是非常有力和精確的。現在,我們已經理解軟件開發是如何類似於其他的建造過程,並開始隨意地使用其他的暗喻,如規格說明、構件裝備、腳手架(測試平臺)(specifications, assembly of components, and scaffolding)。
暗喻“搭建系統”的使用已經有些超出了它的有效期限,是重新換一種表達方式的時候了。如果現在的開發情況與我所考慮的一樣,那些概念性的結構非常複雜,以至於難以事先精確地說明和零缺陷地開發,我們必須採用徹底不同的方法。
讓我們轉向自然界,研究一下生物的複雜性,而不是人們的僵硬工作。我們會發現它們的複雜程度令我們敬畏。光是大腦本身,就比任何對它的描述都要複雜,比任何的模擬仿真都要強大,它的多樣性、自我保護和自我更新能力異常豐富和有力。其中的祕密就是逐步發育成長,而不是一次性搭建。
所以,我們的軟件系統也必須如此。很多年前,Harlan Mills建議所有軟件系統都應該以增量的方式開發。[11]即,首先系統應該能夠運行,即使未完成任何有用功能,只能正確調用一系列僞子系統。接着,系統一點一點被充實,子系統輪流被開發,或者是在更低的層次調用程序、模塊、子系統的佔位符(僞程序)等。
從我在軟件工程試驗班上開始推動這種方法起,其效果就不可思議。在過去幾十年中,沒有任何方法和技術能如此徹底地改變我自己的實踐。這種方法迫切地要求自上而下設計,因爲它本身是一種自上而下增長的軟件。增量化開發使逆向跟蹤很方便,並非常容易進行原型開發。每一項新增功能,以及針對更加複雜數據或環境的新模塊,從已經規劃的系統中有機地增長。
這種開發模式對士氣的推動是令人震驚的。當一個可運行系統—— 即使是非常簡單的系統出現時,開發人員的熱情就迸發出來了。當一個新圖形軟件系統的第一幅圖案出現在屏幕上時,即使是一個簡單的長方形,工作的動力也會成倍地增長。在開發過程的每個階段,總有可運行的系統。我發現開發團隊可以在4個月內,培育(grow)出比搭建(building)複雜得多的系統。
大型項目同樣可以得到與我所參與的小型項目相同的好處。[12]
卓越的設計人員。關鍵的問題是如何提高軟件行業的核心,一如既往的是—— 人員。
我們可以通過遵循優秀而不是拙劣的實踐,來得到良好的設計。優秀的設計是可以傳授的。程序員的周圍往往是最出色的人員,因此他們可以學習到良好的實踐。因此,美國的重大策略是頒佈各種優秀的現代實踐。新課程、新文獻,像軟件工程研究所(SEI)等新機構的出現都是爲了把我們的實踐從不足提升到更高的水平。其正確性是勿庸置疑的。
不過,我不認爲我們可以用相同的方式取得下一次的進步。低劣設計和良好設計之間的區別可能在於設計方法的完善性,而良好設計和卓越設計之間的區別肯定不是如此。卓越設計來自卓越的設計人員。軟件開發是一個創造性的過程。完備的方法學可以培養和釋放創造性的思維,但它無法孕育或激發創造性的過程。
其中的差異並不小—— 就像薩列裏和莫扎特。一個接一個的研究顯示,非常卓越的設計者產生的成果更快、更小、更簡單、更乾淨,實現的代價更少。卓越和一般之間的差異接近於一個數量級。
簡單地回顧一下,儘管很多傑出、實用的軟件系統是由很多人共同設計開發的,但是那些激動人心、擁有廣大熱情愛好者的產品往往是一個或者少數偉大設計師們的思想。考慮一下Unix、APL、Pascal、Modula、Smalltalk的界面,甚至Fortran;與之對應的產品是Cobol、PL/I、Algol、MVS/370和MS-DOS(圖16-1)。
YES NO
Unix Cobol
APL PL/I
Pascal Algol
Modula MVS/370
Smalltalk MS-DOS
Fortran
圖16-1 激動人心的產品
因此,儘管我強烈地支持現在的技術轉移和開發技能的傳授,但我認爲我們可以做的最重要工作是尋求培養卓越設計人員的途徑。
沒有任何軟件機構可以忽視這項挑戰。儘管公司可能缺少良好的管理人員,但決不會比良好設計人員的需求更加迫切,而卓越的管理人員和設計人員都是非常缺乏的。大多數機構花費了大量的時間和精力來尋找和培養管理人員,但據我所知,它們中間沒有任何一家在尋求和培育傑出的設計人員上投入相同的資源,而產品的技術特色最終依賴於這些設計人員。
我的第一項建議是每個軟件機構必須決定和表明,傑出的設計人員和卓越的管理人員一樣重要,他們應該得到相同的培養和回報。不僅僅是薪資,還包括各個方面的認可—— 辦公室規模、傢俱、個人的設備、差旅費用和人員支持等—— 必須完全一致。
如何培養傑出的設計人員呢?限於篇幅,不允許進行較長的介紹,但有些步驟是顯而易見的。
● 儘可能早地、有系統地識別頂級的設計人員,最好的通常不是最有經驗的人員;
● 爲設計人員指派一位職業導師,負責他們技術方面的成長,仔細地爲他們規劃職業生涯;
● 爲每個方面制定和維護一份職業計劃,包括與設計大師的、經過仔細挑選的學習過程,正式的高級教育和短期的課程—— 所有這些都穿插在設計和技術領導能力的培養安排中;
● 爲成長中的設計人員提供相互交流和激勵的機會。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章