12.05.2007

再讀「人月神話」(1)

最近因為指導後進看這本,人月神話:軟體專案管理之道,順便也自己複習了一次,才又重新領悟一些事,也把自己已經淡忘的原則,又重拾回來。

順手這次也將心得寫了起來。

能夠超過20年的書,就是經典。

在寫的過程中,剛好也正在面試人,有些來面試的"好手",顯然對寫程式很有信心,姑且不論是否厲不厲害,對於所謂產品/專案裡做個程式設計師要做的工作,似乎只停在寫"Code"的能力,也因此對於這段話,感慨尤深:


程式 / 產品 / 系統

產品是一個可以讓任何人執行、測試、修改和擴充的程式,並且適用於多種操作環境,以及不同情況的資料。這表示,程式必須經過徹底的測試。以確保它是可靠的,也意味必須準備、啟用一個豐富的測試案例(test case)資料庫,以便於探究並記錄輸入資料的範圍與各個邊界值(boundary)的執行情形。

最後,一個程式要晉升為軟體產品,還必須有完整的文件以指引別人使用、修改或擴充它。根據經驗,我估計就同一項功能而言,完成一項軟體產品的成本至少是寫一個程式的三倍。


若要完成軟體系統(programming system),這是彼此交互運作的一組程式集合,這些程式之間,有律定共同的資料格式與合作模式,組合起來就是可以完成某項複雜工作的一套完整設施。

要做出軟體系統,程式之間必須定義出明確的介面(interface),而每個程式的輸出入都要符合介面所規定的語法(syntax)和語意 (semantic)。所有相關的程式必須整合在一起,以任何設想得到的組台進行測試,隨著越來越多的組合情況,測試的涵蓋面也必須越來越廣才行,麻煩的是,即使組件(component)都已個別除錯完畢,但兜在一超時仍有可能引發意料之外的交互作用,而這種錯誤往往非常棘手,也將耗費更多的時間。
就同一項功能而言,完成軟體系統中的一個組件的成本至少是寫一個程式的三倍,而且,如果系統中的組件數量越多,成本就可能更高。
遺憾的是,大部分對於如何寫好文件以及測試這兩件事的概念時非常薄弱的......
也因此我們可以見到目前IT市場上,號稱會寫程式的一大堆,可是有做專案/產品觀念的工程師,可能不到2成。

雖然說"寫程式的樂趣"很令人嚮往:

為什麼寫程式很有趣呢?寫程式的人期望從中得到什麼樣的樂趣呢?
首先,是創造的趣味。

其次,今人感到愉快的,是我們所創造出來的東西竟然對別人有用。

第三,是那種打造精巧機制時,類似推理、解謎的過程,今人迷戀。把彼此聯動的零件組合起來,眼看著成果真的按照了我們原先所設想的方式微妙地在運作,受程式操控的那台電腦不但擁有彈珠台或自動點唱機的迷人魅力,並且將之發揮到淋漓盡致。

第四,是持續學習的樂趣。這種工作具有不重複的特質,也不知為什麼所要解決的永遠是全新的問題,而解決問題的人總是可以從中學到些東西:有時是在實務方面,有時是在理論方面,或兩者都有。(遺憾的是,很多工程師會一點東西,就自稱已經會了...)

最後,是在如此易於操控的介質(tractable medium)上工作的快樂。
但現實的生活,寫程式的苦難更是一定會遇到的:

首先,你必須表現得非常完美。

其次,由別人設定目標,由別人供給資源,由別人提供相關的資訊,你很少能夠自行安排自己的工作細節與工作目標,套句管理上的術語,你所擁有的權力並不足以承擔你所扛下的責任,不過,好像在任何領域中,真正能把事情做好的職位都未曾在名義上得到與責任相稱的權力。實際上的情況是:你得先把工作做成功,才會得到越多實質上的(相對於名義上應得的)權力。

還有一點,就是得依賴別人才能成事,對系統程式設計師而言,這種獨特的情況也非常今人痛苦。他得依賴別人所寫的程式,可是別人的程式往往是個不良的設計,程式寫得很菜,移交也不完整(缺程式碼或測試案例),文件錯誤百出,於是他必須花很多時間去找出錯誤並加以修正,在理想的世界,這些東西都應該是完整的、隨手可得、隨即適用的

雖說為了偉大的構想而從事設計是份樂趣,但尋找多如牛毛的臭蟲(bug)就只能算是份差事,這是另一個苦難。任何創作活動的背後都免不了附帶枯燥、沉悶、耗時的辛勤工作,寫程式也不例外。
還有,你會發現除錯工作應該是呈線性緩慢地收斂,或者更糟,但其實,最後出現的錯誤才最難纏,也會比早期發現的錯誤花費更多的時間才能找到,所以測試的工作也就拖拖拉拉沒完沒了。

最後一項苦難,就是你所投入心血進行的工作可能要花上許多時日,等產品做出來的時候(或之前),卻發現它就要落伍了。


接著來看看人月的問題吧!

軟體專案進行不順利的原因或許很多,但絕大部分都是肇因於缺乏良好的時程規劃所致。
這種情形相當普遍,是什麼原因造成的呢?

第一,我們目前的時程預估技術還非常不成熟,糟的是,這些不成熟的技術背後都反映出一個假設,亦即,一切都會進行得很順利,但這實在是大錯特錯。
(這真的沒有例外,位置越高,就越容易犯這種錯誤。)

第二,我們的預估技術誤把工作量和專案進度混為一談,這又隱含了另一個假設,以為人力和工時可以互換。(這是在說機器人吧。)

第三,由於我們對自己所做的預估都無法篤定,所以專案經理通常缺乏Antoine餐廳廚師那種委婉的堅持。(真的超過8成的工程師,在品質的要求下,自己也估不出到底要做多久。)

第四,時程進行缺乏監控,並把其他工程領域上被證明可行或慣用的技術套在軟體工程上進行改革。
(軟體管理工程,還是...太嫩了。)

第五,當發現時程延誤的時候,自然而然的(也很典型的)反應就是增加人手,但這簡直就是火上加油,只會把情況弄得更糟,結果是火燒得更大,於是又加更多的油讓它燒,惡性循環,最後以災難收場。(IT界的老爺們,個個都是縱火狂......)

第二個錯誤的想法,是來自於預估和排定時程所使用的人月(man-month),這正是一般用來衡量工作量的單位。
成本確實會隨著人力與工時的乘積而變,但工作的進度可不是如此,所以用人用來衡量工作規模的大小是危險的,也是一個容易遭到誤解的迷思(myth),使用人月的前題必須是在人力和工時可以互換的情況之下
(遺憾到底的是,這些老經驗的PM們總是一錯再錯....)

只有當工作可被切分(partition),而且投入工作的人彼此不用溝通(commun ication),人力和工時的互換才算成立。

當一份工作因具有連續性的限制而不可切分時,就算投入再多的人力,也不會對時程有所影響生小孩就是需要九個月,你叫多少個媽一起生都一樣,軟體工程就是像這樣的工作,因為它必須除錯,而除錯就具有連續性的本質。

當工作可被切分,但是每個子工作之間需要溝通時,為這些溝通所付出的代價必須納入對工作量的計算之中,因此,這種情形就是做得再好,也比不上人力和工時可以互換的情況。

接著,我們就會開始專案的惡性循環:
就學理來說,我們缺乏可供估計之用的資料。
由於我們對自己所做的預估都無法篤定,所以在面對管理上或顧客的壓力時,我們通常都缺乏堅持的勇氣。

Brooks定律:在一個時程已經落後的軟體專案中增加人手,只會議它更加落後。
(大部分的PM,因為無法預估所需要人手的能力,只會要求補人、補人,然後只有成本增加,進度卻無法有效進展......)

欲增加軟體專案的人手,總共必須付出的代價可分為三方面:
  • 工作重新切分本身所造成的混亂與額外
  • 工作量新進人員的訓練
  • 新增加的相互交流

唉!20年前如此,20年後仍如此。

沒有留言: