文檔代碼同源,顧名思義,就是文檔和代碼都寫在源代碼文件里。這樣可以:1.修改代碼的時候就及時修改文檔,使得文檔和代碼及時保持一致;2.閱讀代碼時,增加代碼的可讀性。評審代碼的時候,尤其是修改時后,即對文檔一同評審。結(jié)合研發(fā)流程、評審的配合,可促使代碼、文檔的開發(fā)逐步走向一一對應,逐步向高質(zhì)量發(fā)展,同時也能提高團隊素質(zhì)。
一、問題起源
互聯(lián)網(wǎng)行業(yè)和一些物聯(lián)網(wǎng)行業(yè),軟件開發(fā)都提倡敏捷開發(fā),敏捷開發(fā)為何物?(附件介紹。)這里列出敏捷的宣言:
個體和互動 高于 流程和工具
工作的軟件 高于 詳盡的文檔
客戶合作 高于 合同談判
響應變化 高于 遵循計劃
也就是說,盡管右項有其價值,
我們更重視左項的價值
很多公司所謂的敏捷,很大程度上就是開發(fā)代碼,應該有的必要文檔可能都是不全的。因為要趕工,因為市場的巨大壓力,文檔代碼對應不上司空見慣。更有甚者,壓根就沒有文檔。這里造成了很多隱性的問題。
1.沒有合適的文檔,隨著時間的推移,一些技術(shù)要點,設(shè)計要求,設(shè)計思路隨著時間,盡歸塵土。這些通過市場、技術(shù)、商業(yè)等各個維度試錯的來的寶貴經(jīng)驗和知識無法傳承,是一種浪費,更是一種低效組織的表現(xiàn)。
2.關(guān)鍵崗位的開發(fā)人員一旦流失,產(chǎn)生的技術(shù)、知識斷崖,短期內(nèi)難以補足。
3.新人的進入,需要長時間的消化理解。
4.代碼的評審和檢查不嚴格,想怎樣改就怎樣改,只要外在的功能是正常的。那就是沒有問題的。為很多問題埋下了伏筆和隱患。
敏捷中有一個觀點,竊以為是無比正確的:沒有什么文檔比代碼更準確。但這個觀點又是比較危險的:
1.可運行的功能正確的代碼的確是沒有什么比其更準確的了。但是,代碼畢竟是寫給機器運行的,個人的能力、習慣等都不一致,其他人理解起來必然費勁。有一些飽含技巧的寫法可能是需求的需要,也可能是個人炫技的需要;其他人又怎能看透全部呢?代碼畢竟是非自然語言,有時候能看得懂代碼,是以犧牲速度為代價的,總之,問題比較多。
2.潛臺詞是,文檔不重要。
總之,文檔、代碼的問題,不僅困擾著程序員,也困擾著公司。那么怎么找一個合適的方法解決這個問題呢?
二、解決方案
想想程序員為什么寫或修改代碼?我想即使是為了拯救地球和全宇宙,從微觀上講,也符合下列情況之一:
1.實現(xiàn)需求。是的,這怕是程序員寫/修改代碼的第一大原因了。
2.抓Bug。程序員實現(xiàn)需求的副產(chǎn)品:八阿哥(bug)。把它送走,是我們改代碼的第二大驅(qū)動。
3.其他原因,諸如設(shè)計不足,可理解性不好啦,模塊用起來不爽啦,封裝不夠簡潔實用,有一些程序員還有潔癖。這可能都是修改代碼的原因。但從本質(zhì)上來講,也是滿足需求的修改。每個產(chǎn)品需求定義之外,都有灰色邊界。需求提得越清楚,灰色地帶就越少。閱讀性不好、模塊用起來不爽,可能在需求里沒有提出來。有些作為需求提出來,也是可以的。比如說,對于產(chǎn)品某個模塊的要求,必須使用什么標準技術(shù)或模塊,或者必須滿足下一代的復用等。至于潔癖,團隊沒有定義團隊的寫法,那么沖突修改是必然的。
代碼中所有的修改都可歸為這三類,更進一步,大部分應該是前兩類。開源世界有一個很好用的工具是Doxygen。它的作用就是把代碼里的特殊注釋抽取出來變?yōu)槲臋n(一個類似Latex的工具,非所見即所得的文檔編輯工具)。我們的思路就是,利用Doxygen工具,將代碼和文檔的開發(fā)變?yōu)橥竭^程。由于文檔含在代碼里,也意味著Doxygen的文檔也是文本,在版本庫的管理下,能精確的看到每一個比特的修改。為了不耽誤說正事,后面有文章做一個的Doxygen介紹。這里簡單的介紹一下Doxygen。
Doxygen 是一個程序的文檔產(chǎn)生工具,可將程序中的特定注釋轉(zhuǎn)換成為說明文件。比如說對于一個
以上經(jīng)過Doxygen抽取編譯后,會生成一個綜合性文檔,可在里面查到:
即使我們不用doxygen編譯,寫在代碼里的注釋,也是不影響我們理解的。只是編譯后,查閱起來更方便。
這是我們實現(xiàn)文檔代碼同源的基礎(chǔ)。但文檔代碼的同源不僅僅是把代碼和文檔合成一個源代碼文件。我們要做得是:
1.需求要和代碼中的各個實現(xiàn)模塊對應起來;
2.文檔的修改、代碼的修改同步進行,每天由工程師交叉檢查并給出評語;
3.高級技術(shù)人員定期整理代碼問題,形成案例;
4.如果是公共模塊,項目進行過程中,定期整理其Bug,問題,維護其可用性。
2.1 需求和代碼對應
開發(fā)一款產(chǎn)品,首先要提需求,需求開發(fā)出來,大抵是這樣的:
需求提出了方方面面的要求,一般,需求的分配表也跟在后面,用于指示這個需求都由那些模塊實現(xiàn)。
緊接著下來是軟硬件的概要或者詳細設(shè)計,有些公司為了節(jié)省,就只有設(shè)計;有的干脆就連設(shè)計也省了,走“敏捷'路線。這個并不重要。
Doxygen支持自由頁面,可以輕松的寫一個Python的小工具,將excel的需求表轉(zhuǎn)化為 txt的文本文件,被doxygen所識別。
這樣做得好處:
1.需求只要經(jīng)常用版本庫追蹤,誰改了一個字,改了什么都會清清楚楚。
2.程序員查閱需求會更加簡便。同時,每日的檢查強調(diào),需求的修改,可能會帶來代碼的修改;Bug的修改可能帶來代碼的修改,需求的修改。從而強調(diào)需求的定義作用,主動維護需求的前后一致。
如模塊中編寫時,說明實現(xiàn)了哪些需求。
這些都是超文本標簽,點擊后迅速轉(zhuǎn)到需求定義處可查看。
2.2 每日檢查
該方法的核心內(nèi)容,就是每日檢查。一個程序員每天的代碼產(chǎn)量最多可達上千行(非每日平均產(chǎn)量)。如果是更改Bug,可能一天大部分的時間用于分析跟蹤上。正真的修改并不多。每日提交版本庫后,由其他程序員或者部門經(jīng)理檢查代碼及修改,檢查的內(nèi)容如下:
1.代碼修改是否有效,符合組織內(nèi)部的規(guī)定;
2.文檔和代碼是否對應。
與需求類似,寫一個Excel表格,包含:模塊;檢查人;日期;問題描述的跟蹤表;檢查完成后提交至版本庫,由對應的工程師承接修改。
每次檢查,檢查文檔、代碼的問題,通過版本庫可以很輕松的跟蹤相關(guān)的修改。并定位修改是否合理。
2.3 飛行檢查
為了防止檢查流于形式,定期對一些具有代表性的問題做總結(jié)。高級技術(shù)人員需要做一些飛行檢查,定期的抽查檢查表以及文檔代碼的對應情況。并從問題中選出有代表性的案例,收集成案例,用于團隊的提升和警示。
2.4公共模塊
一個有積累的公司,應該不會從0開始構(gòu)建自己的項目??偸嵌喽嗌偕儆行┓e累的。代碼同源的模塊如何被復用呢?首先,公司內(nèi)部要有完善的版本控制機制。任何代碼,全局只有一份。對于svn的版本庫、git的版本庫,有不同的辦法。(svn可以使用externals屬性,保持全局唯一的庫文件。git可以使用subtree, submodule的辦法建立全局唯一的庫文件。)由于庫代碼導出后,文檔和庫跟著走的,也不存在這不對應的問題。如果發(fā)生庫的修改,因為全局就一份庫的代碼。更改完畢,全局都會跟著修改。所以,庫的提交需要更為慎重。需要建立更為嚴謹?shù)男薷拇_認機制。
無論怎么更改,只要每天保證文檔、代碼對應。下載最新的源代碼,使用Doxygen編譯,則可得到最新的文檔。
三、補充說明
文檔代碼同源的思路,可解決實踐中的文檔代碼不一致的問題,但這不是最終目的。長期堅持,達到一個良好的開發(fā)習慣和開發(fā)氛圍。從而提高項目交付質(zhì)量和內(nèi)部的管理水平。達到組織和個人的共同成長。
四、遺留問題
這個方法,是有適用范圍的,我在軟硬結(jié)合的項目以及一些純軟件的中小型項目上實施,取得了一些比較好的效果。尚未在比較大型的項目上使用。
另外,方法也需要不少工具配合。
1.如果內(nèi)部沒有需求管理工具的廠商,可以直接用excel管理,然后自己寫個python工具轉(zhuǎn)換一下。如果內(nèi)部有需求管理工具的公司,應該都可以將需求導出成excel,然后通過工具轉(zhuǎn)換成doxygen接受的文檔。
2.內(nèi)部的檢查一定要每天堅持,這才是核心中的核心。每天并不耗時,但是卻很重要,量變引起質(zhì)變。
3.庫的管理需要svn、git等版本控制工具的強力支持,這個需要被管理公司有一定的版本管控水平和能力。
最后,文檔中提到的方法和工具,歡迎與我討論。我會陸續(xù)的將一些工具方法整理出來發(fā)給大家。