談軟件巨著《人月神話》-大型軟件項(xiàng)目最佳實(shí)踐|系列二(人月神話 人件)
最近做了一個(gè)超大項(xiàng)目重構(gòu),其中對項(xiàng)目的管理也產(chǎn)生了非常多的問題,進(jìn)行了深度項(xiàng)目的復(fù)盤之后,再回首去看軟件巨著《人月神話》體感更加豐富收獲非常多,故產(chǎn)生了此系列文章。
本系列文是軟件巨著《人月神話》讀書筆記,全系列分為三部分,會(huì)逐步介紹。
本文講述的是作者在大型軟件項(xiàng)目中一些重要的實(shí)踐,主要有
1. 團(tuán)隊(duì)劃分,外科手術(shù)式隊(duì)伍
大型項(xiàng)目的經(jīng)驗(yàn)顯示:一擁而上的開發(fā)方法是高成本、速度緩慢、低效的。成本的主要組成部分是相互的溝通和交流,以及更正溝通不當(dāng)所引起的不良結(jié)果(系統(tǒng)調(diào)試),需要協(xié)作溝通的人員的數(shù)量影響著開發(fā)成本。
不同人或者不同團(tuán)隊(duì)之間效率差異會(huì)有很大,書中提到Sackman,Erikson和Grant曾對有經(jīng)驗(yàn)的程序員進(jìn)行測量,發(fā)現(xiàn)最好的和最差的表現(xiàn)在生產(chǎn)率上有10:1的差異。
從 1963 年到 1966 年,作者項(xiàng)目設(shè)計(jì)、編碼和文檔工作花費(fèi)了大約 5000 人年。如果人月可以等量置換的話,譬如 10 人隊(duì)伍。 作為一個(gè)尺度, 假設(shè)他們都非常厲害,比一般的編程人員在編程和文檔方面的生產(chǎn)率高 7 倍。 假定 OS/360 原有開發(fā)人員是一些平庸的編程人員(這與實(shí)際的情況相差很遠(yuǎn))。 同樣,假設(shè)另一個(gè)生產(chǎn)率的改進(jìn)因子提高了 7 倍, 因?yàn)檩^小的隊(duì)伍所需較少的溝通和交流。 那么, 5000/(10× 7× 7) = 10,他們需要 10 年來完成 5000 人年的工作。一個(gè)產(chǎn)品在最初設(shè)計(jì)的 10 年后才出現(xiàn),還有人會(huì)對它感興趣嗎?或者它是否會(huì)隨著軟件開發(fā)技術(shù)的快速進(jìn)步,而顯得過時(shí)呢?
總之,團(tuán)隊(duì)的規(guī)模太大,帶來的溝通成本也隨之升高,總體效率隨之降低;團(tuán)隊(duì)規(guī)模太小,可能單位效率提升了,但是總體進(jìn)度太慢了,無法及時(shí)完成真正有用的產(chǎn)品。
如何解決上面兩難的問題呢,Harlan Mills 的提議提供了一個(gè)嶄新的、創(chuàng)造性的解決方案 。 Mills 建議大型項(xiàng)目的每一個(gè)部分由一個(gè)團(tuán)隊(duì)解決,但是該隊(duì)伍以類似外科手術(shù)的方式組建,而并非一擁而上,我們叫做“外科手術(shù)隊(duì)伍”
外科手術(shù)隊(duì)伍核心設(shè)計(jì):同每個(gè)成員截取問題某個(gè)部分的做法相反, 由一個(gè)人來進(jìn)行問題的分解, 其他人給予他所需要的支持,以提高效率和生產(chǎn)力。
團(tuán)隊(duì)陣容以一個(gè)主程序員為核心,配合9名其他專業(yè)人員形成一個(gè)團(tuán)隊(duì),如下圖所示:
- 首席程序員:決策一切并實(shí)際動(dòng)手編程,親自定義功能和性能技術(shù)說明書,設(shè)計(jì)程序,編制源代碼,測試以及書寫技術(shù)文檔,首席程序員需要極高的天分、 十年的經(jīng)驗(yàn)和應(yīng)用數(shù)學(xué)、業(yè)務(wù)數(shù)據(jù)處理或其他方面的大量系統(tǒng)和應(yīng)用知識(shí)
- 副手:作為后備,能完成任何一部分工作,但是相對具有較少的經(jīng)驗(yàn)。他的主要作用是作為設(shè)計(jì)的思考者、 討論者和評估人員。他需要詳細(xì)了解所有的代碼, 研究設(shè)計(jì)策略的備選方案。 顯然, 他充當(dāng)外科醫(yī)生的保險(xiǎn)機(jī)制。 他甚至可能編制代碼,但針對代碼的任何部分,不承擔(dān)具體的開發(fā)職責(zé)。
- 管理員:外科醫(yī)生是老板,他必須在人員、加薪等方面具有決定權(quán),但他決不能在這些事務(wù)上浪費(fèi)任何時(shí)間。 因而, 他需要一個(gè)控制財(cái)務(wù)、 人員、 工作地點(diǎn)安排和機(jī)器的專業(yè)管理人員, 該管理員充當(dāng)與組織中其他管理機(jī)構(gòu)的接口。
- 編輯:外科醫(yī)生負(fù)責(zé)產(chǎn)生文檔——出于最大清晰度的考慮,他必須書寫文檔。對內(nèi)部描述和外部描述都是如此。 而編輯根據(jù)外科醫(yī)生的草稿或者口述的手稿, 進(jìn)行分析和重新組織,提供各種參考信息和書目,對多個(gè)版本進(jìn)行維護(hù)以及監(jiān)督文檔生成的機(jī)制。
- 兩個(gè)文秘:管理員和編輯每個(gè)人需要一個(gè)秘書,配合管理員和編輯共同工作。
- 程序職員:他負(fù)責(zé)維護(hù)編程產(chǎn)品庫中所有團(tuán)隊(duì)的技術(shù)記錄。該職員接受秘書性質(zhì)的培訓(xùn),承擔(dān)機(jī)器碼文件和可讀文件的相關(guān)管理責(zé)任
- 工具維護(hù)人員:保證所有基本服務(wù)的可靠性, 以及承擔(dān)團(tuán)隊(duì)成員所需要的特殊工具(特別是交互式計(jì)算機(jī)服務(wù)) 的構(gòu)建、 維護(hù)和升級(jí)責(zé)任。
- 測試人員:負(fù)責(zé)編寫測試用例,搭建測試環(huán)境并測試。
- 語言專家:尋找一種簡潔、 有效的使用語言的方法來解決復(fù)雜、 晦澀或者棘手的問題。
傳統(tǒng)的團(tuán)隊(duì):將工作進(jìn)行劃分,每人負(fù)責(zé)一部分工作的設(shè)計(jì)和實(shí)現(xiàn);
外科手術(shù)團(tuán)隊(duì):實(shí)際設(shè)計(jì)完全由外科醫(yī)生完成,其他人負(fù)責(zé)填充實(shí)現(xiàn)細(xì)節(jié)與提供必要的幫助。
外科手術(shù)式隊(duì)伍的好處在于:
- 減少溝通的成本,在傳統(tǒng)的隊(duì)伍中,大家是平等的,出現(xiàn)觀點(diǎn)差異的時(shí)候,不可避免的需要討論和妥協(xié),在外科式隊(duì)伍中,不存在利益的差別,也不存在因?yàn)橐庖姴缓蠋淼牟呗院拖到y(tǒng)接口上的不一致,觀點(diǎn)不一致由外科醫(yī)生單方面來統(tǒng)一。
- 保證概念完整性,系統(tǒng)的設(shè)計(jì)和程序代碼都由外科醫(yī)生主要負(fù)責(zé),保障了從設(shè)計(jì)到實(shí)現(xiàn)上的概念完整性。
如果整個(gè)工作能控制在范圍之內(nèi), 10 人的團(tuán)隊(duì)無論如何組織, 總是比較高效的。但是, 當(dāng)我們需要面對幾百人參與的大型任務(wù)時(shí), 如何應(yīng)用外科手術(shù)團(tuán)隊(duì)的概念呢?
首先整個(gè)系統(tǒng)必須具備概念上的完整性, 要有一個(gè)系統(tǒng)結(jié)構(gòu)師從上至下地進(jìn)行所有的設(shè)計(jì)。 要使工作易于管理, 必須清晰地劃分體系結(jié)構(gòu)設(shè)計(jì)和實(shí)現(xiàn)之間的界線, 系統(tǒng)結(jié)構(gòu)師必須一絲不茍地專注于體系結(jié)構(gòu)。
然后需要使用分解的技術(shù),分解到一個(gè)個(gè)獨(dú)立部分,每個(gè)部分由一個(gè)外科手術(shù)團(tuán)隊(duì)保障概念完整性。項(xiàng)目整體的溝通只需要再外科醫(yī)生之間進(jìn)行溝通和討論,大大降低成本。
2. 保持概念完整性,貴族專制
絕大多數(shù)歐洲的大教堂中,由不同時(shí)代、不同建筑師所建造的各個(gè)部分之間,在設(shè)計(jì)或結(jié)構(gòu)風(fēng)格上都存在著許多差異。 后來的建筑師總是試圖在原有建筑師的基礎(chǔ)上有所“ 提高”,以反映他們在設(shè)計(jì)風(fēng)格和個(gè)人品味上的改變。所以, 在雄偉的哥特式的教堂上,依附著祥和的諾曼第風(fēng)格十字架,它在顯示上帝榮耀的同時(shí),展示了同樣屬于建筑師的驕傲。
與之對應(yīng)的是, 法國城市蘭斯(Reims) 在建筑風(fēng)格上的一致性和上面所說的哥特式大教堂形成了鮮明的對比。 設(shè)計(jì)的一致性和那些獨(dú)到之處一樣, 同樣讓人們贊嘆和喜悅。 如同旅游指南所述, 風(fēng)格的一致和完整性來自 8 代擁有自我約束和犧牲精神的建筑師們, 他們每一個(gè)人犧牲了自己的一些創(chuàng)意, 以獲得純粹的設(shè)計(jì)。 同樣, 這不僅顯示了上帝的榮耀, 同時(shí)也體現(xiàn)了他拯救那些沉醉在自我驕傲中的人們的力量。
對于計(jì)算機(jī)系統(tǒng)而言,盡管它們通常沒有花費(fèi)幾個(gè)世紀(jì)的時(shí)間來構(gòu)建,但絕大多數(shù)系統(tǒng)體現(xiàn)出的概念差異和不一致性遠(yuǎn)遠(yuǎn)超過歐洲的大教堂。 這通常并不是因?yàn)樗刹煌脑O(shè)計(jì)師們開發(fā),而是由于設(shè)計(jì)被分成了由若干人完成的若干任務(wù)。
作者主張?jiān)谙到y(tǒng)設(shè)計(jì)中,概念完整性應(yīng)該是最重要的考慮因素。也就是說為了反映一系列連貫的設(shè)計(jì)思路,寧可省略一些不規(guī)則的特性和改進(jìn),也不提倡獨(dú)立和無法整合的系統(tǒng),哪怕它們其實(shí)包含著許多很好的設(shè)計(jì)。
短小精干的隊(duì)伍帶來了新的問題,如何對大項(xiàng)目進(jìn)行合理的分割?
這依賴于一個(gè)很重要的前提:概念完整性。系統(tǒng)設(shè)計(jì)中,概念完整性是最重要的考慮因素。概念的完整性的確要求系統(tǒng)只反映唯一的設(shè)計(jì)理念,用戶所見的技術(shù)說明來自少數(shù)人的思想。
如何獲得系統(tǒng)的完整性? 答案是貴族專制,設(shè)計(jì)必須由一個(gè)人或非常少數(shù)互有默契的人員來實(shí)現(xiàn)并理清邊界,然后據(jù)此分割執(zhí)行。對于非常大型的項(xiàng)目, 將設(shè)計(jì)方法、 體系結(jié)構(gòu)方面的工作與具體實(shí)現(xiàn)相分離是獲得概念完整性的強(qiáng)有力方法?!?[同樣適用于小型項(xiàng)目 ]
3. 避免畫蛇添足,要自律
在開發(fā)第一個(gè)系統(tǒng)時(shí),結(jié)構(gòu)師傾向于精煉和簡潔。他知道自己對正在進(jìn)行的任務(wù)不夠了解,所以他會(huì)謹(jǐn)慎仔細(xì)地工作。同時(shí)他對會(huì)不斷產(chǎn)生的裝飾和潤色功能,把這些功能都擱置在一邊,作為下一個(gè)項(xiàng)目的內(nèi)容。第一個(gè)項(xiàng)目遲早會(huì)結(jié)束,而此時(shí)的結(jié)構(gòu)師,對這類系統(tǒng)充滿了十足的信心,熟練掌握了相應(yīng)的知識(shí),并且時(shí)刻準(zhǔn)備開發(fā)第二個(gè)系統(tǒng)。
第二個(gè)系統(tǒng)是設(shè)計(jì)師們所設(shè)計(jì)的最危險(xiǎn)的系統(tǒng),一種普通傾向是過分地設(shè)計(jì)第二個(gè)系統(tǒng),向系統(tǒng)添加更多修飾功能和想法,它們曾在第一個(gè)系統(tǒng)中被小心謹(jǐn)慎地推遲了。如果如同ovid所述,是一個(gè)”大餡餅“。例如,后來被嵌入到7090的IBM709系統(tǒng),709是非常成功和簡潔的704系統(tǒng)進(jìn)行升級(jí)的二次開發(fā)項(xiàng)目,709的操作集合被設(shè)計(jì)的如此豐富和充沛,以至于只有一般操作被常規(guī)使用。
所以書中提到系統(tǒng)設(shè)計(jì)師們,在系統(tǒng)設(shè)計(jì)時(shí),需要對項(xiàng)目有節(jié)制,有些東西可以不添加,不要過度設(shè)計(jì),不要過度自信,保持警覺,確保初始的概念和目標(biāo)的充分體現(xiàn),而不是讓一些次要功能喧賓奪主。
4. 概念完整性貫徹,一些方法
概念的完整性不僅僅要在專制的貴族和系統(tǒng)設(shè)計(jì)師這一層面上充分理解并傳達(dá),在系統(tǒng)的實(shí)現(xiàn)人員中,也要充分傳達(dá)。在不理解業(yè)務(wù)背景的情況下,開發(fā)者也很難寫出優(yōu)秀的代碼。
作者在這一章介紹了很多方法達(dá)到之一目的,包括規(guī)格說明手冊,形式化定義(如原型圖)、會(huì)議和大會(huì)、多重實(shí)現(xiàn)、電話日志、產(chǎn)品測試。當(dāng)然這些方法在如今可能已經(jīng)過時(shí)了或有更好的方式,但是通過種種方式保證軟件開發(fā)的進(jìn)度不偏離最初的概念和目標(biāo),是實(shí)現(xiàn)項(xiàng)目成功的重要保障。實(shí)際上在當(dāng)代的軟件開發(fā)中,也有一些措施來實(shí)現(xiàn)這一目標(biāo),比如各種項(xiàng)目管理工具,版本化文檔工具等。
5. 溝通,巴比倫塔失敗的教訓(xùn)
據(jù)《創(chuàng)世紀(jì)》記載,巴比倫塔是人類繼諾亞方舟之后的第二大工程壯舉,但巴比倫塔同時(shí)也是第一個(gè)徹底失敗的工程。
文中以巴比倫塔建設(shè)失敗的神話故事引出了”溝通“的重要性。當(dāng)上帝消除了統(tǒng)一的語言,人們失去了交流的手段,即使其他條件都能滿足,巴比倫塔也以失敗告終。
文中他們分析了必要的有利條件都已經(jīng)具備,但還缺乏兩個(gè)方面——交流, 以及交流的結(jié)果——組織。他們無法相互交談, 從而無法合作。 當(dāng)合作無法進(jìn)行時(shí), 工作陷入了停頓。 通過史書的字里行間, 我們推測交流的缺乏導(dǎo)致了爭辯、 沮喪和群體猜忌。很快,部落開始分裂——大家選擇了孤立,而不是互相爭吵。
溝通時(shí)確保團(tuán)隊(duì)思想統(tǒng)一、目標(biāo)一致的最重要手段。那么,如何進(jìn)行有效的溝通呢:
- 時(shí)常保持非正式的交流溝通。比如面對面口頭的交流或者電話等過遠(yuǎn)程交流,不論哪種形式,交流的內(nèi)容都應(yīng)形成文字記錄。
- 常規(guī)性項(xiàng)目會(huì)議。關(guān)鍵成員定期組織項(xiàng)目例會(huì),討論主題順明確,結(jié)論有效,會(huì)議內(nèi)容形成文字記錄。
- 項(xiàng)目必須擁有共享的工作手冊。這是一套文檔的集合,在在項(xiàng)目初期就確定各個(gè)文檔的結(jié)構(gòu),然后在項(xiàng)目過程中不斷的填寫細(xì)化完善,每個(gè)版本應(yīng)該擁有明確的時(shí)間記錄和變更說明。
- 文檔其實(shí)是高效溝通的一種有效方式。準(zhǔn)備文檔時(shí),需要要仔細(xì)的核對實(shí)際情況,謹(jǐn)慎的措辭;寫文檔時(shí),各種問題和討論都會(huì)浮出水面,必須進(jìn)行決定;寫完文檔后,所有的想法和決定都都以文字的方式確定并記錄,對每個(gè)人的思想進(jìn)行統(tǒng)一。文檔能夠使各項(xiàng)計(jì)劃和決定在整個(gè)團(tuán)隊(duì)范圍內(nèi)得到交流。
項(xiàng)目經(jīng)理的主要日常工作就是溝通,而不是做出決定。他的職責(zé)是使每個(gè)人都向著相同的方向前進(jìn)。
即使再三強(qiáng)調(diào)溝通的重要性,但是由于主觀或者客觀的原因,在實(shí)際項(xiàng)目過程中還是會(huì)發(fā)現(xiàn)溝通不足導(dǎo)致的問題。書中也提出了幾種方式如何減少溝通也能達(dá)到有效協(xié)作的目標(biāo):
- 每個(gè)人不是必須關(guān)注所有的內(nèi)容,各個(gè)部分應(yīng)該只暴露對外表現(xiàn),而內(nèi)部實(shí)現(xiàn)應(yīng)該封裝不對外暴露。這段內(nèi)容體現(xiàn)到代碼上就是:面向接口編程,不要依賴實(shí)現(xiàn)邏輯。
- 小而精的團(tuán)隊(duì)搭配,保持一個(gè)首席程序員完成所有的設(shè)計(jì)和代碼偏寫工作,其他人進(jìn)行輔助配合,確保概念的完整性和一致性,減少溝通。
- 團(tuán)隊(duì)協(xié)作就要形成組織結(jié)構(gòu),團(tuán)隊(duì)組織的目的是為了減少必要的交流和協(xié)作量,人力劃分和職責(zé)范圍必須明確并且清晰。團(tuán)隊(duì)中禁止雙重領(lǐng)導(dǎo),團(tuán)隊(duì)是樹狀結(jié)構(gòu),交流是網(wǎng)狀結(jié)構(gòu),需要補(bǔ)充特殊組織機(jī)制來克服樹狀組織結(jié)構(gòu)中缺乏交流的困難。
團(tuán)隊(duì)組織的目標(biāo)是為了減少必要的交流和協(xié)作量,為了減少交流,組織結(jié)構(gòu)包括了人力劃分(division of labor) 和限定職責(zé)范圍(specialization of function)。
傳統(tǒng)的樹狀組織結(jié)構(gòu)反映了權(quán)力的結(jié)構(gòu)原理——不允許雙重領(lǐng)導(dǎo),組織中的交流是網(wǎng)狀, 而不是樹狀結(jié)構(gòu), 因而所有的特殊組織機(jī)制(往往體現(xiàn)成組織結(jié)構(gòu)圖中的虛線部分)都是為了進(jìn)行調(diào)整,以克服樹狀組織結(jié)構(gòu)中交流缺乏的困難。
6. 胸有成竹,工作量的預(yù)估
系統(tǒng)編程需要花費(fèi)多長的時(shí)間?需要多少工作量?如何進(jìn)行估計(jì)?
先前他推薦了合理的軟件進(jìn)度安排應(yīng)該遵循:計(jì)劃進(jìn)度(1/3)、編碼(1/4)、構(gòu)建測試(1/4)和系統(tǒng)測試(1/4)。僅僅通過對編碼部分的估計(jì),然后應(yīng)用上述比率對整個(gè)任務(wù)進(jìn)行估計(jì)是錯(cuò)誤的。編碼大約之戰(zhàn)問題的1/6左右,編碼估計(jì)或者比率的錯(cuò)誤可能導(dǎo)致不合理荒謬結(jié)果。
第二,必須聲明的是,構(gòu)建獨(dú)立小型程序的數(shù)據(jù)不適用于編程系統(tǒng)產(chǎn)品。就好像把 100 碼短跑記錄外推, 得出人類可以在 3分鐘之內(nèi)跑完 1 英里的結(jié)論一樣。
作者當(dāng)時(shí)編程量化方法將程序員的生產(chǎn)效率細(xì)化到指令/年(他們當(dāng)年寫的是匯編,高級(jí)語言那個(gè)時(shí)候還很少)。這個(gè)實(shí)際意義不大,但仍然是一個(gè)有趣的參考,最終的結(jié)論是: 工作量=常數(shù)*指令數(shù)量^1.5,也就是說工作時(shí)長跟代碼數(shù)量是指數(shù)關(guān)系而不是線性關(guān)系,隨著代碼數(shù)量的增長,工作時(shí)長是指數(shù)級(jí)上升的。
然后舉例說一些關(guān)于編程人員生產(chǎn)率的研究,提出的一些估計(jì)技術(shù)。生產(chǎn)率會(huì)根據(jù)任務(wù)本身復(fù)雜度和困難程度表現(xiàn)出顯著差異。無法用代碼量來預(yù)估排期,使用適當(dāng)?shù)母呒?jí)語言,編程的生成效率可以提高5倍。
7. 減少程序空間,削足適履
這一章主要是講程序大小的,包括代碼大小和內(nèi)存占用的大小。代碼大小現(xiàn)在應(yīng)該已經(jīng)不是軟件開發(fā)的重要考量了吧? 但是這一問題在如今的App開發(fā)中應(yīng)該也有,雖然很多公司毫不在乎占用用戶幾百M(fèi)的存儲(chǔ)空間……當(dāng)然在前端還存在另外一個(gè)問題,即過大的代碼包會(huì)耗費(fèi)過多的流量,尤其是在早年的移動(dòng)端開發(fā)中,那時(shí)候流量很金貴,現(xiàn)在這樣的顧慮逐漸變少了,但是一直都存在的顧慮是代碼的加載速度,當(dāng)然這一問題也可以通過分包懶加載來解決了??偠灾?當(dāng)年的那些經(jīng)驗(yàn)在前端領(lǐng)域適用的已經(jīng)不多了,但是在客戶端領(lǐng)域可能仍然適用。
內(nèi)存當(dāng)然始終是一個(gè)問題,但是應(yīng)該主要考慮不要發(fā)生內(nèi)存泄露的問題,自動(dòng)的垃圾收集可以解決大部分問題。計(jì)算機(jī)硬件的進(jìn)步真的極大地降低了軟件工程的難度。
8. 項(xiàng)目文檔的重要性,提綱挈領(lǐng)
這一章主要是介紹文檔的重要性,對于項(xiàng)目經(jīng)理來說,文檔是很重要的,它包含了項(xiàng)目目標(biāo)、產(chǎn)品的技術(shù)說明、時(shí)間、資金預(yù)算、工作空間的分配和人員的組織結(jié)構(gòu)。
- 文檔的重要性主要體現(xiàn)在: 明確的書面記錄會(huì)讓分歧更明朗,使混沌的狀態(tài)變得清晰、明確。
- 文檔降低了溝通的負(fù)擔(dān)。
- 文檔便于項(xiàng)目經(jīng)理跟蹤項(xiàng)目的進(jìn)度狀態(tài)。
9. 唯一不變的是變化,未雨綢繆
軟件領(lǐng)域的名言:“唯一不變的就是變化本身”,潛臺(tái)詞就是“其他都會(huì)發(fā)生變化”
變化意味著不可預(yù)料,不可提前準(zhǔn)備,準(zhǔn)備好的可能徒勞、不可控,變化的情況有很多,例如:
- 用戶不會(huì)在初期提供明確的需求,用戶的實(shí)際需要和用戶的感覺會(huì)隨著程序的構(gòu)建、測試和使用而變化。
- 軟件開發(fā)和運(yùn)行過程中的環(huán)境不一定一致,甚至運(yùn)行環(huán)境本身也在變化。
- 設(shè)計(jì)人員在軟件開發(fā)完成之后才能意識(shí)到設(shè)計(jì)上的缺陷,從而視圖在下一個(gè)版本中彌補(bǔ)
- 團(tuán)隊(duì)成員由于各種因素(私人的或者公司的)變化,甚至核心成員發(fā)生變化可能直接導(dǎo)致軟件推翻重來。
系統(tǒng)必然會(huì)面臨各種變化,你開發(fā)的軟件必然會(huì)在修修補(bǔ)補(bǔ)中變得面目全非,最初的設(shè)計(jì)必須在各種妥協(xié)中打上各種丑陋的補(bǔ)丁。無論是多么良好設(shè)計(jì)的系統(tǒng),都會(huì)走向混亂,區(qū)別只是這個(gè)過程的快慢而已。因此,好的設(shè)計(jì)會(huì)讓這個(gè)過程盡可能的慢,盡可能地不那么痛苦,我們能做的就是眼光盡量放長遠(yuǎn),讓我們的代碼盡可能地具有高可擴(kuò)展性并且易于維護(hù)。而且,在面對不得不進(jìn)行重構(gòu)時(shí),做好心里準(zhǔn)備。
一些Bug有趣的數(shù)據(jù),對于一個(gè)廣泛使用的程序,其維護(hù)總成本通常是開發(fā)成本的 40%或更多。令人吃驚的是,該成本受用戶數(shù)目的嚴(yán)重影響。用戶越多,所發(fā)現(xiàn)的錯(cuò)誤也越多。
起初,上一個(gè)版本中被發(fā)現(xiàn)和修復(fù)的 bug,在新的版本中仍會(huì)出現(xiàn)。 新版本中的新功能會(huì)產(chǎn)生新的 bug。 解決了這些問題之后, 程序會(huì)正常運(yùn)行幾個(gè)月。接著, 錯(cuò)誤率會(huì)重新攀升。 Campbell 認(rèn)為這是因?yàn)橛脩舻氖褂玫竭_(dá)了新的熟練水平,他們開始運(yùn)用新的功能。這種高強(qiáng)度的考驗(yàn)查出了新功能中很多不易察覺的問題。
程序維護(hù)中的一個(gè)基本問題是——缺陷修復(fù)總會(huì)以(20- 50) %的機(jī)率引入新的 bug,所以整個(gè)過程是前進(jìn)兩步,后退一步。
系統(tǒng)軟件開發(fā)是減少混亂度(減少熵)的過程,所以它本身是處于亞穩(wěn)態(tài)的。軟件維護(hù)是提高混亂度(增加熵) 的過程, 即使是最熟練的軟件維護(hù)工作, 也只是放緩了系統(tǒng)退化到非穩(wěn)態(tài)的進(jìn)程。
10. 提升開發(fā)效率的工具,干將莫邪
巧匠因?yàn)樗墓ぷ鞫雒üそ尘瘢?/p>
好的開發(fā)團(tuán)隊(duì)自然要有自己一套比較完好的開發(fā)工具和開發(fā)環(huán)境,用來提供生產(chǎn)力和生產(chǎn)效率。
本章主要向我們傳達(dá)的意思是: 工具對于軟件產(chǎn)業(yè)的重要性,工具需要做到統(tǒng)一,需要有專人進(jìn)行維護(hù)。
11. 如何讓整體正常運(yùn)行,整體部分
當(dāng)每個(gè)功能模塊開發(fā)、測試完成,開始多個(gè)模塊之間進(jìn)行集成測試;或者一個(gè)子系統(tǒng)開發(fā)測試完成,開始多個(gè)子系統(tǒng)進(jìn)行集成測試。單個(gè)模塊獨(dú)立運(yùn)行對最終用戶根本沒有意義,所有模塊配合到一起形成完整的業(yè)務(wù)鏈路才能作為交付物。
這時(shí)的人們都樂觀地認(rèn)為"總算都開發(fā)完了,集成調(diào)試一下就都搞定了"。其實(shí),這才是痛苦的開始。各種之前不相關(guān)的人和資源需要協(xié)調(diào),這些人互相屬于不同的團(tuán)隊(duì),團(tuán)隊(duì)之間職責(zé)劃分不清晰,這些都開始極度考驗(yàn)每個(gè)團(tuán)隊(duì)負(fù)責(zé)人的水平–"開始推卸責(zé)任":因?yàn)槟K與模塊之間的適配部分沒有人負(fù)責(zé)開發(fā)實(shí)現(xiàn),每個(gè)團(tuán)隊(duì)都理所當(dāng)然的認(rèn)為這些公共部分是對方負(fù)責(zé)的。
即使各個(gè)模塊獨(dú)立運(yùn)行正確,也不一定能夠集成。事實(shí)上,預(yù)先定義的集成標(biāo)準(zhǔn)并不是完美的、嚴(yán)格的。這就導(dǎo)致不同團(tuán)隊(duì)對標(biāo)準(zhǔn)的理解有差異,實(shí)現(xiàn)出來的模塊總會(huì)有差異,這些差異只有在集成的過程中才能發(fā)現(xiàn)。每個(gè)模塊都認(rèn)為自己的符合標(biāo)準(zhǔn)的,對方需要修改才能按照標(biāo)準(zhǔn)進(jìn)行集成。
這些技術(shù)問題相對還是容易解決的,更麻煩的是各個(gè)系統(tǒng)是不同的團(tuán)隊(duì)或者組織開發(fā)的,系統(tǒng)間進(jìn)行集成就必須同時(shí)協(xié)調(diào)多方組織的人員。在權(quán)力不能到達(dá)的情況下,協(xié)調(diào)多方利益并不完全一致的組織簡直是時(shí)間殺手。
書中也指出:"系統(tǒng)調(diào)試(相對于單元測試)所花費(fèi)的時(shí)間會(huì)比預(yù)料的更長"。針對這個(gè)問題,我在書中沒有找到針對性的解決方案,最好是早集成、早暴露、早解決。
同時(shí)我們可以在設(shè)計(jì)系統(tǒng)結(jié)構(gòu)時(shí)精心設(shè)計(jì),減少各個(gè)部分間的耦合,各個(gè)模塊的獨(dú)立性越高,系統(tǒng)級(jí)的bug的可能性就越低。重構(gòu)過的模塊在合進(jìn)整體的時(shí)候仍然需要對系統(tǒng)整體進(jìn)行測試,而不是僅僅測試重構(gòu)過的模塊。如自上而下的設(shè)計(jì)、構(gòu)件單元調(diào)試等。
12. 進(jìn)度管理和監(jiān)控的方法–防止禍起蕭墻
在我們的工作經(jīng)驗(yàn)中,很多大型軟件項(xiàng)目都會(huì)比預(yù)期延后,在事后的總結(jié)中卻又并不能發(fā)現(xiàn)重大的失誤,那么,到底是什么導(dǎo)致了項(xiàng)目的整體落后呢?
書中提到:"一天一天的進(jìn)度落后比重大災(zāi)難更難以識(shí)別,不易防范,更加難以彌補(bǔ)"。確實(shí)是這樣的,某天關(guān)鍵成員請假了,某天需要的環(huán)境沒有到位,某天公司的網(wǎng)絡(luò)突然換掉了,這些隱藏在日常過程中的小事,一天一天的把進(jìn)度延后了。而且沒有人能夠及時(shí)發(fā)覺,在發(fā)覺進(jìn)度延后之后,也會(huì)下意識(shí)的認(rèn)為:明天就好了,加加班就趕回來了。慢性的進(jìn)度偏離絕對是士氣殺手。沒有人總結(jié),沒有人匯報(bào),也就沒有人解決,時(shí)間就這樣一天天的過去了,直到項(xiàng)目到期時(shí)才發(fā)覺:"時(shí)間都去哪了"?
隱藏偏離是人的本性,每個(gè)人都不希望將自己的缺點(diǎn)暴露在人前,軟件開發(fā)人員更傾向自己悶頭鉆研而不善于求助他人,更希望自己將問題搞定而沒有發(fā)覺進(jìn)度已經(jīng)延后。作為項(xiàng)目管理里者不能奢望團(tuán)隊(duì)成員都能如實(shí)的、及時(shí)的匯報(bào)工作進(jìn)展。項(xiàng)目管理者需要通過各種方式維護(hù)一種信任、平等、合作、互助的工作氛圍,逐漸的引導(dǎo)或者影響開發(fā)人員將實(shí)際情況表達(dá)出來。
項(xiàng)目經(jīng)理必須使用嚴(yán)格的進(jìn)度表來控制項(xiàng)目,進(jìn)度表由里程碑和日期組成。每個(gè)里程碑必須是具體的、特定的、可度量的事件,能夠進(jìn)行清晰定義。項(xiàng)目經(jīng)理積極的跟進(jìn)每項(xiàng)工作進(jìn)展才可能盡量準(zhǔn)確的了解項(xiàng)目的真實(shí)進(jìn)展,從而進(jìn)行資源的調(diào)配。
項(xiàng)目進(jìn)度滯后往往如溫水煮青蛙一樣讓我們難以應(yīng)付,最重要的就是要防微杜漸。
13. 提供面向用戶的文檔,另外一面
程序向用戶所呈現(xiàn)的面貌(界面、文檔、注釋)與提供給機(jī)器識(shí)別的內(nèi)容(代碼)同樣重要。不管是獨(dú)立程序還是系統(tǒng)軟件,都應(yīng)該編寫注釋,因?yàn)槿藭?huì)遺忘的。
注釋需要描述事情如何,還應(yīng)描述為什么,注釋信息應(yīng)該以段落的方式向程序中插入必要的記述生文字,同時(shí)可以借助源代碼的固定格式來附件更多的文檔信息關(guān)提升可讀性。
除了面向開發(fā)者的項(xiàng)目文檔和說明之外,軟件開發(fā)也需要編寫詳勿的面向用戶的文檔,文檔需要包含軟件的目的、運(yùn)行環(huán)境、轉(zhuǎn)輸入輸出范圍、實(shí)現(xiàn)的功能和使用的算法、輸入輸出的格式、排操作指令、選項(xiàng)、運(yùn)行時(shí)間、輸出結(jié)果的精度和校驗(yàn)方式等等。
除此之外,還需要充分的測試用例來說明程序的功能和邊界。