代碼審查(Code Review)是軟件開發中經常使用的手段,和QA測試相比,它更容易發現和架構以及時序相關等較難發現的問題,還能夠幫助團隊成員提升編程技能,統一編程風格等。
**1. 代碼審查要求團隊有良好的文化**
團隊須要認識到代碼審查是爲了提升整個團隊的能力,而不是針對個體設置的檢查「關卡」。
「A的代碼有個bug被B發現,因此A能力不行,B能力更好」,這一類的陷阱很容易被擴散從而影響團隊內部的協做,所以須要避免。
另外,代碼審查自己能夠提升開發者的能力,讓其從自身犯過的錯誤中學習,從他人的思路中學習。若是開發者對這個流程有抵觸或者反感,這個目的就達不到。
**2. 謹慎的使用審查中問題的發現率做爲考評標準**
碼審查中若是發現問題,對於問題的發現者來講這是好事,應該予以鼓勵。但對於被發現者,咱們不主張使用這個方式予以懲罰。軟件開發中bug在所不免,過分苛求自己有悖常理。更糟的是,若是形成參與者怕承擔責任,不肯意在審查中指出問題,代碼審查就沒有任何的價值和意義。
**3. 控制每次審查的代碼數量**
根據smartbear在思科所做的調查,每次審查200行-400行的代碼效果最好。每次試圖審查的代碼過多,發現問題的能力就會降低,具體的比例關係以下圖所示
(我想這是根據實現狀況而定,如結合文檔來評審,那麼代碼多一點也不要緊)
咱們在實踐中發現,隨着開發平臺和開發語言的不一樣,最優的代碼審查量有所不一樣。可是限制每次審查的數量確實很是必要,由於這個過程是高強度的腦力密集型活動。時間一長,代碼在審查者眼裏只是字母,無任何邏輯聯繫,天然不會有太多的產出。
**4. 帶着問題去進行審查**
咱們在每次代碼審查中,要求審查者利用自身的經驗先思考可能會碰到的問題,而後經過審查工做驗證這些問題是否已經解決。一個竅門是,從用戶可見的功能出發,假設一個比較複雜的使用場景,在代碼閱讀中驗證這個使用場景是否可以正確工做。
使用這個技巧,可讓審查者有代入感,真正的沉浸入代碼中,提升效率。你們都知道看武俠小說不容易瞌睡,而看專業書容易瞌睡,緣由就是武俠小說更容易產生代入感。
有的研究建議每次樹立目標,控制單位時間內審覈的代碼數量。這個方法在咱們的實踐中顯得很機械和流程化,不如上面的方法效果好。
**5. 全部的問題和修改,必須由原做者進行確認**
若是在審查中發現問題,務必由原做者進行確認。
這樣作有兩個目的:
(1)確認問題確實存在,保證問題被解決
(2)讓原做者瞭解問題和不足,幫助其成長
有些時候爲了追求效率,有經驗的審查者更傾向於直接修改代碼乃至重構全部代碼,但這樣不利於提升團隊效率,而且會增長由於重構引入新bug的概率,一般狀況下咱們不予鼓勵。
**6.利用代碼審查激活個體「能動性"**
即便項目進度比較緊張,沒法徹底的進行代碼審查,至少也要進行部分代碼的審查,此時隨即抽取一些關鍵部分是個不錯的辦法。
背後的邏輯是,軟件開發是很是有創造性的工做,開發者都有強烈的自我驅動性和自我實現的要求。讓開發者知道他寫的任何代碼均可能被其餘人閱讀和審察,能夠促使開發者集中注意力,尤爲是避免將質量糟糕,乃至有低級錯誤的代碼提交給同伴審查。開源軟件也很好的利用了這種心態來提升代碼質量。
**7.在非正式,輕鬆的環境下進行代碼審查**
如前所述,代碼審查是一個腦力密集型的工做。參與者須要在比較輕鬆的環境下進行該工做。所以,咱們認爲像某些實踐中建議的那樣,以會議的形式進行代碼審查效果並很差,不只由於長時間的會議容易讓效率低下,更由於會議上可能出現的爭議和思考不利於進行如此複雜的工做。
**8.提交代碼前自我審查,添加對代碼的說明**
全部團隊成員在提交代碼給其餘成員審查前,必須先進行一次審查。此次自我修正形式的審查除了檢查代碼的正確性之外,還能夠完成以下的工做:
(1)對代碼添加註釋,說明本次修改背後的緣由,方便其餘人進行審查。
(2)修正編碼風格,尤爲是一些關鍵數據結構和方法的命名,提升代碼的可讀性。
(3)從全局審視設計,是否完整的考慮了全部情景。在實現以前作的設計若是存在考慮不周的狀況,這個階段能夠很好的進行補救。
咱們在實踐中發現,即便只有原做者進行代碼審查,仍然能夠很好的提升代碼質量。
**9.實現中記錄筆記能夠很好的提升問題發現率**
成員在編碼的時候應作隨手記錄,包括在代碼中用註釋的方式表示,或者記錄簡單的我的文檔,這樣作有幾個好處:
(1)避免遺漏。在編碼時將考慮到的任何問題都記錄下來,在審查階段再次檢查這些問題都確認解決。
(2)根據研究,每一個人都習慣犯一些重複性的錯誤。這類問題在編碼是記錄下來,能夠在審查的時候用做檢查的依據。
(3)在反覆記錄筆記並在審查中發現相似的問題後,該類問題出現率會顯著降低
**10. 使用好的工具進行輕量級的代碼審查**
「工欲善其事,必先利其器」。咱們使用的是bitbucket提供的代碼託管服務。
每一個團隊成員獨立開發功能,而後利用Pull Request的形式將代碼提交給審查者。複審者能夠很方便在網頁上閱讀代碼,添加評論等,而後原做者會自動收到郵件提醒,對審閱的意見進行討論。
即便團隊成員分佈在天南海北,利用bitbucket提供的工具也能很好的進行代碼審查。
程序員
Google的代碼之因此優秀緣由其實很簡單:他們很是重視代碼審查。代碼審查並非Google獨有的,它被公認爲是一個很好的(提升代碼質量的)手段,不少人已經在平常開發中採用代碼審查。但我尚未看到哪一家大公司(像Google這樣)應用得如此普遍。在 Google,任何的產品或者項目代碼在檢入(代碼倉庫)以前都須要進行有效的審查。數據庫
每一個人都要參與代碼審查,並且這裏我指的不是非正式的審查:它是軟件開發環節中很是重要並且通用的規則。不只是產品代碼,全部的代碼都須要進行審查。審查代碼不須要投入不少的精力,可是(與不作審查相比)產生的效果倒是天壤之別。編程
關於代碼審查(code review),Jonathan Danylko 的見解是「代碼要常常檢查(包括自查和其餘同事檢查)。不要把別人的檢查,當作是對代碼風格的苛求。應該把它們看做是有建設性的批評。對我的來講,常常檢查你的代碼而且自問,「我怎樣才能寫得更好呢?」 這會加速你的成長,讓你成爲一個更優秀的程序員。」設計模式
**你能從代碼審查中收穫什麼?**瀏覽器
事實顯而易見,有另一我的檢查即將提交的代碼,可以幫助找到bug。這是代碼審查衆所周知且常常被說起的好處。但依據個人經驗,這是最沒有價值的一個好處。人們確實能夠在代碼審查中找到bug。然而坦率地說,在代碼審查中找到的bug絕大多數都是一些代碼做者花上幾分鐘就能找到的小bug。那些真正須要花時間才能找到的bug在代碼審查中是檢查不到的。緩存
代碼審查最大的好處在於它是一種社交的途徑。若是你編程的時候就知道會有同事檢查你的代碼,那麼你的程序會有所不一樣。你寫的代碼會更加整潔,有着較好的註釋,結構也組織的不錯——由於你知道會有人來檢查你的代碼,並且你很在乎他們的意見。若是沒有代碼審查,你知道代碼會在最後纔會審查。由於不是立刻就要檢查,因此對你而言並不緊迫,於是你不會想着先自檢一遍。安全
代碼審查還有一個更大的好處,就是能夠分享知識。在不少的開發團隊中,每一個人都會負責而且專一於一個核心模塊。除非別的同事負責的模塊出現問題致使本身的代碼不能運行,不然他們是不會去關注別人的工做。這樣產生的結果是,每個模塊的代碼只有一我的比較熟悉。假如事不湊巧,那位程序員正好休假或者離開了公司,那麼沒有人瞭解那些代碼了。若是有代碼審查的環節,那麼至少會有兩我的熟悉代碼——代碼的做者和審閱者。審閱者雖然沒有做者對代碼那麼瞭解——可是他一樣熟悉代碼的設計和結構,這些信息是無價之寶。數據結構
固然,沒有什麼事情是那麼簡單的。以個人的經驗看來,要作好代碼審查須要一段時間練習。我注意到經驗不足的審閱者一般會落入一些代碼審查的陷阱,這些陷阱每每會形成不少的麻煩,給那些但願嘗試代碼審查的人們留下了壞印象,成爲了他們採納代碼審查的一個主要障礙。架構
代碼審查最重要規則是對即將提交的代碼中查找問題——你須要作的就是確認代碼是正確的。而一般會犯的一個錯誤,也是剛剛接觸代碼審查的新手容易犯的一個錯誤,即審閱者會判斷這段代碼是否按照本身思路來實現。併發
當有一個問題須要解決時,一般會有幾十種的辦法。當選定一個解決方法時,會有百萬種代碼實現。所以,做爲一個審閱者,你的工做不是確保代碼是按照你的方式來編寫的——由於這是不可能的事情。審閱者的工做是確保原做者編寫的代碼是正確的。若是你沒有遵照這個規則,你可能會處處碰壁,審查結束時你的心情很糟糕,對你來講確定不是一件好事情。
**問題在於這是不自覺就會犯的一個錯誤。**假定你是一個程序員,當你在看一個問題的時候,你會獲得一個本身的解決方案——而且你認爲你看到的就是這個問題(應該採用的)解決辦法。若是想要成爲一名好的審查者,你須要知道這是不對的。
**第二個誤區就是人們感受必定要說點什麼(纔算是作了代碼審查)。**代碼的做者花了不少的時間和精力來編寫代碼——你難道不該該說點什麼嗎?
答案是:你不該該。
若是隻是說「哦,這看起來這不錯!」,這永遠沒錯。反之,若是你不斷地去查找一些「問題」並加以指責,那麼我確定你的信譽會蕩然無存。若是你不斷地去製造一些事情來講些什麼,那麼代碼的做者會認爲,當你的言論只是爲了不冷場。今後,你的意見不會受到重視。
**第三個誤區就是速度。**你不該該匆忙完成一次代碼審查——可是也不要拖延。你的同事在那裏等着你的審查結果。若是你和同事不肯意抽出時間來作代碼審查或者一直拖延,你們會對此次的審查感到厭煩,也會認爲之後的代碼審查也只會帶來麻煩。看起來好像代碼審查會打斷你的工做,其實沒必要如此。你沒必要要在別人要求你審查的時候立刻丟掉手頭上的事情。可是在幾個小時以內,當你工做中間休息的時候——喝杯茶,去一下洗手間或者聊聊天,散散步。當你再回來工做的時候,你能夠開始並完成這個代碼審查。若是你這麼作了,沒有人會站在你身邊一直等着你給出審查結果。
在軟件工程領域裏代碼審查能夠結束程序員之間無謂的爭執。開發者經常會由於一些愚蠢的小事鬥嘴,冒犯對方,甚至是在Q&A問答以前抓住Bug而喋喋不休,爭執老是圍繞在你左右。OK,千萬不要誤會個人意思,由於咱們有理由相信代碼審查絕對是個不錯的好方法。緣由以下:
1. 越早發現bug也就意味着可下降項目成本。無須釋放一個修復補丁,由於它正處在開發階段。
2. 代碼變得愈來愈重要。
3. 知識貫穿於你的團隊中,再也不像之前那樣一大塊代碼只有某一我的知道。
4. 開發者須要加倍的努力。若是開發者知作別人要對他的工做進行評估時,就會採起額外的努力作好工做,同時他還喜歡用文檔註釋標出異議。
現在,在21世紀的今天不少項目都沒有使用代碼審查。**本文將提供8條準則**,供開發者學習與參考。
1. 永遠別忘了TDD
再確認測試代碼前,先找別人幫你檢查下是否無誤。在別人作以前儘可能檢查出bug而且將其處理好。代碼審查最重要規則是對即將提交的代碼中查找問題——你須要作的就是確認代碼是正確的。
2.儘量的自動化
這裏有幾個很是好的Java工具好比:PMD, Checkstyle, Findbugs等等。問題是當利用這些工具查找後人們還肯花時間去作代碼審查嗎?
使用這些工具前,爲這些工具制定一套細則是很是重要的。這可以確保你使用同一個代碼審覈標準從而區別於那些常被用於20世紀老式的代碼審查規範。在理想的狀態下,這些工具可運行在各類版本控制系統上經過hook審查每一個代碼。若是該代碼很差將被阻止在外。
3.尊重設計
在我開始從事Java項目早期時,用代碼審查的方式已爲時已晚。由於當你檢查代碼問題時實際上給你的設計形成了缺陷。設計模式被誤解,一些繁雜的附屬物質混入進來或者開發者脫離了主題。
審查會混亂你的觀點。或許你會反駁:「這是代碼審查而不是設計審查」。這時一些爛攤子必然會接踵而至。爲了不這些問題發生,咱們改變了設計的初衷。代碼審查會牽連到不少面,不管是設計仍是設計審查。事實上,咱們經過設計審查要比代碼審而得多的衝擊要多的多。設計須要更高的質量和靈感,咱們應該避免一些複雜的思惟。
4. 統一的風格指南
即便是使用自動化工具(諸如Checkstyle,Findbugs等)也應避免沒必要要的風格衝突,你的項目應該具有有風格指南。(在儘量的狀況下)堅持Java協議的規範標準。嘗試着爲你的項目介紹制定一個「詞典」,這就意味着,當涉及這個代碼時,查看該代碼的用法和環境是否適宜,這些都很容易被檢測出。
5. 挑選適宜的工具
若是開發者都在使用Eclipse開發工具( Eclipse IDE插件Jupiter),你能夠經過你的方式來查看代碼、調試代碼甚至可以使用Eclipse IDE上的一切東西當來幫助你在審查代碼時更加的便捷。可是,若是你們沒有使用同一個IDE(或者該IDE沒有給你的工做帶來方便)你能夠考慮Review Board. ,它是個不錯的選擇。
6.請記住每一個項目都不一樣
也許你在採用之前的項目方法工做,可是,請記住每一個項目之間是不一樣的。每個項目都有特定的架構(高併發或是高分散),有特定的文化(或許不少人喜歡使用Eclipse),並使用特定的工具(maven or ant)。難道你想照葫蘆畫瓢?OK,請記住,不一樣的項目有不一樣的工做方法。
7.懂得取捨
代碼審查須要積極和細緻而不是賣弄學問。你會由於一些細微的雜事讓你緊張而致使項目失敗或是花費公司成本嗎?記住,千萬不要這樣。理清頭緒,換個角度想一想,改變本身的心態而不是記掛着去改變別人。
8. Be buddies
在我看來,稱之爲「buddy reviews」(別人會叫「over the shoulder」)很是好。A buddy review是指與其餘團隊成員每隔一到兩天以非正式的形式討論,而且快速的瀏覽(5-10分鐘)對方的代碼。這種方法能夠幫助你:
1. 及早的發現問題
2. 老是很快的知道該幹什麼
3. 代碼審查無須過長,由於你只須要查看新的代碼,舊的代碼會很快遇上
4. 這種非正式的場合——沒有緊張感,頗有趣!
5. 能夠按期的交換想法
buddy reviewing在團隊中是一種很好的工做方式,當某人在團隊中出現問題時能夠及早的發現。這不只能夠幫助你們,還能夠交換彼此的進度和想法。
總之,若是你的項目正在進行代碼審查,應該作到快速、有效、不浪費別人的時間。正如文章所說的,這幾點很是重要。代碼審查用意是在代碼提交前找到其中的問題。
代碼審查能夠幫助提升代碼質量,避免因爲代碼習慣而形成的 bug。下面列出的這些要點因該能夠做爲大部分代碼審查的指導,若是是 Java 應用的話,這些建議應該被視做最佳實踐。
Javadoc 應該在每個類和方法中添加。
若是是修復某個 bug,應該添加 bug ID。
走捷徑的方法或者複雜的邏輯要有解釋。
若是代碼會被公開,每一個文件頭都要標註版權信息。
複雜的 HTML,JavaScript,CSS 應該包含文檔。
若是相似的邏輯被使用了屢次,應該把它寫成一個幫助類,而後在多出調用。
鼓勵使用 API 而不是重複編寫代碼解決相同的問題。
要強調代碼的單元測試。
任何新加的代碼不該該破壞已有的代碼。
假如是 Web 應用,JSP 不該該包含 Java 代碼。
任何代碼都不能執行用戶的輸入,除非轉義過了。這個經常包含 JavaScript 的 eval 函數和 SQL 語句。
禁止那些在短期內提交很是多請求的 IP。
任何類,變量,還有方法都應該有正確的訪問域。
儘可能避免使用 iframe。
全部數據庫和文件操句柄在不須要的時候都應該被關閉。
SQL 語句的寫法會致使性能千差萬別。
鼓勵建立不可變(immutable)的類。
相似的邏輯代碼,儘可能經過 if else 語句來實現更多的重用。
儘可能避免使用重對象(heavy objects)。
若是是 Web 項目,請檢查是否使用了合適的圖片尺寸,CSS sprites 和瀏覽器緩存等技術。
全局都須要的信息保存在 application context 中。
沒有被使用的變量要刪除。
針對不一樣的 Exception 要用不一樣的 catch 語句,而不是一個 Exception 解決全部問題。
針對變量,方法和類要用相同的命名方法。
常量應該被寫在獨立的常量類中。
每行代碼的尾部不要有多餘的空格。
對於括號,循環,if語句等等要用統一的格式。
每個單獨的方法不該該超過100行。
一個單獨的語句不該該超過編輯器的可視區域,它能夠被拆分紅幾行。
檢查 String 對象既不是null也不是空的最好方法是 if(「」.equals(str))
假如類有不少成員變量,而且實例化的時候只須要少數變量傳入的話,最好使用靜態工廠方法,而不是重載構造函數。
給方法添加適當的訪問控制,而不是全部都是 public。
遵照項目中使用的框架的最佳實踐建議,例如 Spring,Struts,Hibernate,jQuery。
以上的某些注意點能夠經過靜態代碼檢查工具完成,例如 CheckStyle,FindBugs 和 JTest。