一、消除隱喻
1、隱喻
軟件開發這件事情,出現得很晚。距今只有幾十年的時間,關于它的定義,我們可以簡單地說:“就是把軟件做出來。” 這基本上等于什么都沒有說。而軟件開發究竟是怎么回事,大家也沒有搞明白,于是隱喻就派上用場了。當你要向一個完全沒有概念的朋友,解釋什么是軟件開發的時候,你無法向解釋建筑工程那樣把他帶到現場去看——案件開發的現場,你的朋友會以為軟件開發就是一群人坐在電腦前面打鍵盤——你只能打比方:它就像是造一幢樓,有基礎,有結構,有可以使用的房間,在這之前必須要設計,最后一樣要通過驗收,最終用戶就能夠住進去——哦,不,是可以使用軟件的各種功能。
這樣,你用上了一個隱喻:軟件開發就像建筑工程,或許極可以稱之為軟件工程。還有其它一些隱喻:比如手工作坊與軟件工藝。我們不會說建筑工程就像什么什么,它們都有自己鮮明的特點,不需要通過像什么什么來解釋。但是軟件開發,還是太年輕,也缺乏鮮明的特征,只能借助隱喻,我們才能向人們解釋它。在這條路上,很多人都已經走得太遠,隱喻不但被用來向外行解釋什么是軟件開發,居然被用來說服自己人,軟件開發就應該像那個比喻的對象一樣,具有類似的規范、過程、特征以及方法論。但是,比喻只能是比喻。軟件開發的方法論,只應該從軟件開發的本質推導出來,而不是從一些隱喻里抄襲過來。
2、另一個隱喻
佛教有一種說法:“佛法不過是一條渡船,過河之后,你就不再需要它了?!睂で筌浖_發的本質,也許還是需要隱喻的幫助,只是這些船能不能把你帶到彼岸,要仔細辨別。
設想這樣一個場景:在公安局的一個辦公室里,你的對面坐著一個目擊證人,而你是一個犯罪肖像畫家。這個證人在講述他還記得的罪犯特征,你一邊提問,一邊在紙上沙沙的畫著。一開始的提問與回答總是很概要性的。“圓臉”“不,很瘦的長臉”;“戴眼鏡?”“是的”。在紙上出現了大致的輪廓之后,對話變得比較瑣碎,“眼睛再小一點?”“鼻子比這個大一些?!睗u漸的,證人的話越來越少,而且不斷地端詳著紙上的那個人,而你還在做一些細小的修正。突然,證人激動地大叫起來:“就是他!就是這個人……”于是,你的任務完成了!
這個過程像不像軟件開發呢?有人也許會說,嗯,軟件開發就是這樣的。不!其實軟件開發,并不是這樣的,它應該是這樣的……
你的朋友,晚上到你家來了。“我昨天晚上做了一個夢,夢見了我這輩子見過的最美的女孩,你幫我把她畫出來吧?!薄八哪樖恰痹谝欢斡忠欢稳鐗羧缁玫拿枋鲋?,你開始畫起來,過程與前面有點類似,但是,似乎你的朋友沒有停下來的跡象,他不斷的要求你改進,希望這個她能夠更加完美。終于,他放棄了:“就這樣吧,雖然不是她,但是已經很像了?!蹦汩L吁了一口氣,但是,你的朋友瘋了,他懇求你把這個女孩變成一個活人,能跑能跳,能夠跟他交流,而且還能夠愛上他。沒想到,其實你不是人,而是上帝,而且你大發慈悲,竟然真的滿足了他的要求。終于,他滿意地回去了。但是,幾天之后,他又來了,他居然因為還不夠滿足,又來了!“上帝,”他懇求道,“你能不能夠幫我把她改一下,當我……”隨后的日子里,他不斷地找到你,要求你再完善完善他的女人。直到有一天,你發了一道閃電,劈死了這個貪得無厭的家伙。
不不,最后這一幕沒有出現,因為根據軟件開發及維護合同,你不能劈死你的客戶?。ㄎ腋掖蛸€,是個程序員,就想過這么干。)如果這個合同簽得不夠好,他真的有可能向你提任何要求。
3、消除隱喻
這個隱喻怎么樣?這是對軟件開發過程的一個好的描述嗎?不,它還不夠好,而且我們不可能通過修正完善這個隱喻,來得到一個對軟件開發的準確的描述。事實上,所有的隱喻都不夠好,都會扭曲軟件開發過程的真相,都會使我們對軟件開發的過程產生誤解。
為什么會這樣呢?為什么一個挺像軟件開發的隱喻會最終誤導我們呢?原因在于一個隱喻是一個完整的場景,這個場景中有很多相互交織的“概念要素”。當這些要素有很多在軟件開發中出現時,我們就會認為這個隱喻很貼切,而當一個隱喻越是貼切時,這個隱喻中的其他一些在軟件開發中不存在的要素,或者與軟件開發相矛盾的要素,就會打擾我們的分析,干擾我們的判斷。使得我們不再思考軟件開發本身,而是將思考建立在某個隱喻的場景中。這樣思考得到的結果,肯定存在著誤導的可能。再由于不同的隱喻互不相容——你無法想象一群工匠去建設現代化的高樓大廈,他們最多只能造些平房——因此,建立在各種隱喻基礎上的軟件開發,至今沒有找到適合自己的方法論,倒是不同的隱喻之間互相打得火熱。
4、分析各種現有的隱喻:
1)工程隱喻
在各種隱喻中,建筑工程與軟件開發的關系最為密切,這個隱喻與軟件開發的相似之處最多,因此影響也最為深遠。這個隱喻有四個要點:分解、分配、設計和階段化。
分解是一種極為深刻的思想,將整個過程分為幾個階段,將整個任務分解為幾個子任務,將系統分解為多個層次,多個模塊,將需求劃分為多個類型等等。這樣的思路,是解決復雜問題的唯一正確的方法,一團亂麻的需求、任務、項目、設計,根本不可能成功。但是分解也意味著它最好第一次就劃分正確,當任務被層層分解,變成了很多很多的子任務、模塊、子模塊、類的時候。你發現有一個子任務的分解有問題,修改的困難可能極為驚人,而軟件開發,在第一次就劃分正確的情況,幾乎絕無僅有。
分配與分解一樣,是工程隱喻所特有的,當一個需要完成的系統,已經被仔細的分解之后,分解的粒度會達到一個人能過獨立完成的范圍,然后根據現有的資源以及任務的前后依賴關系,合理的分配給各有不同能力和特長的人,沒有這樣的分配,項目同樣會一片混亂,而這個隱喻還包含一種(支配關系),存在分配的人與被分配的人,層層分解的任務與層層分解的人力資源,使得整個項目成為一個嚴密的金字塔結構,而這樣的結構,往往使得項目的應變能力與可能性,隨著項目的擴大而縮小。
基于以上的兩個要點,工程隱喻極為順理成章的推出了這樣一個結論:“必須嚴格的控制需求的變更,如果可能,將所有的變更都頂回去?!奔冋能浖こ痰乃枷胫校魏涡枨蟮淖兏际遣皇軞g迎的。
設計極為重要,無論是對于建筑還是對于軟件開發來說,都是這樣。但是設計與設計不同,在建筑行業,不體現設計師理念的建筑,會被稱為沒有靈魂的“水泥塊”。但是在軟件開發里,如果開發人員老是想著往程序里加入自己的東西,會被稱為過度設計。但是由于軟件開發對于建筑工程的模仿,過度設計變得比比皆是。
在建筑工程中,有著極為清晰的階段劃分,分析、設計、施工、驗收。最早的軟件工程,就是完全模仿這樣的階段而執行的。這樣的模仿,后果是嚴重的,因為這樣的階段不是軟件開發的特征,強行套用,大多失敗。隨后的改進似乎總也跳不出這個思維模式,就像用無數的直線去擬合一條曲線,用N多個正方形去拼出一個圓形。比如說螺旋式開發,在一個螺旋中,還要搞出四個象限,使得軟件開發的過程,不斷的重走這四個階段。但是,軟件開發的過程,真的是像建筑工程一樣嗎?
2)流水線隱喻
產生式編程和MDA,是所有“銀彈”承諾中,最為大膽的兩種。如果有一天世界大同,萬物升平,人間與天堂無異,那應該就是MDA的時代來臨了。這兩種思路的理論依據(如果這能稱之為理論的話)何在呢?其實還是一個隱喻:流水線。當然他們不會直接用普通的流水線來做比喻,而是一種比現代工業中最為先進的柔性制造流水線還要先進的“超級無敵自定義流水線”。用戶(對,就是最終用戶)可以選擇、定義并且畫出那個“軟件裝配圖”(UML之類的表示方法),就能直接組裝出用戶想要的軟件。但是,這樣的隱喻其實無法用于軟件開發,甚至無法用于工業生產的大多數領域。在工業領域,大多數流水線 還是用來生產有限種類的產品,種類多到一定程度之后,流水線的效率根本無法體現。當然成本優勢也無法體現。這還是一個零件的粒度問題,大粒度的零件組合,使得生產的可能種類減少,而小粒度的零件,又使得裝配成本與效率無法體現,這樣的兩難,在軟件開發上同樣存在,而且更加嚴重,所以這顆子彈,不可能是“銀彈”。
3)舞蹈隱喻
CMM本身不需要隱喻,它的理論基礎來源于純正的軟件工程,所有軟件工程有關的隱喻,CMM都用得上,但是CMM有它自身的特點,主要是在CMM的實施方面。我看到過一個關于CMM實施的隱喻:軟件開發就像跳舞,軟件過程改進就像是舞蹈編排,軟件開發人員在過程改進專家的知道下,就像舞蹈演員在舞蹈編導的知道下,學習新的節奏、動作。最后開發出令消費者滿意的軟件產品。就像舞蹈演員為觀眾帶來出色的表演。這樣的隱喻,為一個巨大的咨詢市場開辟了道路;最天才的舞蹈演員,也不能沒有編導的知道,所以想要公司提高CMM等級,就必須找專家來做咨詢,果然巧妙!但是這樣的隱喻,卻經不起推敲,舞蹈編排過程中,演員們排練的目標是達到編導的要求,如果演出的效果不好,自然由編導負責。但是軟件開發過程的改進,如果也是為了博得咨詢專家的滿意,到時候軟件開發出來不賺錢,那些專家可不會負責。他們早就賺到咨詢費,走人了。關鍵問題在于,過程改進只能是一種手段,它本身不能成為目的,更不能想當然的認為,完美的過程就一定能帶來完美的產品。舞蹈編導不是觀眾,沒有一個編導敢保證自己的這次創作,一定能贏得觀眾的好評,但是為什么現在CMM專家,就敢作出這樣的保證呢?當舞蹈演員在一個“三角形的舞臺上”,完美的跌落的時候,誰會為這樣的悲劇負責呢?
4)工匠、工藝隱喻
說到工程隱喻,現在大家自然會想到最近出來的《軟件工藝》這本書。如果工程的隱喻有問題,那么工藝怎么樣?如果工程師的隱喻有問題,那么工匠怎么樣?按照軟件工藝的說法:“如果項目中的成員不具備執行項目過程所必備的技能,那么縱有世界上最好的過程,也無法挽救項目失敗的命運;與此相反,真正優秀的開發者,能夠讓任何過程,發揮最大的作用?!闭娴木瓦@么簡單嗎?
工匠與工藝的隱喻,與工程相對,但是這樣的對立,并非如《軟件工藝》所理解的那樣,是由于不同的復雜程度而做出的不同的選擇。如果2000個人年的項目,我們應該采用工程的隱喻,5個人年的項目,我們應該采用工藝的隱喻,那么50個人年呢?500個人年呢?我們是不是有可能將兩種不同的隱喻像調雞尾酒一樣,選取適合的比例,然后調制起來呢?這樣具有的“顛覆性”的理論,我想作者也沒有考慮過如何與工程隱喻相調和吧?
在工藝隱喻中,還有幾個特點,質量、培訓、高手。
工藝隱喻,意味著工匠(程序員)會在自己的作品上簽名,并終生為之負責(這與XP是有區別的)這樣就能保證質量。但是我們知道,手工制作就意味著質量無法保證,第一次與第二次不同,第二次與第三次不同,現代工業比起手工業來最大的進步,就是能夠保證一個始終如一的質量水平。所謂為自己的作品負責的榮譽感,最多只能保證我能夠在“事發之后”找到人來修補,卻不能保證我免受這樣的損失。軟件質量更多的取決于一個開發團隊的能力,而不是他們愿意為之負責的決心與榮譽感。如果真的那么簡單,中國男足立了那么多次軍令狀了?早就該有成效了吧?
培訓開發人員,當然是非常重要的,但是現在軟件開發中較多使用的“新手”,并非“工程隱喻”的罪過。作者設想的學徒的過程,也并不與軟件工程相矛盾,這在日本的軟件工程實踐中,可以得到證實。不客氣的說,這樣的浮躁,不是軟件工程的責任,而是文化的問題??杀氖?,中國的軟件產業,較之美國,更為浮躁。
高手是寶貴的,但同樣也是稀缺的。一個公司或者一個項目團隊,不可能全由高手組成,再者,對于一個項目來說,所有的活都讓高手來干,也同樣是浪費。在這里還要指出作者的自相矛盾之處。一方面,作者強調“師—徒”式的培訓,另一方面,又想把低手從公司里趕出去。那么究竟該怎么做呢?如果一個項目內,低手比高手還要多(這是幾乎是必然的)。這樣的項目應該如何組織呢?任務如何劃分呢?作者沒有告訴我們。因為在工藝里面,學徒做的可能是毫不重要的,甚至是重復的勞動,只是為了學習。但是在軟件企業,誰來為這樣的學徒買單呢?
工藝的隱喻,新則新已,好就未必。這本書,就是那種“用隱喻來思考的產物”。真要照做,只怕危險。
5)敏捷的場景
敏捷開發與其它模式不同,它似乎沒有隱喻,但是,還記得我們是如何定義隱喻的嗎?一個隱喻是一個完整的場景,這個場景中有很多相互交織的“概念要素”。 當這個場景中多出了與軟件開發無關的要素時,就會誤導我們。敏捷開發是一個逼真的場景,這個場景不是像軟件開發,它就是軟件開發,它沒有多出任何東西,因此,這樣就完美了嗎?不,它卻少了很多要素。當一個逼真的場景,向你描述了一個成功的,但是卻卻少了很多要素的軟件開發項目時,這樣的場景同樣會產生誤導,會使你認為其他的要素,都是不重要的,至少是可以在大型項目中才需要考慮的。我說的要素,并非CMM的KPA,或者RUP里的關鍵活動,然后通過剪裁就能得到XP那樣的要素。而是指關鍵的概念,缺少關鍵概念,故事就會顯得虛假,那么在敏捷項目中,缺少了什么呢?時間概念,成本概念以及分工概念。
在一個又一個的迭代周期中,什么時候,項目算是完成呢?這個完成,由誰來決定呢?似乎敏捷開發面對的是一個User Story集合,多一些,少一些,都沒關系的。如果用戶給定時間,功能的多少,就得由開發人員決定。反之,如果用戶要求必須數量的功能,開發時間的多少就得由開發人員決定。這樣的項目,可以說簡直沒有壓力,這是咱們夢寐以求的項目,但是這可能嗎?
再說成本概念,同樣的道理,合同是在開發開始之前簽訂的,但是按照敏捷開發的場景,能開發出多少東西,需要多少時間,都是不一定的。那么成本如何確定?如果成本無法確定,這個合同可能就會有一方要吃虧,這樣的合同,誰去簽呢?
再說分工概念,敏捷開發是程序員提出的,而且完全是從程序員的角色出發,在他們的故事里,除了用戶,就只剩下了程序員,你也許會說,還有項目經理呢!但是,那只不過是一個名稱而已,他不過就是一堆程序員里最有權威的那個。那么其他角色呢?你在敏捷開發的故事里,看不到界面設計人員,看不到獨立的、專職的測試人員,看不到數據庫管理人員(隨著設計的浮現,也許項目進行到40%時,程序員中會有一個人,轉而承擔較多的數據庫管理的職責,但是這并不一定)看不到產品經理,看不到用戶手冊的編寫人員,看不到客戶培訓人員(XP認為客戶會和程序員一起工作,但是那些沒來的可能誰去培訓呢?)也許XP的支持者會說,“嗨,我們又不是要開發巨型項目。”但是我要說的是:“不管有多大的項目,一定會有不需要、也不應該程序員做的事情?!弊鳛橐粋€軟件開發的方法論,就必須包含對這些工作的探討,一個完全從程序員本位出發的,不考慮其他工作的方法論,不是一個完整的方法論,這樣的場景如果被普遍模仿的話,也是相當危險的。
6)銀彈隱喻
《沒有銀彈》如此著名,以至于無論它的贊同者還是反對者,都無法回避它的存在。但是銀彈究竟是什么呢?“沒有銀彈”究竟意味著什么呢?
首先,“銀彈”是一個隱喻,它的本意是能夠殺死人狼(一種怪獸)的武器。用在軟件開發里,銀彈是什么,用通過追問“什么是軟件開發中的人狼”來得到答案。在一個項目中(在一個村莊里),出現了一個困難(出現了一頭人狼),如果任由困難存在,項目就會失?。ㄈ绻麤]有辦法趕走人狼,村民就會受害),一種方法出現了,解決了這個困難,項目成功了(銀彈出現了,打死了人狼,村民獲救了)。所以我們可以這樣理解:銀彈就是能夠保證項目成功的方法。但是,如果Brooks真的這樣簡單的推出自己的結論,那么大家都會說;“廢話,誰不知道,沒有一種方法能夠保證項目的成功?”Brooks的水平當然遠不止此。但是很多人對《沒有銀彈》的理解,卻事實上到此為止了,然后他們就拿著這個結論,四處“傳道”開來。
Brooks更進了一步(或者說退了一步),他將保證項目成功的目的,弱化為提高項目效率的目的,并且給出了一個看起來能夠量化的標準“單一技術,十年之內,提高十倍以上的效率?!保煽啃院秃啙嵭愿緹o法量化,咱們先不討論)
但是,我們知道,如果一個論斷無法證實,又無法證偽,這個論斷就毫無意義。那么我們如何能夠檢驗他的這個論斷呢?首先我們要能夠明確,什么是單一技術?軟件工程算單一技術嗎?CMM體系算嗎?CMM里的一個KPA呢?UML算嗎?設計模式呢?XP呢?還是XP中的結對編程呢?怎么才算單一?沒有界定!也無法界定,包括Brooks,也不能告訴我們,什么算單一技術?
然后我們還要確定,如何比較開發效率,如何量化?嚴格的說,必須證實兩組能力,知識水平,人數,了解的信息都完全相同的人馬,在互不交流的情況下,同時開發一個項目,都達到了一組項目的目標(即不是不夠,也不是超過),然后兩組人的開發時間,是否相差十倍。
再者,當我們要證明單一技術的功效時,必須保證這兩組人馬只在這一項技術上有區別,其他都一樣。
最后,當我們要證明十年之內的差別時,還要保證十年后的這組人馬,與十年前的那組人馬使用相同的軟件、硬件設備。(十年前是什么操作系統?WIN32?CPU呢?486?)這樣的研究,才能夠算是精確的驗證。但是這樣的驗證,沒有,也不可能有人去進行,自然這樣的論斷也就毫無意義!
可笑的是,居然有人,當真去尋找銀彈的證據,并且興奮的宣稱找到了,最近還有一家著名的公司,出版了一本的著名的雜志,名字就叫《銀彈》!但是,最可笑的還在于,Brooks居然還寫了一篇《再論沒有銀彈》,宣稱自己的論斷,已經基本上成立了。
如果事情到此為止,那么Brooks也不過就是跟大家開了個玩笑罷了。但是Brooks更進一步指出:“軟件開發分為根本問題與次要問題,根本問題占軟件開發的90%的比重。而且很難被很好的解決。”一方面,我們要說:“這樣的認識很有必要”,另一方面,我們也要說:“這樣的論斷,毫無疑義?!币驗樗炔荒鼙蛔C實,又不能被證偽。90%從何而來?如何證實?我們無法得知。我相信,10年,10倍,根本就是他隨口說出的一個數字,同樣的,90%也不過是一個“印象”。當不得真,作不得數,也無法用來指導我們的實踐,更無益于我們提高軟件開發水平。這樣的玩笑文字,竟然風行世界,備受矚目,的確是軟件開發的方法論,還處于蒙昧的“隱喻時代”的最好證明!
二、追求定論
這篇文章的標題就叫定論,那么什么是定論呢?就是不再有異議的結論。就是每個人都能同意的結論。A方法比B方法好,好在哪里?好多少?為什么好?我們追求定論,就是追求一種有效的比較和評價標準。
軟件開發有那么多方法,有那么多過程,那么多“最佳實踐”,但是卻從來沒有定論,為什么沒有定論呢?因為軟件開發的“方法學”還處于蒙昧的“隱喻時代”,各家各派,都從自己的隱喻出發來看問題,所謂“雞同鴨講”,指的就是這種情況。
但是追求定論的努力,并不是從我才開始的。在此之前也有人追求過,這樣的努力,統稱為——“軟件度量”,這當然是典型的西方觀點:能夠量化,就能夠比較;能夠比較,就能夠改進。這樣的觀點,一點沒錯,但是還少了前面一句,首先要理解,才有可能量化。如果我們不能真正理解軟件開發的本質,就無法判斷哪些可以量化,如何量化,以及度量得出的數據又該如何解釋,數據的重要性如何?不能回答這些問題,追求定論,依然是不可能的。
請允許我先把話題扯遠一點,談一談管理學,談一談泰勒以及泰勒之后的管理學。
1.“科學管理”與“泰勒式管理”
泰勒是毫無疑問的科學管理之父,為什么我會起這樣一個標題呢?“科學管理”和“泰勒式管理”還有什么不同嗎?
所謂“科學管理”,在我看來,就是以科學的方式研究管理。而泰勒正是以這樣的方式研究如何進行管理的第一人。在泰勒之前的所有管理,無論好壞,都只是停留在經驗的層面,而經過泰勒的科學方式的研究,管理也終于可以當之無愧的稱之為一門科學,而泰勒以這樣的研究方式,得出的結論,就可以稱之為“泰勒式的管理”,這兩者并不能等同。
我們知道,一個科學體系,包含兩個方面,假設(公理)與邏輯推論。從哲學上來說,我們把假設稱為世界觀,而把推出結論的方式,稱為方法論。無論誰來研究管理,只要他運用的是科學的邏輯的方法,我們就可以稱其為“科學管理研究”,而如果他的初始假設與泰勒的不同,那么他得出的結論,就不是“泰勒式的管理”,但卻肯定是“科學管理”。
無數的人可以有無數種不同的假設,那么我們如何判斷哪一種假設更為合理,得出的結論更有價值呢?答案是:通過解釋和預言。一套理論,必須自洽,也就是僅僅依靠本體系內已知的,有限的假設,通過邏輯推理,能夠解釋所有已知的、相關的現象。其次就是通過推理得出的預言,要能夠接受驗證,并且不被證偽。兩種不同的假設得出的不同的預言,就能夠通過驗證,判斷他們的勝負。而在預言沒有被證偽前,該理論體系,就和其他尚未被證偽的理論一樣,是有效的。而所謂的偽科學,就是只能解釋,無法給出預言的理論。
“泰勒式的管理”,首先被證明是有效的。通過發現或者發明某個具體崗位上的最佳辦法和最佳工具,大幅度的提升了工作的效率。以搬運生鐵為例,工場工人裁減數從400~600下降到140,人均工作量從每天16噸,上升到每天59噸,人均收入從每天1.15美元上升到每天1.88美元,平均費用從每噸0.072美元,下降到每噸0.033美元。另外還有更為重要的效果是在工人本身,工人中喝酒的人大為減少,浪費錢的人也少了,因此都比以前生活得更好,他們把自己的頂頭上司和教師,看成是最好的朋友而不是強逼他們做工的人。
泰勒的研究方式十分科學,他尋找并假設了影響工人效率的幾大因素:技能、工具、激勵、外部環境。并一一研究這些因素對于效率的影響,進而通過實驗的效果來得出結論。這所有的一切,都沒有什么錯,只是當時的科學研究,尚無法證偽泰勒的諸多假設。而這些假設,也只有通過更進一步的科學研究,才有可能證偽。這個研究在管理學歷史上大大有名,被稱之為:“霍桑試驗”,由喬治.埃爾頓.梅奧主持。
“霍桑試驗”原本是一次典型的“泰勒式的科學試驗”。根據科學的思維模式,一個待研究的系統,接受很多輸入變量,也產生很多輸出變量,在嚴密的、可控的、量化的輸入變量的變化情況下,觀察輸出變量的變化,通過一系列的數據去分析系統可能的數學模型,而“霍桑試驗”的第一階段,就是要研究各種外界工作條件,對生產率的影響。他們把女工分為試驗組和控制組(始終不改變條件,以作對照)然后每次試驗只改變一項條件,比如照明條件,工間休息時間和頻率,工作日長度等等。按照試驗計劃,第3、第10和第13試驗期的工作條件將完全相同。但實際記錄到的產量,卻分別是:2500、2800、3000。這是完全不符合預測的,也不是簡單的測量誤差可以解釋的,更令人不解的是,對照組的產量也在持續的提高。
這究竟說明了什么問題?到底是哪里出錯了?梅奧是這樣分析這個問題的:他認為存在著兩種研究方法,“臨床式研究”和“實驗室”式研究?!芭R床式研究”的目的在于對事物的本質形成正確的認識,并學會處理實際材料的技能,在此基礎上,進一步區分哪些方面可以繼續進行更詳細的“試驗室”式研究。如果隨后的“試驗室”方法由于排除了某些未知的重要因素而歸于失敗,研究人員就應當回到“臨床式研究”中去,以便弄清自己忽略了哪些因素。
而在我看來,所謂的“試驗室”研究,就是在不動搖基本假設的前提下,進行邏輯推理,對照現實,豐富理論的細節。只有當這一理論的預言失敗,或者出現無法解釋的現象時,基礎假設才會被置疑,研究者需要重新去尋找能夠解釋現有現象的新的假設,這樣的研究往往非常困難,而且一旦成功就一定意義非凡。這在科學哲學上,被成為“范式的轉換”。
科學范式的轉化,從來都不是科學的失敗,而是科學的重要的,甚至是跨越式的進步。在管理學上,從“經濟人”假設轉換為“社會人”假設,就是這樣一次重要的進步。但是卻有很多人,既不了解科學進步的規律,也不了解管理學的演變,卻簡單的認為人際關系學派的興起,就意味著科學管理學派的失敗和錯誤,并進而認為科學管理學派的失敗,就意味著以科學方法研究管理底失敗,這樣的誤會,實在是太不應該了。
2.探尋假設
在探尋軟件開發以往的方法論背后的假設之前,首先要指出的是,這些假設很難被發現,不是說它們不存在,而是這些加上很少被看成是假設,往往作為理所當然的一部分,被排除在常規的思考范圍之外。讓我們來看幾段大家都很熟悉的文字吧。
“大多數大型軟件項目都沒有達到預期的目標,交付推遲,預算超支,功能不完善。許多軟件項目徹底失敗了?!?br> ——FDD
“當前,軟件開發的情況并不理想。很多系統最終不能交付,或者最終交付的系統經常性地發生延期或者超出預算;系統常常不能滿足用戶的需要,其結果是不得不一遍又一遍地開發。”
——AM
“許多軟件項目,或許應該說大部分軟件項目實際的開發周期比預期的要長,實際的花費比預期的要多,實現的功能比預期的要少。這造成了嚴重的質量問題。”
——某一本CMM的書籍
怎么樣,是不是似曾相識?我敢肯定,你不只在一本書的序言部分,看到過類似的文字。無論這本書寫于70年代、80年代、90年代還是21世紀。情況一直都是這么“糟糕”。有趣的是,這些書都會在“痛說軟件開發現狀”之后,轉而兜售自己的方案。當然,在Brooks的《沒有銀彈》之后,他們兜售的語氣謙虛了很多。作為一個文化現象來說,這非常值得細細品味。但是,我們需要追問的是:為什么?
難道軟件開發是全世界最難的事情嗎?為什么失敗率如此之高?如果我們在使用了層出不窮的手段之后,還是不能提高成功率,我們應該怎么辦?其實也很容易,當年我的一個老板就想出了一個絕妙的辦法,絕對簡單,就是將我自己的工作量估算乘2!我們的項目幾乎從不失敗,總是能夠在計劃時間內完成。于是我想,如果我們把全世界的軟件項目估算都乘以2的話。也許軟件開發這個行當,也能成為一個有尊嚴的職業。大家都會生活得更加幸福。
“這實在是太過分了!”也許有人會說:“你這是自欺欺人、掩耳盜鈴、移靶就箭!”但是且慢生氣,生氣的人應該冷靜下來反思:如果目標如此難以達到,會不會是目標有問題呢?當然,事情沒有這么簡單,如果把目標直接乘2來提高成功率,全世界的老板都會發瘋的!我們要做的,是提高估算的準確性。
“嘖嘖,還以為是什么了不得的結論呢!這個問題早就有人研究了,不就是IT度量嗎?”一定會有人站出來這么說。但是,IT度量的研究,提高了估算的準確度了嗎?思路在這里被卡住了。直到有一天,我看到了量子力學中的“測不準原理”!
“測不準原理”告訴我們,在物理學中存在著很多對變量,當我們想要精確測量其中一個變量時,對另一個變量的測量誤差就會越來越大。但是,在軟件開發里,我們是進行估算,而不是進行測量,而且也不存在一個和工作量相對的變量,當工作量估算準確時,它會變得模糊。簡單地套用物理定律是行不通的,思路又卡住了。
突然有一天,我問自己:“假設工作量已經估算精確到了99.9999%會出現什么情況?”“不可能!”“如果真的達到了這個精確度了呢?”我對自己窮追不舍。“那只有一種情況,就是項目已經接近完成了!”“我們估算完成時,項目接近完成,這意味著什么呢?”“這毫無意義,沒有一個項目會花這個多時間來估算,而且如果要這樣估算,估算本身要花多少時間都不知道?!蓖?!我已經想通這個問題了。
估算工作量也是一種工作,同樣也需要工作量。對于大多數任務來說,估算所花費的工作量,相對與總的工作量來說,幾乎可以忽略不計,或者說:為了能夠得到一個有指導價值的估算值,所花費的工作量,幾乎可以忽略。但是,對于軟件開發來說,這只是一個假設。我們假設對于軟件開發的工作量估算,同樣只需要花費極少的工作量。但事實上,當我們花費三五天時間得出結論,這個項目需要20個人月時,我們估算的誤差,可能(甚至一定)會大于200%這就是我們這個行業顯得如此失敗的原因。
為什么這個行業與其它行業不同呢?在建筑行業,工程概預算的費用,不超過總費用的百分之一、甚至千分之一。為什么軟件項目的估算做不到這一點?因為兩個原因:
一是由于技術的復雜性,以及這個行業技術的飛速發展(也可說尚未定型),同樣的需求,采用不同的設計,不同的技術實現,工作量相差極大。僅僅根據需求,無法估算出工作量。而隨著概要設計、詳細設計的層層分解,工作量估算的精確度的確會提高,但是對于軟件開發來說,項目也越來越接近完成了。
二是由于需求的變動性以及不可預測性。早期的估算、設計甚至代碼,都有可能作廢。一個項目實際上重做了N遍,在軟件開發領域也是常有的事。估算的誤差,自然也就大到不可思議了。
然而,絕大多數人沒有想過這個問題,大家都自然而然的根據最初的工作量估算,來評價以后的工作。
工作量/人員效率=項目時間
工作量×單位成本=項目成本
缺陷總數/工作量=軟件質量
我們根據最初估算的工作量,來推出項目的時間、成本和質量目標,我們假設工作量估算只花費可以忽略不計的工作量,我們依據這些目標來衡量項目的成敗,然后我們發現大多數項目都失敗了,然后我們研究技術、改進過程、尋找銀彈!最終,我們發現自己還是這么失?。?/p>
是到了徹底反省我們的假設的時候了。
(注:Brooks在《人月神話》中指出了另一個重要的假設:人與月是可以互換的。)
三、軟件開發的特征
軟件開發究竟是怎么一回事呢?在我的前一個連載《敲響OO時代的喪鐘》里,我也討論到了軟件開發的實質,自己引一段來用用。
軟件開發的定義:“軟件開發,就是在一個受到限制的環境中,利用環境提供的可能性,修改或添加環境允許的各種狀態,去滿足某一組需求?!?/p>
- 軟件開發所處的環境,不僅僅是一個限制,同時也是一個可能性。軟件的能力,局限性與硬件的能力,比如說,如果計算機沒有喇叭,那么任何軟件都不能使計算機播放音樂。但是,另一個必須考慮的方面是,同樣有能力發聲的計算機,要想使他播放音樂,可能很容易,也可能很困難。用專業一點話來描述就是:“有些硬件的API設計很合理,有些則非常愚蠢。”由于我們對于軟、硬件的定義是一個連續體,因此,這個觀點不只是可以用來評價硬件API設計,也可以用來評價語言、虛擬機、框架、平臺等等軟件的一個方面的優缺點——是否有利于二次開發,這是一個重要的評價標準。
- 修改、添加狀態,比較拗口,其實就是編程的意思。在一個受限制的范圍內編程,我們需要考慮很多東西,語法、接口、規范、內存大小諸如此類,當然,不同級別的,不同領域的編程,需要考慮的限制是有巨大差別的。軟件開發的水平高低也就體現在,滿足同樣的需求,有些方法速度更快,有些方面卻要慢很多。而軟件開發的方法的選擇,受到很多因素的影響:環境限制,經驗多少以及對于需求的了解程度等等。
- 滿足需求,是啊!提起這個需求,每一個程序員都會有好多的苦水要倒出來。為什么滿足需求就這么難呢?因為,對于程序員來說,那是另外一個世界(這是比較客氣的說法),那些提需求的家伙根本不懂怎么說話(這個說法稍為激烈一些),那是一些不知道自己要什么的蠢貨(你遇到過這樣的用戶嗎?)作為程序員,我知道我有很多同行,非常苦惱于與客戶談需求這樣的任務——“至少電腦不會出現前后矛盾的邏輯錯誤”——這就是做程序員的難處。如果我們不僅僅是抱怨的話,也必須承認,程序員是非常挑戰的職業,一個好的程序員,不但得是軟件開發領域的專家,還得是他開發的那一類軟件所在領域的專家。但事實上,其他行業的人,只需要做一種專家就能夠混得很好了。
軟件開發的實質,與軟件開發的特征之間,還是有區別的。畢竟我的前一篇文章,是從技術的角度出發來看軟件開發,而現在我們的要討論的是從管理的角度來看待,它又有哪些特征呢?
軟件開發的管理特征,在外行看來,也就是一堆人在做個東西。但是,軟件開發的獨特之處就在于,軟件開發是由一堆獨特的人,以獨特的方式,做獨特的東西。我們先來看看軟件開發,遇到了哪些獨特的困難:
1、溝通困難:同為軟件開發,可能面對的思維模式,是完全不同的世界。比如二進制的世界,函數的世界、邏輯的世界、過程的世界、對象的世界、二維表的世界等等等等。在這些不同的世界中開發軟件,需要的思考方式、思維習慣都是不同的。開發項目大到一定程度以后,不同的世界必須在一個完整的項目中和諧并存,這些差異,有時候就會帶來溝通障礙。再加上技術與需求世界之間的差異,溝通成為一個非常重要的工作。軟件開發中的人與事,如何才能有效溝通,是一個非常重大的課題。
2、控制困難:程序員都是些怪人,至少都是些聰明人。要讓他們聽話,很難啊。一個項目,要想順利進行,程序員們能夠接受的,必須是“穩定而合理的命令”。而在軟件開發過程中,往往需求頻繁變動,領導層層疊疊,用戶花樣百出,計劃一改再改。程序員們經常會接到朝令夕改的命令,而且還來自于那些莫名其妙,連說話的邏輯都成問題的家伙。如何才能知道,那些小伙子是在嚴格地執行命令而不是在那里磨洋工呢?
3、評價困難:要控制,必須要能夠賞善罰惡,但是在軟件開發中,何為善?何為惡?如何評價一個程序員的工作?我們當然可以在項目計劃該結束的時候,再去問他們,做完了嗎?但是如果他們那時候沒有完成,再要挽救就來不及了。必須在項目開發過程中建立即使有效的反饋機制。以小而高密度的評價手段,來對開發過程進行較為準確的控制,這一切,都必須建立在合理的評價機制的基礎上。但是,這樣一套評價機制,非常困難。什么才算是好的需求分析?好的代碼?好的設計?好的測試用例?沒有定論。舉個例子:兩三年前,在項目中加入EJB的成分,越多越好。現在呢?設計人員,隨時都可能被人指責濫用EJB。這風向變得也太快了。
4、估算困難:這個在上一章我們也討論到了,軟件開發與其它行業的一個重大區別,就在于對于軟件開發的估算成本,不能忽略不計。想要估算變動劇烈的項目的時間、人力、成本,簡直就是不可能的任務。
怎么辦?
討論軟件開發的特征,需要站在一個大的背景下來看。我以前考過PMP,在PMBOK中,軟件項目管理,是作為項目管理下的子課題來討論的??纯聪旅孢@張圖:

按照PMBOK的知識結構圖,PMBOK已經告訴了我們那么大一個園。而要進一步搞好軟件的項目管理,我們只需要再掌握相關應用領域的知識和實踐,就ok了。
這其實是大多數項目管理的理論,對于軟件項目管理的看法,所有的項目,都是項目。軟件項目與大多數其它項目,大同而小異。至于差異部分,往往被歸入“風險管理”的領域,就算是“一切盡在掌握了”。
而事實上,軟件項目與其它項目的差異是如此之大,以至于由量變而導致了質變,使得我們以傳統的工程項目管理的方式來管理軟件開發項目,注定是要失敗的。
我們來看看這樣一個關鍵詞:“迭代”。這是其它的項目管理中,基本上不可能出現的概念,而在軟件項目管理領域,卻是幾乎每一種方法學中,都要極力強調的概念。這就是最大的區別。如果我們能夠搞清楚迭代的本質,也就能夠搞清楚軟件項目與其它項目的本質區別了。
在我看來,在軟件開發的過程中,引入迭代,就是承認,軟件開發需要承受大大小小的失敗,而減少失敗的辦法,就是不跑步,不走路,盡可能的爬行,這樣就算跌倒,也不會跌得太重。我們來看一個有趣的數據。這是我在竹筍炒肉的blog上看到的一段話。
1994年,由于其非凡的軟件開發能力和優秀的軟件質量,SEL成為第一個因軟件過程的成就而贏得IEEE獎勵的軟件開發組織。與普通的軟件開發組織相比,在同樣的軟件開發條件下,NASA所開發的軟件的質量要好10到20倍。
這個成就是如何得出的呢?那么是怎樣的項目呢?我搜索了一個google,找到另外一段話:
To put it a little differently, the average MIS shop would need about 14 calendar months and 110 staff-months to deliver a 100,000 line-of-code MIS system, and it would typically contain about 850 defects when delivered. The NASA SEL would deliver a system of that size with about the same amount of time and effort, but it would contain only about 50 defects.
也就是說,10萬行代碼的一個MIS系統,他們花了110個人月,一共14個月,才完成。平均下來,每個人每天大約需要寫30行代碼!如果這樣也算成功的軟件項目管理的話,我以后只要將所有的項目工作量估算,乘以10,就能同樣拿到IEEE的獎勵了,如果我的老板允許的話。
各位一定非常驚訝(如果是讀過前面幾篇連載《定論》的人),怎么這就完了呢?看著架勢,應該還早啊。
是啊,按照原定的計劃呢,的確是還早,但是那樣的寫法,我自己都不知道會寫到何年何月去了,因此打算結束這個東西,把我要表達的想法,一口氣跟大家說了,也是一種解脫。
總結我的想法,主要有以下幾點:
1、現有的軟件開發方法,都不是定論,不過是你說你的好,我說我的好罷了。要能夠得到定論,必須要有一種能夠判斷方法好壞的方法。也就是說,能夠判斷一個方法,用或不用,有多少好處。幾個方法比較,哪個能夠勝出的“檢驗標準”。
2、要能夠檢驗軟件開發方法的優劣,必須基于對于軟件開發本質的正確認識,這樣才能量化兩個因素:軟件需求的復雜程度以及軟件開發的實際工作量。而現在的軟件復雜度的度量,并未區分“需求”與“實際”的不同,或者“代碼行數”,或者“功能點”,都是如此。
3、在能夠正確度量需求復雜度與實際工作量之后,我們會發現,過去那么多號稱是為了保證軟件順利開發的手段,往往只會壞事,耽誤事。但是,完全不提前設計的方法,也并不可取。
原文寫于:2005年11月,最后其實是草草結束,并沒有寫完。當然,后續我也一直在思考,直到最近,我又另外寫了一篇《從軟件工程到研發管理》,希望能夠把這個問題思考明白。