名不副實的 “軟體工程”

餘晟發表於2016-03-09

  本文中,作者從三個方面來論證教材中的 “軟體工程” 和實際中的 “軟體工程” 有何不同。鑑於此,作者認為或許實打實地寫程式碼、做系統才能幫助學習者進一步增進對於 “軟體工程” 的理解。本文作者 餘晟,微信公眾號  餘晟以為(ID: yurii-says)。

  按:本文的很多觀點來自與七牛雲端儲存首席架構師道哥(李道兵)的討論,在這裡對道哥表示感謝。

  高校的計算機教育與時代脫節,這已經成為大家的共識。如果要問哪些課程脫節最嚴重,我的答案是 “軟體工程”。其他的課程雖然也有脫節,但多少有點用處:程式語言雖然不教怎麼把程式寫漂亮,至少教了語法;網路課程雖然沒有形象直觀的展示,畢竟通訊協議還在使用;資料庫課程不講資料庫的安裝和調優,關係代數理論仍然是不少問題的原型;資料結構與演算法即便看起來與開發沒有直接關聯,有了概念總不會吃虧……

  只有軟體工程,是例外。顧名思義,“軟體工程” 講的應當是把軟體開發出來的學問。所以,它是名不副實的:如果你按照 “軟體工程” 教的去做,多半開發不出來軟體,至少開發不出好的軟體。一方面大量畢業生不會寫程式、寫不出好程式,另一方面合格的 “軟體工程師” 奇缺,對這種怪異的景象,名不副實的 “軟體工程” 功不可沒。

  不信?我在寫作本文之前專門查閱瞭如今流行的 “軟體工程” 教材,共同的大綱如下:

  • 可行性研究

  • 形式化說明

  • 軟體研發模型

  • 設計-實現-測試

  • 物件導向分析、方法、實現

  • 軟體生命週期

  • 專案管理 

  如今真正做過軟體開發的人覺得這些名詞和自己的開發有多大的關係?就我的調查,大多數人的答案是 “沒多大關係”。但是大多數人的日常工作,分明又是 “軟體工程”。那麼,此 “軟體工程” 和彼 “軟體工程” 為何不一樣,問題到底出在哪裡呢?按照我的總結,主要有以下幾個方面。

  教材上的 “軟體工程” 是理論先行的,現實的 “軟體工程” 是實踐先行的。

  理論先行的潛意識,就是把現實世界削刪之後裝到理想的世界裡,受到預定義的規範和定理的支配。早期的軟體開發確實可以嚴格遵循這種套路,比如銀行的業務就與關聯式資料庫理論嚴密契合,所以要做的是直接對映到複雜(完美)的實體-關係中,用資料庫表加以實現。所以,重要的問題是 “分析”,也就是找到對應的理論模型,然後進行設計和開發。

  現代軟體開發的環境則有很大不同。軟體需要解決的不再是 “經典問題”,而是複雜的現實問題,這類問題背後根本沒有統一的抽象模型。比如當前熱門的 NoSQL,出現的原因是大家發現很多問題 “不是關係模型可以解決的”。然而 “不是關係模型” 的模型到底是什麼模型,根本沒有理論答案,所有人都在不斷摸索和總結,雖然有了一些中間階段的解決方案,但各個流派至今也沒有統一。既然沒有理論,就只能在實踐中不斷思考、摸索、總結,並及時關心瞭解業界的最新經驗。很不幸,這樣的工作方式並不包含在 “軟體工程” 的教材裡。

  “實踐先行” 的另一個表現是,必須意識到軟體執行的環境是不可靠的——使用者是不會按照說明書的嚴格規定來使用軟體的,安裝軟體的作業系統可能缺乏某個類庫,軟體執行的硬體環境往往並不可靠…… 我們說一款軟體(或者一套系統)工程做得好,往往就是肯定它們已經預先考慮到了各種異常情況,並且都準備了適當的應對預案。能夠在開發之前思考各種異常並設計應對方案(“為失敗而設計”),這是軟體工程師的基本素質。不幸的是,“軟體工程” 教材也沒有教授這樣的素質。

  教材上的 “軟體工程” 是單機環境的,現實的 “軟體工程” 是網路環境的。

  如果你仔細留意就會發現,在 “軟體工程” 的教材裡,計算機的資源常常被假設為無限的,它們給了開發者披堅執銳的勇氣。即便有 “工程” 相關的考慮,往往也只是針對這個流程的思考而已。比如常見的圖書管理系統,幾十萬幾百萬圖書的資訊雖然人工管理起來無比麻煩,計算機卻異常簡單,根本不用考慮記憶體、資料庫、硬碟、處理速度的限制,所以這些因素大可在抽象思考的過程中忽略。自然而然的,“軟體工程” 只需要關心專案管理即可。

  但是有過現實開發經驗的人都知道,如今單機的處理能力已經遠遠不能應對計算機要解決的問題。比如網站的登入服務,從模型上說與圖書管理系統差不了多少,甚至更簡單。但是使用者量的飛漲可能迅速超過了單表、單庫能承受的極限,大量使用者的集中登入會大量消耗頻寬和計算資源,登入資訊的儲存很可能超過單臺機器的記憶體容量,這還不包括避免會話保持伺服器發生異常影響使用者體驗而必須準備的會話遷移…… 

  在移動網際網路推動導致資料和計算量爆炸式增長的今天,幾乎所有的程式設計師都必須從一開始就擺脫單機的思維,掌握這種從邏輯服務、抽象資源及其限制的角度出發看待和解決問題的思考和工作方法。不幸的是,這樣的思維方式,教材上的 “軟體工程” 也沒有涉及。結果就是大量系統只能滿足於小打小鬧,業務稍微增長就無力應對了。

  教材上的 “軟體工程” 側重的是開發,實際的 “軟體工程” 兼顧開發與維護。

  如果你仔細觀察就會發現,教材上的 “軟體工程” 無論怎麼強調反饋和改進,總是把大部分篇幅放在了 “開發” 上。只要軟體的分析準確、設計得當、開發規範,交付之後就解決了大部分的問題。至於軟體執行中會遇到什麼問題,那是運維的事情。軟體的缺陷如何管理,那是下次升級要解決的問題。總而言之,軟體交付之後,事情基本就告一段落了。

  但是實際的軟體開發中,“交付” 的更準確的說法只是 “第一次交付”,後續還有若干次交付。尤其在時間緊急的專案中,根本不可能有那麼多時間去分析和設計,只能保證幾個主要的功能執行正常。之後再投入精力去改進和完善這個 “半成品”。對優秀的軟體工程師來說,這種權衡能力是非常重要的。不幸的是很多人都不具備這種能力,結果要麼是過度設計導致遲遲不能交付,要麼是毫無設計和規劃導致改進和完善困難重重。可惜,這種權衡的能力,教材上的 “軟體工程” 並沒有涉及。

  現代軟體開發的另一個特點是,開發的結果不再是一次定型的 “軟體”,而是需要不斷維護和改造的 “系統”。系統既要根據實際的執行環境不斷調優,又要持續根據使用者(而不是一錘子買賣的 “客戶”)的反饋迅速改進甚至是調轉方向。所以優秀的軟體工程師一方面會關心繫統的執行狀況,不會一股腦扔給運維人員去解決,另一方面還得設計出柔韌而健壯的系統架構,並且有勇氣和耐心持續投入精力去維護和改造,有時候甚至要毫不猶豫地推倒重來。很可惜,這種 “持續打磨” 的工作模式,教材上的 “軟體工程” 也沒有涉及。

  總的來說,現在高校的 “軟體工程” 教材其實與 “工程” 沒什麼聯絡。當然這也情有可原,因為現代軟體開發已經脫離了 “電腦科學” 的籠罩,依靠自身的經驗和實踐形成了一門全新的學問。然而無論是教材的編寫者,還是課程的教授者,習慣和思維都還停留在 “電腦科學” 的時代,並沒有多少實際開發的經驗,也沒有重視實際的開發。不幸的是,教師和教材可以停留在過去,學生卻必須在現在的時代工作。所以,如果你現在正在高校學習計算機的知識,不妨實打實地寫程式碼、做系統。如果持之以恆,你對 “軟體工程” 的理解將會遠遠超過《軟體工程》。

相關文章