大多數(shù)程序員,都極度痛恨寫文檔。Coding是愉快的,而Write是痛苦的。有一部分原因,其實(shí)是要?dú)w咎于程序員自身,以我的經(jīng)驗(yàn),很多程序員往往會(huì)“艱于表達(dá)”,尤其是用“文字、圖表、PPT、Word”之類的Office Document來表達(dá)。當(dāng)然,還有一部分原因,是由于很多項(xiàng)目開發(fā)實(shí)踐中,文檔的前后矛盾、形式主義、反復(fù)修改、歧義重重,常常讓程序員們抓狂。
UML是一個(gè)比較好的工具,但是,僅僅靠UML,是無法將項(xiàng)目的知識(shí)描述清楚的。也有不少項(xiàng)目組在引入了UML之后發(fā)現(xiàn),文檔的工作量不但沒有減少,而是更多了。隨著項(xiàng)目的進(jìn)展,需要維護(hù)的設(shè)計(jì)文檔數(shù)量,也更多了。也因此造成了更多的前后矛盾,形式主義,反復(fù)修改。
根本的痛苦,并不在于一開始寫一份文檔,而在于所有寫下的文檔,都必須跟隨項(xiàng)目的進(jìn)展而隨之變化。當(dāng)我們寫出來的文檔越多,需要被持續(xù)維護(hù)的文檔也就越多,需要反復(fù)檢查文檔間的可能存在的矛盾也就越多,所有扔出去的石頭,最后都會(huì)落回到自己頭上。
于是,還有不少項(xiàng)目組,將文檔工作與代碼工作截然分開,文檔就寫一次,用來應(yīng)付上面的管理層,而代碼自管自的繼續(xù)開發(fā)。對(duì)于小型項(xiàng)目來說,這其實(shí)是一個(gè)不錯(cuò)的權(quán)宜之計(jì)。但是一旦項(xiàng)目越來越龐大、復(fù)雜。所有的隱性的知識(shí),都僅僅存在于程序員的腦子里,所有成文的東西,都可能是錯(cuò)的,而真實(shí)的情況,卻隱藏在代碼之中。如果代碼質(zhì)量再糟糕一些,后來維護(hù)的朋友,就遭遇火坑了。
文檔,寫還是不寫,這是一個(gè)問題!
還記得測試驅(qū)動(dòng)開發(fā)嗎?為自己的每一個(gè)方法,每一個(gè)類,都寫出單元測試來。不但如此,更加徹底的做法是,在寫代碼之前,先寫測試用例。這樣才能保證不會(huì)忘記寫測試用例。更大的好處在于,這樣有助于思考、有助于獲得更加完善的設(shè)計(jì),有助于寫出更加高質(zhì)量的代碼,有助于安全的重構(gòu),有助于自動(dòng)化的持續(xù)集成實(shí)踐??傊呛玫貌荒茉俸玫囊豁?xiàng)開發(fā)實(shí)踐。
這一實(shí)踐之所以可行,就在于他將繁雜的集中的測試工作,分解為日常的,必須不斷進(jìn)行的工作。當(dāng)你每天都在寫測試用例,當(dāng)你的每一個(gè)測試用例,都能夠與代碼完全對(duì)應(yīng)時(shí),壓力反而減輕了,工作量也更少了,更重要的,一些優(yōu)良的習(xí)慣也因此被養(yǎng)成了。
在兩年前,我要開始一個(gè)全新的P2P網(wǎng)絡(luò)電視項(xiàng)目時(shí),也在考慮關(guān)于文檔的問題。當(dāng)時(shí)我發(fā)現(xiàn)了Open Source的WikiPedia。這是一個(gè)PHP的WIKI,最大的應(yīng)用是維基百科全書。因此,這個(gè)項(xiàng)目的質(zhì)量就絕對(duì)值得信賴。我就將它拿過來,作為我們
項(xiàng)目文檔管理的工具。
用Wiki來管理項(xiàng)目文檔,基于以下一些考慮:
通信博客——通信人自己的博客!m cJZF| ~文檔是項(xiàng)目的知識(shí),這些知識(shí)必須集中管理、容易獲取、人人可以編輯。
6cu-u1y,CTL0通信博客——通信人自己的博客! ?/GCmE+p~項(xiàng)目在生長,代碼在增加,文檔也必須能夠跟隨項(xiàng)目自然生長,強(qiáng)行劃分設(shè)計(jì)階段和開發(fā)階段,是不可取的。
'b @*E,D|3z2KAH:S0#ub5sUip5O}T)c:}0Wiki不是傳統(tǒng)的項(xiàng)目文檔,而是一個(gè)應(yīng)交流需要,可能隨時(shí)增刪改的知識(shí)庫。項(xiàng)目組的成員,遇到問題,就應(yīng)該首先查看Wiki,如果這是Wiki中沒有,那么他應(yīng)該找人詢問。而那個(gè)知道答案的人,如果他不想再今后不斷的回答同一問題,就應(yīng)該把這個(gè)答案寫入Wiki,這就是Wiki條目增長的自然動(dòng)力。通信博客——通信人自己的博客!+S&?,R'n2b jx
通信博客——通信人自己的博客!g5ww7dC2L7I8L傳統(tǒng)文檔最大的問題在于浪費(fèi),而Wiki通過持續(xù)修改,按需提供的方式,保證了所有寫下的文字,一定有超過一個(gè)人需要讀它。通信博客——通信人自己的博客!%fJE}V6u5u+cS
在Wikipedia的基礎(chǔ)上,我又做了一些增強(qiáng),以更好的輔助項(xiàng)目的管理。
通信博客——通信人自己的博客!l(Ys{]2Q`Include功能,增加include標(biāo)簽,可以在一個(gè)條目中,引入其他條目的全文,而不是僅僅增加一個(gè)link。
cu5U^7UTK2}0B@%GZm9]m+di0文檔的層次結(jié)構(gòu),當(dāng)項(xiàng)目的文檔條目逐漸增加,分門別類的條目,更加便于查找,也可以有效的避免條目重名的問題。通信博客——通信人自己的博客! U$x3x6zj1`} E
通信博客——通信人自己的博客!7V8Kf{8p1@H一個(gè)Click,就能夠創(chuàng)建新一個(gè)條目,用于填寫當(dāng)天的工作安排。通信博客——通信人自己的博客!E"nQl}'C
Camu-Bjn(mP0每日15分鐘文檔制度,基于“填寫當(dāng)日工作”的功能,我規(guī)定每個(gè)項(xiàng)目組成員,每天要花三個(gè)5分鐘來寫文檔,早上的5分鐘,填寫當(dāng)日工作計(jì)劃。中午的5分鐘填寫上午的工作情況,下班前的5分鐘,填寫下午的工作情況。這樣,每天的文檔工作相當(dāng)輕松,但是文檔能夠保證持續(xù)的跟隨項(xiàng)目成長下去。更進(jìn)一步的,這樣的制度,對(duì)于項(xiàng)目的進(jìn)度控制,也很有幫助。通信博客——通信人自己的博客!,i7l+jf.Fwp
0s+w}7B(\0User Case條目驅(qū)動(dòng),所有分解出去的User Case,在分配到責(zé)任人之后,該責(zé)任人的第一項(xiàng)工作,就是在Wiki中寫下對(duì)于這個(gè)User Case的理解。隨后項(xiàng)目進(jìn)展,也應(yīng)該持續(xù)的維護(hù)這個(gè)條目。通信博客——通信人自己的博客!pJ}'? u4{ d faAP"H
通信博客——通信人自己的博客!+b^RiX'tB#A [K同時(shí)進(jìn)行Bug的管理,Bug也作為Wiki中的條目,以便于和其他條目項(xiàng)目引用。
3x+q"o_8b9Q0h{^2s+J0每次Check In CVS時(shí),必須寫注釋。這是更加細(xì)節(jié)的文檔,然后我還做了一個(gè)小程序,能夠自動(dòng)的從CVSTrac中讀出當(dāng)天Check In代碼的注釋。供每個(gè)人在寫當(dāng)天文檔的時(shí)候引用。
m!rd#VkC1Y0 總而言之,我對(duì)于項(xiàng)目文檔的看法,并不是非此即彼的極端主義者。在我看來,好的項(xiàng)目文檔管理政策,應(yīng)該有助于集中團(tuán)隊(duì)知識(shí)和智慧,同時(shí)不要讓程序員痛苦和反感。這樣才叫做有效的項(xiàng)目管理。仿造Martin Fowler的著名文獻(xiàn)《持續(xù)集成》,我給這篇Blog起這樣一個(gè)名字《軟件開發(fā)文檔的持續(xù)集成》,希望能夠引發(fā)更多的、更深入的思考。