Bertrand Meyer 和 Bill Venners 討論軟體品質不斷攀升的重要性、市場對軟體品質的影響以及軟體複雜性的挑戰。
Bertrand Meyer 是同時活躍於學術和商業二界的軟體先驅。他目前擔任瑞士理工學院的軟體工程協會主席。他撰寫了數量浩繁的論文和書籍,如經典的《物件導向軟體構造》( Prentice 出版社, 1994 , 2000 )。 1985 年,他創立了互動軟體工程公司。公司目前已經更名為 Eiffel 軟體公司,提供基於 Eiffel 語言的軟體工具、培訓和諮詢業務。
2003 年 9 月 28 日, Bill Venners 對 Bertrand Meyer 做了電話訪談。在這次訪談(內容將在 Artima.com 分多次公布)中, Meyer 對許多有關軟體的問題作了鞭辟入裡的論述,如軟體品質、軟體複雜性、契約設計以及測試驅動型開發等。在這個最開始的部分中, Meyer 論述了軟體品質不斷攀升的重要性、市場對於軟體品質的影響以及軟體複雜性的挑戰。
軟體品質的重要性
你在 2001 年 InformIT 對你的一次訪談中講到:“當前的形勢很好,以至在軟體界,品質已經能成為很多人的話題。它將日益成為人們最主要的議題。”這是為什麼呢?
電腦的應用已經遍及社會生活的方方面面,因此,品質低下的軟體是不被接受的。軟體業飛速發展,我們對軟體的依賴性也日益增加。到了今天,我們必須面對一些由來已久但不被重視的問題。
Alan Perlis 在麻省理工學院的一本教材—— Abelson 和 Sussman 合著的《電腦編程的結構和解析》——的序言中有一段頗具啟發性的話。他寫到:
我認為電腦科學至關重要的是保持“計算”的趣味性。在它剛興起的時候,它的確非常有趣。當然,使用者也常常為之買單;過了一段時間,我們開始認真對待使用者的抱怨。於是我們認為自己應該為電腦成功地、無錯地完美運行負責。我卻不這樣看。我認為我們應該為之努力的是延伸電腦的功能,讓它們有新的發展方向,讓我們的屋子裡充滿趣味。
一種典型的態度是:“你完全可以相信,我們能做任何我們想做的事情。如果有什麼問題,我們會修正它。”但這恰恰已不再可能。人們對軟體的依賴性如此之大,以至他們根本不可能接受這樣的態度。在 .com 時代( 1996 到 2000 年)的早些時候,這樣的觀念還勉強能站住腳,但到 1998 年已不可能。這種在過去可以讓人們輕易接受的搭便車態度,如今已無立足之地。
2003 年 5 月,《哈佛商業評論》發表了 Nicholas Carr 的文章《 IT 麻木不仁》,文章指出: IT 沒有兌現它的承諾。這發出了一個明顯的訊號:整個社會要求我們對自己的承諾要有比過去高得多的嚴肅態度。儘管在目前看來,我們似乎還能(不負責任地)搭便車,但這樣的時代將很快終結。人們越來越關心我們的所作所為,關心自己的支出是否可以得到回報。這一些的核心就是品質。
市場對軟體品質的影響
你的論文《可信任組件的巨大挑戰》中談到:“品質提升的動機是存在的,但它僅僅被允許到達這樣的水平:可以存在在市場上不會危機到產品有效性的缺陷。大多數管理者認為超出此範圍的品質提升措施只能產生急劇下降的投資回報。”那麼市場到底是怎麼影響軟體品質的?
市場力量對於軟體品質的影響,既有正面的,也有負面的。這差不多和雷根經濟政策時期流行的拉弗曲線理論類似。我不是經濟學家,也聽說這個理論目前已不足信,因此我沒有暗示拉弗曲線在經濟學上根本正確的意思。不過,拉弗曲線告訴我們,如果你按 0% 水平對人們徵稅,那麼國家會遭受災難,因為它得不到任何收入;如果提高到 100% (不能再高的水平),則人們不能獲得任何收入,因此他們將拒絕工作,這樣國家也得不到任何收入。這是一種相當單純的討論。儘管拉弗曲線在這一點上具有相當明顯的合理性,但我無疑確定它在經濟學上的正確性和精確性。不過作為一個類比,它可以很好地描述市場力量對於軟體品質的影響力。
如果你的軟體產品品質非常糟糕,你將得不到任何收入,因為沒人願意買它。相反,如果你窮盡時日、耗盡人力、物力和財力去構造絕對完美的軟體,那麼其過長的開發週期和高昂的成本將決定你必然退出市場。你不是錯過市場機遇就是最終耗盡所有資源。所以,置身軟體行業的人們都要努力尋找一個難以把握的平衡點:產品要足夠好,以至它不會在諸如評估等階段就馬上被否定;同時也不追求十全十美、精雕細琢,否則會囿於時間和金錢而無法達到目的。
複雜性的挑戰
你的大作《物件導向軟體構造》中講過:“可靠性,或許還有軟體品質,的唯一最大敵人通常是複雜性。”對此你能展開談談嗎?
我認為我們的軟體中存在一些到達人類想象極限的複雜部分,某些時候,這些部分讓我們一敗塗地。構建大型的、讓人滿意的系統的唯一辦法是不要持續地複雜化,必須保持對複雜性的控制力。比如 Windows XP 系統包含大約 4 千 5 百萬行代碼,這完全不是單獨某個人可以理解甚至想象的。如果要想保持對它們的控制,或者說還希望哪怕有一點點可靠性的話,唯一的辦法就是剔除沒必要複雜的部分,而想盡辦法保持對其餘部分的複雜性控制。
複雜性控制在 Eiffel 語言編程中是一個基本原則。 Eiffel 對人們作複雜、高難度開發大有協助。當然,你可以用 Eiffel 語言構建簡單的、困難適度的系統,甚至可以比使用其他工具做得更好,但當問題複雜到超過你的意願,你沒辦法控制其複雜性的時候, Eiffel 才會真正大放異彩。例如,它的基本原則之一就是對對象模組性和隱藏資訊要有相應的嚴格規定。在很多別的語言中,你能找到取得隱藏資訊的簡單辦法,但 Eiffel 中是不存在的。一開始,這些嚴格規則可能會激怒程式員,因為他們無法幹自己想做的事情,或者要寫更多的代碼才能達到目的。但當你需要拓展你原來的設計時,這些規則就成了避免大禍的強大衛士。
比如,在目前很多的物件導向語言中,儘管有一些限制,但你可以直接給一個對象的欄位賦值: x.a = 1 ,其中 x 是一個對象, a 是它的一個欄位。任何一個有近代方法論和對象技術基礎的人都明白為什麼這是錯誤的。幾乎每個人都會說:“的確是錯誤的,但大多數情況下我不會在意它。我當然知道我在幹嘛。它們是我的對象和類,我應該控制它們所有的提供者,所以你不要來煩我。不要強迫我額外寫些代碼去封裝對欄位 a 的修改過程。”表面看,他們是對的。短期內,小範圍情況下,它沒有問題。有誰會在意它呢?
但直接賦值這樣一個典型的小問題在你有上萬、十萬甚至百萬行代碼、有成千上萬個類,很多人蔘與一個項目,項目經曆很多變動、大量修改,並且需要面向不同平台的時候,會將事情帶入一個完全不同的方向。像對象欄位直接賦值這類問題,將徹底攪亂整個架構。最終,一個小問題要帶來一個大麻煩。
如此一個小問題,你完全可以很容易在原始碼中修正它。你僅僅需要像 Eiffel 語言那樣禁止對對象欄位的直接存取,轉而必須在對完成這項工作的簡單過程的封裝基礎上進行——當然這樣的過程可能還需要一些契約。這是一個很容易消滅在萌芽階段的問題,但如果你不這樣做,它將會茁壯成長,最後置你於死地。
另外一個例子是重載:在同一個類中定義相同名字(的方法)去實現不同的操作。我知道對於這個問題是有爭議的。人們已經被洗腦,堅信重載是一個非常好的東西,但本質上,它是危險的,並不是個好東西。和對象欄位直接賦值一樣,現在的各種語言都支援重載。人們編寫的各種庫中,重載泛濫,用一個名字(的方法)去實現許多不同操作。表面上,它短期內有其便利性,但長遠來看,則付出了複雜性上升的代價,因為你必須搞清楚不同操作中每個變數的確切含義。其實,對象技術(當然還包括 Eiffel )中的動態綁定機制完全能提供人們想要的、比重載更好的靈活性。
所以說,有很多例子證明,如果在程式設計語言設計時謹慎一些,就可以大大趨近複雜性控制的目標。這可能有時候也人們為什麼不相信我們有關 Eiffel 的承諾的原因。 Eiffel 的使用是非常簡單的;我們公布的例子也很簡單,但其原因並不在於問題本身簡單,而是我們的解決方案簡單。 Eiffel 其實是一個剝離人為的複雜並找到常常隱藏起來的、本質上的簡單性的工具。但我們現在發現人們有時候並不相信這一點,不相信有簡單的解決方案。他們認為不是我們隱藏了某些東西,就是這種語言和這些方法並不能真正解決軟體開發中的實際問題,因為他們相信就是應該更複雜些。有如此一種可惡的陳詞濫調:“如果它好得不像是真的,那麼就必然不是真的。”這可能是人類有史以來最愚蠢的說法。很多人都有這種論調,但在 Eiffel 面前,它恰恰就錯了。只要你使用正確的工具去解決問題,你就可以去除不必要的複雜並找到隱藏的、本質的簡單。
任何一個正在構建大型系統的人,天天面對的中心議題就是:如何剔除不必要的、人為的、自找的複雜部分,並控制好剩下的、無可逃避的複雜性。在這個問題上,繼承、契約、泛型以及物件導向開發等思想一般都可以——特別是 Eiffel ——發揮重要作用。
根據我的理解,你應該是在論述兩件事情:去除不必要的複雜性和處理必然的複雜性。我可以找到一些工具,如物件導向技術和語言,協助我們處理必然的複雜性。但是工具如何協助我們去除自找的複雜性呢?你所說“找出複雜背後的簡單”是什麼意思?
我們來看現在的一些作業系統。例如,人們猛烈抨擊 Windows 的複雜性,但我並不認為其他競爭者做得更好。人們並沒有攻擊任何廠商的需要,但是很明顯,有些系統的確顯得過於混亂。如果重新徹底地審視人們提到的某些問題,的確可以設計出更好的架構。但是從另一方面來說,一個作業系統的複雜性又是無法避免的。 Windows XP 、 RedHat Linux 和 Solaris 都必須處理 Unicode ,必須為上百種語言提供使用者介面。特別是 Windows ,它必須相容大量廠商生產的難以計數的不同裝置。這就不是學術界批判的那種自找的複雜性。在現實世界中,我們不得不面對外界強加給我們的各種要求。因此,複雜性可以分為兩類:必然的複雜性,它要求我們必須通過最佳化組織、分析隱藏資訊和模組化等手段找到辦法來處理;另一類是人為的複雜性,我們應該通過簡化要解決的問題來消除之。