內容簡介
本書內容來自Brooks博士在IBM公司SYSTEM/360家族和OS/360中的項目管理經驗,該項目堪稱軟件開發項目管理的典范。該書英文原版一經面世,即引起業內人士的強烈反響,全球銷售數百萬冊。
作者簡介
布魯克斯博士1956年開始任職于IBM公司,早期擔任Stretch和Harvest計算機的體系建構師。他被認為是“IBM360系統之父”,曾擔任360系統的項目經理。憑借在此項目中的杰出貢獻,他在1985年獲得了美國國家技術獎。
第1章焦油坑
編程系統產品
編程系統(programing system)開發的工作量是供個人使用的、獨立開發的構件程序的9倍。估計軟件構件產品化引起了3倍的工作量,將軟件構件整合成完整系統所需要的設計、集成和測試又加強了3倍的工作量,這些高成本的構件在根本上是相互獨立的。
編程的樂趣
這種快樂是一種創建事物的純粹快樂;
這種快樂來自于開發對他人有用的東西;
快樂來自于整個過程中體現出的一股強大魅力;
這種快樂是持續學習的快樂;
這種快樂來自于易于駕馭的介質上工作。
編程的苦惱
苦惱來自追求完美;
苦惱來自由他人來設定目標、供給資源和提供信息;
依賴于其他人的拙劣程序是苦惱的;
概念性設計是有趣的,但尋找bug卻只是一項重復性的活動;
投入大量辛苦勞動,產品上線時卻顯得陳舊過時。
第2章人月神話
缺乏合理的時間進度是造成項目滯后的主要原因,它比其他所有因素的綜合影響還大。
良好的烹飪需要時間,某些任務無法在不損害結果的情況下加快進度。
所有的編程人員都是樂觀主義者:一切都將運作良好。
由于編程人員通過純粹的思維活動來開發,我們期待在實現過程中不會碰到困難,但我們的構思本身是有缺陷的,因此總會有bug。
我們圍繞成本核算的估計技術,混淆了工作量和項目進展。人月是危險和帶有欺騙性的神話,因為它暗示人員數量和時間是可以相互替換的。
在若干人員中分解任務會引發額外的溝通工作量—培訓和相互溝通。
關于進度安排,我的經驗是1/3計劃、1/6變化,1/4構件測試以及1/4系統測試。
我們對自己的估計技術不確定,因此在管理和客戶的壓力下,我們常缺乏堅持的勇氣。
Brooks法則:向進度落后的項目增加人手,只會使進度更加落后。
向軟件項目中增派人手從三個方面增加了項目必要的總體工作量:任務重新分配本身和所造成的工作中斷:培訓新人員;額外的相互溝通。
第3章 外科手術隊伍
同樣有兩年經驗而且在受同樣培訓的情況下,有些專業程序員的生產率是較差的程序員的10倍。
小型、精干隊伍是最好的—思緒盡可能的少。
兩個人的團隊,其中一個是領導者,常常是最佳的人員使用方法(留意一下上帝對婚姻的設計)。
對于真正意義上的大型系統,小型精干的隊伍太慢了。
實際上,絕大多數大型編程系統的經驗顯示,一擁而上的開發方法是提高成本、速度緩慢、低效的,開發出的產品無法進行概念上的集成。
一位首席程序員、類似外科手術隊伍的團隊架構提供了一種方法—既能獲得由少數頭腦產生的產品完整性,又能得到多位協助人員的總體生產率,還徹底減少了溝通的工作量。
第4章 貴族專制、民主政治和系統設計
概念完整性是系統設計中最重要的考慮因素。
功能與理解上的復雜程度的比值才是系統設計的最終測試標準,而不僅僅是豐富的功能(該比值是對易用性的一種測量,由簡單和復雜應用共同驗證)。
為了獲得概念完整性,設計必須由一個人或者具有共識的小型團隊來完成。
對于非常大型的項目,將體系結構方面的工作與具體實現相分離是獲得概念完整性的強有力方法(同樣適用于小型項目)。
如果要得到系統概念上的完整性,就必須有人控制這種概念。這實際上是一種無須任何歉意的貴族專制統治。
紀律、規則對行業是有益的,外部的體系結構規定實際上是增強,而不是限制實現小組的創造性。
概念上統一的系統能更快地開發和測試。
體系結構、設計實現、物理實現的許多工作可以并發進行(軟件和硬件設計同樣可以并行)。
第5章 畫蛇添足
盡早交流和持續溝通能使結構師有較好的成本意識,使開發人員獲得對設計的信息,并且不會混淆各自的責任分工。
結構師如何成功的影響實現:
牢記是開發人員承擔創造性的實現責任,結構師只能提出建議。
時刻準備著為所指定的說明建議一種實現的方法,準備接受任何其他可行的方法。
對上述建議保持低調和平靜。
準備對所建議的改進放棄堅持。
聽取開發人員在體系結構上改進的建議。
第二個系統是人們所設計的最危險的系統,通常的傾向是過分的進行設計。/*設計第一個系統時因沒經驗而比較謹慎*/
為功能分配一個字節和微妙的優先權值是一個很有價值的規范化方法。
第6章 貫徹執行
即使是大型的設計團隊,設計結果也必須由一兩個人來完成,以確保這些決定是一致的。
必須明確定義體系結構中與先前定義不同的地方,重新定義的詳細程度應該與原先的說明一致。
出于精確性的考慮,我們需要形式化的設計定義;同樣,我們需要記述性定義來加深理解。
必須采用形式化定義和記述型定義中的一種作為標準,另一種作為輔助措施,它們都可以作為表達的標準。
直接整合是一種強制推行軟件的結構性標準的方法。(硬件上也是如此)
如果起初至少有兩種以上的實現,體系結構定義會更加整潔和規范。
允許體系結構師對實現人員的詢問做出電話應答解釋是非常重要的,并且必須進行日志記錄和整理發布。
項目經理最好的朋友就是他每天要面對的對手—獨立的產品測試小組。
第7章 為什么巴比倫塔會失敗
交流
巴比倫塔項目的失敗是以為缺乏交流以及交流的結果—組織。
左手不知道右手在做什么,從而進度災難、功能的不合理和系統缺陷紛紛出現。由于對其他人的各種假設,團隊成員之間的理解開始出現偏差。
團隊應以盡可能多的方式進行相互之間的交流:非正式的進行簡要技術陳述的常規項目會議,共享的正式項目工作手冊。
項目手冊
項目工作手冊不是獨立的一篇文檔,它是對項目必須產生的一系列文檔進行組織的一種結構。
項目所有的文檔都必須是該工作手冊結構的一部分。
需要盡早和仔細的設計工作手冊結構。
事先制定了良好結構的工作手冊可以將后來書寫的文字放置在合適的章節中,并且可以提高產品手冊的質量。
每個團隊成員應該了解所有的材料(工作手冊)。
實時更新是至關重要的。
工作手冊的使用者應該講注意力集中在上次閱讀后的變更以及關于這些變更重要性的評述上。
組織架構
團隊組織的目標是為了減少必要的交流和協作量。
為了減少交流,組織結構包括了人力劃分和限定職責范圍。
傳統的樹狀組織結構反映了權利的結構原理—不允許雙重領導。
組織中的交流是網狀,而不是樹狀結構,因此所有的特殊組織機制都是為了進行調整,以克服樹狀組織結構中缺乏交流的困難。
每個子項目具有兩個領導角色:產品負責人、技術主管,兩種角色的任意組合都可以是非常有效的,一個作為總指揮,另一個作為副手。
第8章 胸有成竹
僅通過對編碼部分時間的估計,然后乘以任務其他部分的相對系數,是無法得出對整個項目的精確估計的。
程序開發呈程序規模的指數增長,研究報告顯示指數約為1.5。
數據顯示相對于其他活動開銷,全職程序員僅將50%的時間用于編程和調試。
在基本語句級別,生產率看上去是個常數。
當使用適當的高級語言時,程序編制的生產率可以提高5倍。
第9章 削足適履
除了運行時間以外,程序所占的內存空間也是主要開銷。特別是對于操作系統,它的很多程序是永久駐留在內存中的。
即便如此,花費在駐留程序所占內存上的金錢仍是物有所值的,比其他任何在配置上投資的效果都要好,規模本身不是壞事,但不必要的規模是不可取的。
軟件開發人員必須設立規模目標,控制規模,發明一些減少規模的方法—就如同硬件開發人員為減少元器件所做的事一樣。
規模預算不僅在占據內存方面是明確的,同時還應該指明程序對磁盤的訪問次數。
規模預算必須與分配的功能相關聯,在指明模塊大小的同事,確切定義模塊的功能。
在大型團隊中,各個小組傾向于不斷的局部優化,以滿足自己的目標,而較少考慮對用戶的整體影響。這種方向性的問題是大型項目的主要危險。
在整個實現的過程期間,系統結構師必須保持持續的警覺,確保連貫的系統完整性。
培養開發人員從系統整體出發、面向用戶的態度是軟件編程管理人員最重要的職能。
在早期應該制定策略,以決定用戶選項目的粗細程度,因為它們將作為整體打包能夠節省內存空間。(常常還能節約市場成本)
暫存區空間的尺寸,以及每次磁盤訪問的程序數量都是很關鍵的決策,因為性能是規模的非線性函數。
為了獲取良好的空間—時間折中,開發隊伍需要得到特定于某種語言或機型的變成技能培訓,特別是在使用新語言或新機器時。
編程需要技術積累,每個項目需要自己的標準組件庫。
精煉、充分和快讀的程序往往是戰略性突破的結果,而不僅僅是技巧上的提高。
戰略上的突破常來自于對數據或表的重表達。數據的表現形式是編程的各根本。
第10章 提綱挈領
對于計算機硬件開發項目,關鍵文檔是目標、手冊、進度、預算、組織機構圖、空間分配以及機器本身的報價、預測和價格。
對大學科系,關鍵文檔類似于目標、課程描述、學位要求、研究報告、課程表和課程的安排、預算、教室分配、教室和研究生助手的分配。
對于軟件項目,要求是相同的:目標、用戶手冊、內部文檔、進度、預算、組織機構圖和工作空間分配。
因此,即使是小型項目,項目經理也應該在項目早期對上述的一系列文檔進行規范化。
以上集合中每一個文檔的準備工作都將注意力集中在思索和對討論的提煉上,而書寫這項互動需要上百次的細小決定。正式由于它們的存在,人們才能從令人迷惑的現象中得到清晰、確定的策略。
對每個關鍵文檔的維護提供了狀態監督和預警機制。
每個文檔本身就可以作為檢查列表或者數據庫。
項目經理的基本職責是使每個人都向著相同的方向前進。
項目經理的主要日常工作是溝通,而不是做出決定,文檔使各項計劃和決策在整個團隊范圍內得到交流。
第11章 未雨綢繆
化學工程師已經意識到無法一步將實驗室工作臺上的反應過程移到工廠中,需要一個實驗性工廠來為提高產量和在缺乏保護的環境下運作提供寶貴經驗。
對于編程產品而言,這樣的中間步驟同樣是必要的,但是軟件工程師在著手發布產品之前,并不會常規的進行試驗性系統的現場測試。(現在,這已經成為了一項普遍得實踐,beta版本不同于有限功能的原型,alpha版本同樣是我所倡導的實踐)
第一個開發的系統對于大多數項目并不合用,它可能太慢、太大,而且難以使用,或者三者兼而有之。
系統的丟棄和重新設計可以一步完成,也可以一塊塊的實現,但這是個必須完成的步驟。
將開發的第一個系統—丟棄原型—發布給用戶,可以獲得時間,但是它的代價高昂,對于用戶,使用極度痛苦;對于重新開發的人員,分散了經理;對于產品,影響了聲譽,及時最好的再設計也難以挽回名聲。
因此,為舍棄而計劃,無論如何,你一定要這樣做。
開發人員交付的是用戶滿意程度,而不僅僅是實際的產品。
用戶的實際需要和用戶感覺會隨著程序的構件、測試和使用而變化。
軟件產品易于掌握的特性和不可見性,導致它的構件人員(特別容易)面臨著永恒的需求變更。
目標上和開發策略上的一些正常變化無可避免,事先為它們準備總比假設它們不會出現要好得多。
為變更計劃組織架構
程序員不愿意為設計書寫文檔,不僅僅是因為惰性,更多的是源于設計人員的躊躇—要為自己嘗試性的設計決策進行辯解。
為變更組件團隊比為變更進行設計更困難。
只要管理人員和技術人才的天賦允許,老板必須對他們的能力培養給予極大關注,使管理人員和技術人才具有互換性;熱別是希望能在技術和管理角色之間自由的分配人手的時候。
具有兩條晉升線的高效組織機構存在著一些社會性的障礙,人們必須警惕并積極的同它做持續的斗爭。
很容易為不同的晉升線建立相互一致的薪水級別,但同等威信的建立需要一些強烈的心理措施:相同的辦公室、一樣的支持和技術調動的優先補償。
組建外科手術隊伍的軟件開發團隊是對上述問題所有方面的徹底沖擊,對于靈活組織架構問題,這的確是一個長期行之有效的解決方案。
程序維護
程序維護基本上不同于硬件的維護,它主要由各種變更組成,如修復設計缺陷、新增功能,或是使用環境或配置變更引起的調整。
對于一個廣泛使用的程序,其維護總成本通常是開發成本的40%或更多。
維護成本受用戶數目的嚴重影響,用戶越多,所發現的錯誤也越多。
缺陷修復總會以20%~50%的幾率引入新的bug。
每次修復之后,必須重新運行先前所有的測試用例,確保系統不會以更為隱蔽的方式被破壞。
能消除、至少是能指明副作用的程序設計方法,對維護成本有很大影響。
實現設計的人員越少、接口越少,產生的錯誤也就越少。
系統熵隨時間增加
模塊數量隨大型操作系統版本號的增加而呈線性增長,但是收到影響的模塊以版本號指數的級別增長。
所有修改都傾向于破壞系統的架構,增加了系統的混亂程度(熵)。即使是最熟練的軟件維護工作,也只是延緩了系統退化到不可修復的混亂狀態的進程,以致必須要重新進行設計(許多程序升級的真正需要,如性能等,尤其會沖擊它的內部結構邊界。原有邊界引發的不足常常在日后才會出現。)
第12章 干將莫邪
項目經理應該制定一套策略,并為通用工具的開發分配資源,于此同時,他還必須意識到專業工具的需求。
開發操作系統的隊伍需要自己的目標機器,進行調試開發工作。相對于最快的速度而言,它更需要最大限度的內存,還需要安排一名系統程序員,以保證機器上的標準軟件是及時更新和實時可用的。
同時還需要配備調試機器或軟件,以便在調試過程中,所有類型的程序參數可以被自動計數和測量。
目標機器的使用需求量是一種特殊曲線:剛開始使用率非常低,突然出現爆發性的增長,接著趨于平緩。
拋開理論不談,一次分配給某個小組的連續的目標時間塊被證明是最好的安排方法,比不同小組的穿插使用更為有效。
如果目標機器是新產品,就需要一個目標機器的邏輯仿真裝置。這樣,可以更快的得到輔助調試平臺。即使在真正機器出現之后,仿真裝置仍可提供可靠的調試平臺。
主程序庫應該被劃分成:一系列獨立的私有開發庫;正處在系統測試下的系統集成子庫;發布版本,正式的分離和進度提供了控制。
在編制程序的項目中,節省最大工作量的工具可能是文本編輯系統。
系統文檔中的巨大容量產生了新的不易理解的問題,但是它比大多數未能詳細描述變成系統特性的短小文章更加可取。
自上而下、徹底的開發一個性能仿真裝置。盡可能早的開始這項工作,仔細的聽取“它們表達的意見”。
交互式編程
在某些應用上,批處理系統絕不會被交互式系統所替代。
調試是系統編程中較慢和較困難的部門,而漫長的調試周轉時間是調試的禍根。
有限的數據表明,系統軟件開發中,交互式編程的生產率至少是原來的兩倍。
第13章 整體部分
第4、5、6章所以為的煞費苦心、詳盡體系結構工作不但使產品更加易于使用,而且使開發更容易進行且bug更不容易產生。
許許多多的失敗完全源于那些產品未精確定義的地方。
在編寫任何代碼之前,規格說明必須提交給外部測試小組,以詳細的檢查說明的完整性和明確性。開發人員自己無法完成這項工作。
自上而下的設計(逐步細化)將會是最重要的新型形式化軟件開發方法。
每個步驟中,都盡可能使用級別較高的表達方法。
有時必須退回,推翻頂層設計,重新開始。
結構化編程中,程序的控制結構僅由支配代碼塊(相對于任意的跳轉)的給定稽核所組成,這種方法很好的避免了bug,是一種正確的思考方式。
對良好(對交互式調試做出快速反應)系統的正確使用,往往要求每兩小時的終端會話對應于兩小時的桌面工作:1小時會話后的清理和文檔工作,1小時為下一次計劃變更和測試。
系統調試(相對于單元測試)說話的時間會比預料的更長。
系統調試僅僅應該在所有部件能夠運作之后開始。
開發大量的輔助調試平臺和測試代碼是很值得的,代碼量甚至可能會有測試對象的一半。
必須有人對變更和版本進行控制和文檔化,團隊成員應使用開發庫的各種受控拷貝來工作。
系統測試期間,一次只添加一個構件。
第14章 禍起蕭墻
一天一天的進度落后比起重大災難更難以識別,更不容易防范和彌補。
根據一個嚴格的進度表來控制大型項目的第一個步驟是制定進度表,進度表由里程碑和日期組成。
里程碑必須是具體的、特定的和可度量的時間,能進行清晰的定義。
如果里程碑定義的非常明確,以至于無法自欺欺人時,程序員很少會就里程碑的進展弄虛作假。
對于大型開發項目中的估計行為,政府的承包商所做的研究顯示:每兩周進行仔細修訂的活動時間估計,隨著開始時間的臨近不會有太大的變化。期間內對時間長短的過高估計,會隨著活動的進行持續下降。過低估計直到計劃的結束日期之前大約三周左右,才會有所變化。
慢性進度偏離是士氣殺手,如果你錯過了第一個最終期限,確保完成下一條。
不存在關鍵路徑進度的替代品,使人們能夠辨別計劃偏移的情況。
PERT的準備工作是PERT圖使用中最有價值的部分,它包括了整個網狀結構的展開、任務之間依賴關系的識別和各個任務鏈的估計。這些都要求在項目早期進行專業的計劃。
每個老板同時需要采取行動的異常信息以及用來進行分析和早期預警的狀態數據。
狀態的獲取是困難的,因為下屬經理又充分的理由不提供信息共享。
老板的不良反應會對信息的完全公開造成壓制,相反,仔細區分狀態報告、毫無驚慌的接收報告、決不越俎代庖,將能鼓勵誠實的匯報。
必須有評審的機制,使所有成員可以通過它了解真正的狀態。出于這個目的,里程碑的進度和完成文檔是關鍵。
對于大型項目,一個隊里程碑報告進行維護的計劃和控制小組是非常可貴的。
第15章 另外一面
對于軟件編程來產品來說,程序向用戶所呈現的面貌—文檔,與提供給機器識別的內容同樣重要。
即使對于完全開發給自己使用的程序,描述性文字也是必須的,因為它們會被用戶—作者所遺忘。
培訓和管理人員基本上沒有能向編程人員成功的灌輸對待文檔的積極態度—文檔能在整個生命周期對克服懶惰和進度的壓力起促進和激勵作用。
這樣的失敗并不都是以為缺乏熱情或說服力,而是沒能正確的展示如何有效和經濟的編制文檔。
大多數文檔只提供了很少的總結性內容,必須放慢腳步,穩妥的進行。
由于關鍵的用戶文檔包含了跟軟件相關的基本決策,因此它的絕大部門需要在程序編制之前書寫,它包括了9項內容(目的、環境、范圍、實現功能和使用的算法、輸入—輸出格式、操作指令、選項、運行時間、精度和效驗)。
每一份發布的程序拷貝應該包括一些測試用例,其中一部分用于效驗輸入數據,一部分用于邊界輸入數據,另一部分用于無效的輸入數據。
對于必須修改程序的人而言,他們需要程序內部結構文檔,同樣要求一份清晰明了的概述,它包括了5項內容。(流程圖或子系統的結構圖、對所用算法的完整描述、對所有文件規劃的解釋、數據流處理的概要描述、初始設計中對已預見修改的討論)
為了使文檔易于維護,將它們合并至源程序是至關重要的,而不是作為獨立文檔進行保存。
最小化文檔擔負的3個關鍵思路:借助那些必須存在的語句,如名稱和聲明,來附加盡可能多的文檔信息;使用空格和格式來表現從屬和嵌套關系,提高程序的可讀性;以段落注釋,特別是模塊標題的形式,向程序中插入必要的記敘性文字。
程序修改人員所使用的文檔中,除了描述事情如何以外,還應闡述它為什么那樣,對于加深理解,目的是非常關鍵的,但即使是高級語言的語法,也不能表達目的。
在線系統的高級語言(應該使用的工具)中,自文檔化技術發現了它的絕佳應用和強大功能。
20年后的《人月神話》
核心觀點:概念完整性和結構師
一個整潔、優雅的編程產品必須向它的每位用戶提供一個條理分明的概念模型,這個模型描述了應用、實現應用的方法以及用來知名操作和各種參數的用戶界面使用策略。用戶所感受到的產品概念完整性是易用性中最重要的因素。
任何規模很大或非常緊急并需要人力較多的項目,都會碰到一個特別的困難:必須由多人來設計,但同時還要在概念上與單個使用人員保持一致。結構師是用戶的代理,在不可避免的對功能、性能、規模、成本和進度進行平衡時,卓有成效的體現用戶的利益。結構師就像電影的導演,而經歷類似于制片人。
將體系結構和設計實現、物理實現相分離,為了使結構師的關鍵任務更加可行,有必要將用戶所感知的產品定義—體系結構,與它的實現相分離,體系結構和實現的劃分在各個設計任務中形成了清晰的邊界,邊界兩邊都有大量的工作。(概念的完整性是產品質量的核心)