軟體工程Team 專案Alpha版本已基本完成,我們的項目是一個Web UI設計——Xueba線上學習網站。團隊在整個項目中應用了C#、ASP.NET、SQL等語言,為這個項目付出了極大的努力。
在項目即將發布的欣喜時刻,我們閱讀了老師推薦的一些部落格、論文與書籍,對軟體工程整體的概念與理論也有了一些新的認識。我就“沒有銀彈”、“瀑布模型”、“大泥球”、“教堂與集市”、“敏捷開發方法”等文章結合自己參與的Team 專案來總結一下理解與心得。
我們對Silver Bullet這個概念都不陌生。能夠幹掉幾乎無敵的狼人的銀色子彈,如果用在軟體項目開發中,自然是所向披靡,一些讓我們很痛苦的開發難題會迎刃而解。然而很遺憾,就目前軟體發展的情況來看,所謂的銀彈是不存在的。就像Albert Einstein生前致力於的統一場理論一樣,想要創造一種能夠涵蓋所有方面問題的解決方案或工具是不可能的。Frederick P. Brooks, Jr.先生在文中指出的幾樣很有望成為軟體開發銀彈的語言、概念如Ada語言等,這些都是被認為是很優越的軟體開發解決方案,但卻依舊無法成為銀彈。軟體的特性本身也導致不大可能有任何的發明創新——能夠像電腦硬體工業中的電子器件、晶體管、大規模整合一樣——提高軟體的生產率、可靠性和簡潔程度。
我們必須看到這樣的畸形並不是由於軟體發展得太慢,而是因為電腦硬體發展得太快。從人類文明開始,沒有任何其他產業技術的性價比,能在30年之內取得6個數量級的提高,也沒有任何一個產業可以在效能提高或者成本降低方面取得如此的進步。這些進步來自電腦製造產業的轉變,從裝配工業轉變成流水線工業。
對於軟體開發來說,一個相互牽制關聯的概念結構是軟體實體必不可少的部分,它包括:資料集合、資料條目之間的關係、演算法和功能調用等等。這些要素本身是抽象的,體現在不同的表現形式下的概念構造是相同的。儘管如此,它仍然是內容豐富和高度精確的。軟體開發中困難的部分是規格說明、設計和測試這些概念上的結構,而不是對概念進行表達和對實現逼真程度進行驗證。當然,我們還是會犯一些語法錯誤,但是與絕大多數系統中的概念錯誤相比,它們是微不足道的。
如果這是事實,軟體開發總是非常苦難的,天生沒有銀彈。(If this is true, building software will always be hard. There is inherently no silver bullet.)
我們的團隊在開發這個項目時,還沒有上升到考慮銀彈的高度。因為我們做的東西所需要的知識有很多是全新的,我們需要learning by doing新知識,還遠遠達不到考慮它的多方面優缺點以及是否有成為銀彈可能性的程度。程式員對於物件導向編程一直都有著很高的期望值,可我們現在雖說也是寫過一定數量的物件導向程式,卻依舊沒有真正掌握其精髓。要在這一次小規模的Team 專案中所涉及到的技術與銀彈聯絡起來過於牽強,但我們單是從這有限的技術手段中就已經體會到程式設計面臨的諸多困難挑戰。我們不能期望著銀彈橫空出世為我們幹掉所有的障礙,在自己的能力範圍內儘可能多地學習程式設計手段或許才是完成工程的不二法門。
1970年 ,Dr. Winston W. Royce提出瀑布模型,他結合自己在過去參與宇宙飛船空間任務的分析項目經驗發表了Managing the development of large software systems闡述對電腦軟體開發的看法。
任何電腦程式開發無論規模大小都有兩個部分,即分析與編程。但是對於軟體的實現來說,分析與編程並不是一成不變的。因為對於軟體開發人員或是軟體開發部門內部使用的小型軟體,軟體的實現、功能與使用都不必像面向全體客戶那樣事無巨細都要達到很高的標準。僅僅是通過分析與編寫程式實現需要的功能就完全足夠了。而那些使用者付費使用的、應用更為廣泛的更大型的軟體,這些細節方面的東西就必須納入考慮之內。僅僅是簡簡單單的analysis與coding顯然已經不能滿足大工程的實現要求。
要實現更大規模的軟體,就要從最初分析與編程的基礎上衍生出更多的實現步驟,也就形成了較完備的瀑布模型:
系統需求—軟體需求—軟體分析—程式設計—代碼實現—軟體測試—運行維護
雖說叫做瀑布模型,但這整個的開發階段並不是像瀑布一樣從上到下按順序走一遍就大功告成。它們之間的聯絡十分緊密,每一步都是在其上一步和下一步的基礎上實現的。前一步是後一步的基礎,後一步是前一步的反饋。雖然各步互相依存,但是非相鄰的兩步卻沒有太大的聯絡。為了保證每一個步驟的正確實施,我們希望每個步驟有一定的互動,然而不幸的是,我們在測試的時候往往會發現設計甚至是需求的問題,因此我們不得不返工。為了很好地解決這個問題,我們採用幾個步驟來解決。
1) Preliminary Design,程式設計先行,確定在進入需求分析之前,我們的概要設計要完整。
2) Document the Design,書寫設計文檔,確認我們的設計是完整的。
3) Do it Twice,雙保險,把文檔了的東西試著預先走一遍,看看能否成為最終產品。
4) Plan,control and monitor testing計劃,控制和監控測試。
5) Involve the customer 使用者介入,全程review各個環節。
最後,一個完整的瀑布模型就完成了。
現在,當你在使用waterfall開發軟體的時候,知道為什麼痛苦了吧,40年前就已經如此了。
我們團隊的項目還沒有完成瀑布模型中的後一部分,但對於模型中提到的“返工”我們可是充分領教到了。我們之前對於需求分析並沒有想得很詳細,在寫代碼的時候不斷補充、刪減、修改,最後才形成現在的作品。根據反饋更改程式設計前期的工作,這本身就是一個相輔相成的前進過程,但是因為自己一開始考慮不夠全面而導致的大的功能變更,這應該算是開發過程的忌諱。我的老師曾經這樣給學習新知識打比方:學新東西就像蒸饅頭一樣,第一遍蒸不熟,再回籠就不是那個味了。同樣的,開發新軟體在第一遍寫的時候沒有打好基礎,將來也就難逃崩潰的命運。
至於大泥球,這太貼近我們的開發過程了。我認為行雲流水般順暢地完成軟體開發應該是每一個程式員的夢想,但是真正在開發過程中沒有遇到一點的混亂與邋遢對於我們來說實在是難度太大了。雖然出現了各種鼓勵、促進良好結構代碼的開發方法,軟體技藝運動也在不斷成長,但大泥球看起來仍然是設計軟體架構的最常見方法。即使人們已經從過去惡劣的設計中學到了東西,但在新的開發過程中,大泥球仍未消失。我們的項目組出現雜亂無章、錯綜複雜的代碼的例子不少,這也為最後整合到一起增加了很多困難。
大泥球發生的主要原因可以歸結為:
- 一次性代碼
- 片段式增長
- 為了讓軟體不出問題
- Copy/paste導致問題轉移(有問題的代碼被複製到很多地方,不斷蔓延)
我們常提的敏捷是解決這個問題的手段之一,但是值得注意的是敏捷之所以能起作用,不是因為其流程,而是因為很多實踐能夠讓人們持續關注技術的卓越性、回顧、面對面溝通和得到激勵的個體。當軟體品質下降時,採取簡單的重構和測試。因此,看起來並不是流程能夠協助減少泥球,最終還是有責任心的程式員願意承擔責任、保持警惕。除非如此,不管是敏捷還是非敏捷,大泥球總會揮之不去。
說到敏捷,我們的項目中也不純熟地運用了一些敏捷的開發方法。我曾讀過敏捷式軟體開發 (Agile Software Development)宣言(Manifesto for Agile Software Development),我們在開發中也體會到了這些原則:個體和互動勝過過程和工具;可以工作的軟體勝過面面俱到的文檔;響應變化勝過遵循計劃等。工作的軟體是首要的進度度量標準——這是我們毫不動搖的基本原則。而其中有關結對程式設計和SCRUM的方式我們也實踐得很好。
在之前的討論中我們也談到過不要為了敏捷而敏捷。在我看來,在目前的軟體開發中,多數方法仍是邊寫邊改(code and fix),那麼,引入一些紀律約束肯定會比一片混亂要好。敏捷型途徑的主要優點在於它的步驟要少得多。如果你已習慣於無過程,那麼遵循簡單過程應該比遵循繁瑣過程更容易一些。對任何新過程,你都需作一番評價,這樣你可看一看它是否適合你的環境。我們的小組雖然只有6個人,但是在開發過程中對敏捷的態度基本都是支援的。敏捷開發眾口難調,就目前而言我們的項目從敏捷開發中收穫不少。不管我們以後是否會繼續從事軟體開發方面的工作,從軟工Team 專案中學到的互相學習合作的精神,將是協助我們在任何領域實現個人在團隊中價值的重要利器。