百度高效研發實戰訓練營-Step4
4.1 代碼檢測規則:Java案例詳解
以Java的案例進行代碼檢查規則解釋,代碼檢測規則可以分為以下十類:
4.1.1 源檔案規範
該類規範,主要為從檔案名、檔案編碼、特殊字元等三個方面制定的規則。
![](https://img.laitimes.com/img/_0nNw4CM6IyYiwiM6ICdiwiI0gTMx81dsQWZ4lmZf1GLlpXazVmcvwFciV2dsQXYtJ3bm9CX9s2RkBnVHFmb1clWvB3MaVnRtp1XlBXe0xCMy81dvRWYoNHLwEzX5xCMx8FesU2cfdGLwMzX0xiRGZkRGZ0Xy9GbvNGLpZTY1EmMZVDUSFTU4VFRR9Fd4VGdsYTMfVmepNHLrJXYtJXZ0F2dvwVZnFWbp1zczV2YvJHctM3cv1Ce-cmbw5SOwQjM1QjNyMGO1kTMiNWYyYzXxQzM1ADM4EzLcZDMyIDMy8CXn9Gbi9CXzV2Zh1WavwVbvNmLvR3YxUjLyM3Lc9CX6MHc0RHaiojIsJye.png)
- 檔案名方面:Java源檔案名,必須和它包含的頂層類名保持一緻,包括大小寫,并以.java作為字尾名。
- 檔案編碼方面:為了保持編碼風格的一緻性,避免編碼不一緻導緻的亂碼問題,要求所有源檔案編碼必須使用UTF-8格式。
- 特殊字元方面:針對換行、縮進、空格等操作而制定,有以下強制規則:
- 1 換行符以外,ASCII空格(0x20)是唯一合法的空格字元。
- 2 由于不同系統将Tab轉換成空格的數目不一緻,統一使用空格進行縮進。
- 3 檔案的換行符統一使用Unix格式(\n),而不要使用Windows格式(\r\n)
4.1.2 源檔案組織結構規範
這一大類規則規定了源檔案所應包含的具體組成部分,和各個部分間應遵循的一系列規則。
對于源檔案的組成部分,規定如下:
源檔案,必須按照順序包含以下内容,許可證或版權聲明、package、import、唯一的頂層類四個方面的内容。同時,每兩個部分之間用一個空行進行分隔,不允許出現多餘空行,對于以上四個方面的内容,每個組成部分又有相應的編碼規則。
1 許可證或版權聲明
- 如果檔案有許可證或版權聲明,應放在最開頭,如果沒有,則可以忽略這部分。
2 package語句
- package語句一定單獨占一行不換行
- 允許超過Java的120字元列寬限制
3 import語句
- 對于所有非靜态導入,禁止使用通配符import
- 所有未使用的import語句均應删除,并且與package語句相同
- 每條import語句單獨占據一行不換行,允許超出120字元列寬限制
4 唯一的頂層類
類聲明規範
- 每個源檔案隻允許包含唯一一個頂層類,若需要定義其他的類,可将多餘的類放在另外一個獨立的源檔案中,或者可将其作為一個内部類,定義在頂層類中來使用
- 重載的方法必須放在一起,即同名的構造函數或方法之間禁止插入其他成員
4.1.3 代碼結構規範
這一部分規則,主要是對花括号(即大括号),縮進與換行、空行的一系列規範和其他說明。
1 花括号
花括号,經常在類和方法定義以及代碼塊劃分中使用,花括号在使用中常需要合理的換行操作進行配合,規定為:
- 在非空代碼塊中使用花括号時,要遵循K&R風格(Kernighan and Ritchie Style)。
三個主要原則為:
- ①在左花括号({})前不能換行,在其後換行
- ②在右花括号(})前應有盡有
- ③表示終止的右花括号(})後必須換行,否則,右花括号後不換行。
2 縮進與換行
縮進與換行,主要是為了保證代碼風格的一緻性,提升代碼的可維護性。
主要規範有:
- ①每次開始書寫一個新代碼塊時,使用四個空格進行縮進,在代碼塊結束時,恢複之前的縮進級别。
- ②每條語句之後都要換行,每行隻能有一條完整語句
-
③除package語句import語句外,單行代碼字元數限制不超過120個。
超出則需要換行,換行時,遵循如下五條原則:
(1) 第二行相對于第一行縮進四個空格,從第三行開始,不再繼續縮進。
(2) 運算符與下文一起換行,即運算符位于行首
(3) 方法調用的點符号與下文一起換行
(4) 方法調用中的多個參數需要換行時,在逗号後進行
(5) 在括号前不要換行
3 空行
合理使用空行,可以提高代碼的可讀性,有利于後期維護。
對于空行的使用,有如下規範進行限制:
- ①在類的不同成員間增加空行,包括:成員函數、構造函數、方法、内部類、靜态初始化塊、執行個體初始化塊等。
- ②在兩個成員變量聲明之間可以不加空行。空行通常用于成員變量進行邏輯分組。
- ③方法體内,按需增加空行,以便從邏輯上對語句進行分組。
- ④使用空行時,禁止使用連續的空行。
4 其他說明
Java中有兩種數組定義形式,為規範代碼書寫形式,要求為:
- 類型與中括号緊挨相連來表示數組,即中括号寫在數組名之前
而當注解與注釋同時存在時,統一的規範要求為:
- 添加在類、方法、構造函數、成員屬性上的注解,直接寫在注釋塊之後,每個注解獨占一行
當同時存在多個修飾符時,需要按照順序書寫,順序要求如下:
- 排在首位的一定是通路修飾符,随後是
,即抽象類或抽象方法,緊接着是abstract
、static
。這是常見的幾類修飾符,對于其他的修飾符,可以參考以上列舉的順序書寫。final
public protected private abstract static final
transient volatile synchronized native strictfp
為避免小寫字母,l與1混淆,有如下規定:
- 常整型數字必須使用大寫字母L結尾,以便于和數字1進行區分
4.1.4 命名規範
在Java中,無論是方法名還是類名,均需使用駝峰命名格式進行命名。
1 駝峰命名格式
對于兩種駝峰命名格式的使用範圍,有如下規範:
- ①方法名、參數名、成員變量、局部變量都統一使用lowerCaeCase風格,即首字母小寫的駝峰命名格式
- ②類名使用UpperCamelCame風格,即首字母大寫的駝峰命名格式,以下情形例外:DO/BO/DTO/VO/AO/PO/UID等。
2 類的命名格式
除此之外,對于一些類,命名格式有更加具體的規範要求:
- ①抽象類命名,使用Abstact或Base開頭
- ②異常類命名使用Exception結尾
- ③測試類命名以它要測試的類的名稱開始,以Test結尾。
3 常量命名格式
對于常量的命名規範,與上述所述有所不同:
- ①常量命名全部大寫,單詞間用下劃線隔開;
- ②不允許任何未經定義的常量直接出現在代碼中。
4.1.5 OOP規約
OOP規約,主要是針對面向對象程式設計過程中,定義的一些類所制定的一些規則,包含的強制規範要求有
- ①所有POJO類屬性,必須使用包裝資料類型,禁止使用基本類型。
- ②所有的覆寫方法,必須加@Override注解
- ③Object的equals方法容易抛空指針異常,應使用常量或确定有值的對象來調用equals
- ④定義DO/DTO/VO等POJO類時,均不要設定任何屬性預設值。
4.1.6 集合處理規範
集合和數組,是我們開發過程中使用頻度最高的兩個資料結構。
對于二者的使用,也有嚴格的強制規範:
- ①當需要将集合轉換為數組時,必須使用集合的toArray方法,傳入的是類型完全一樣的數組,大小是list.size()。
- ②對一個集合求子集合時,需高度注意對原集合元素的增加或删除,均會導緻子清單的周遊、增加、删除,産生ConcurrentModificationException異常。應通過對子集合進行相應操作,來反射到原集合,進而避免異常的發生。
- ③不要在循環體内部進行集合元素remove/add操作。remove元素請使用Iterator(疊代器)方式,如果并發操作,需要對Iterator對象加鎖。
4.1.7 控制語句規範
Java中的控制語句主要有Switch、if、else、while。這些語句的使用在編碼過程中需要遵循以下規範:
- (1)在一個switch塊内,每個case要麼通過break/return等來終止,要麼注釋說明程式将繼續執行到哪一個case為止;在一個stitch塊内,都必須包含一個default語句并且放在最後。
- (2)使用if/else/while/do語句必須使用花括号。即使隻有一行代碼,避免采用單行的編碼方式。
- (3)在高并發場景中,避免使用“等于”判斷作為中斷或退出的條件。防止在擊穿現象下,程式無法正常中斷或退出的情況發生。
4.1.8 注釋規約
合理使用注釋可以提高程式可讀性,進而便于後期的維護。
注釋可以是程式說明,也可以是程式設計思路。
Java中的注釋主要分三種形式:文檔注釋、單行注釋和多行注釋
注釋規約包括:
- ①類、類屬性、類方法的注釋必須使用文檔注釋形式,即使用\(/**内容**/\)格式,不得使用單行注釋的格式。單行注釋和多行注釋主要使用在方法體内。
- ②方法内部單行注釋,在被注釋語句上方另起一行,使用//注釋。方法内部多行注釋,使用\(/*内部*/\),注釋與代碼對齊。
4.1.9 異常處理規範
在Java中,我們通常使用try catch來進行捕獲異常處理,而Java中的異常又分為運作時異常和非運作時異常。對于處理運作時異常,有如下規範:
- ①Java類庫中定義的可以通過預檢查方式規避的RuntimeException異常不應該通過try catch的方式來處理,比如:空指針異常和數組越界異常等等。
-
②對于捕獲後異常的處理,有如下規範:捕獲異常是為了處理異常,不要捕獲後不進行任何處理而将其抛棄。
若不想進行異常的處理,則應将該異常抛給它的調用者。
最外層的業務使用者必須處理異常,将其轉化為使用者可以了解的内容。
即對于捕獲後的異常,要麼繼續向上抛,要麼自己進行處理。
- ③異常處理的規範要求還包括:不能在finally塊中使用return語句。
4.1.10 缺陷檢測規則
缺陷檢測要是對Java源代碼進行靜态分析,掃描其中潛在的缺陷,比如空指針異常、死循環等。
這一階段所應遵循的規則包括:
- (1) 不能使用單個字元定義StringBuffer和StringBuilder;
- (2) 任何上鎖的對象均需保證其鎖可以被釋放
- (3) 嚴格避免死循環的發生
-
(4) 對于字元串中的點号(".")、豎線("|")和檔案分隔符("File.separator")進行替代時,需要注意其特殊含義。
“.”:比對任意單個字元。在replaceAll中使用,它比對所有内容。
“|”:通常用作選項分隔符,它比對字元間的空格。
“File.separator”:比對特定平台的檔案路徑分隔符。在Windows上,這将被視為轉義字元。
- (5) 當synchronize對成員變量進行上鎖時,該成員變量必須是final類型的。
- (6) synchronize上鎖的成員變量類型一定不能是裝箱類型。
- (7) 所有被spring托管的類,其成員屬性的初始化均要使用注入的方式。
-
(8) 當使用try catch方式進行異常捕獲,且需要在catch中對異常資訊進行輸出時,不得使用printStackTrace的方式。
這種方式會導緻後期分析代碼困難。而應采用一些Log架構,友善使用者檢索和浏覽日志。
- (9) 方式傳回值包含操作狀态代碼時,該狀态碼不應被忽略
- (10) 【%s】數組具有協變性,元素指派類型與初始化類型不一緻,此種情況可通過編譯,但運作階段會發生錯誤。
- (11) 對于使用者名和密碼不應直接寫在Java的檔案中,避免洩露。而應将相信關鍵資訊寫在配置檔案中進行讀取。
- (12) 方法和成員變量的命名不應相同,也不應通過大小寫進行區分。
4.2 單元測試之Java實踐
如何寫單元測試,這部分包括四個方面,基本流程、測試替身、設計思路、斷言(Assertions)。
4.2.1 如何寫單元測試
1 基本流程
單元測試的基本流程如下,首先,環境初始化,其次準備輸入參數,再次,調用待測試方法,然後檢查輸出,最後測試完成後環境複原。
環境初始化=>準備輸入參數=>調用待測試方法=>檢查輸出=>測試完成後環境複原。
2 測試替身
下面來介紹一下什麼是測試替身。
測試替身,可用于隔離被測試的代碼,加速執行順序,使得随機行為變得确定,模拟特殊情況,以及能夠使測試通路隐藏資訊等。
在Java代碼開發過程中,替身測試能夠保證單元測試的獨立性與重複性。
常見的測試替身有四類:樁(Stub)、僞造對象(Fake)、測試間諜(Spy)、模拟對象(Mock)等。
對于以上四個類别:
1 樁(Stub)
對于樁,一般什麼都不做,實作空的方法調用或者簡單的寫死傳回即可。
2 僞造對象(Fake)
真實資料的簡單版本,僞造真實對象的欣慰,但是沒有副作用或者使用真實事物的其他後果。比如替換資料庫的對象,而得到虛假的僞造對象。
3 測試間諜(Spy)
需要得到封閉對象内部狀态的時候,就要用到測試間諜,事先學會回報資訊,然後潛入對象内部去擷取對象的狀态。測試間諜是一種測試替身,它用于記錄過去發生的情況,這樣測試在事後就能知道所發生的一切。
4 模拟對象(Mock)
模拟對象是一個特殊的測試間諜。是一個在特定的情況下可以配置行為的對象,規定了在什麼情況下,傳回什麼樣的值的一種測試替身。目前Mock已經有了非常成熟的對象庫,包括JMock、Mockito和EasyMock等。
下面重點講一下,模拟對象(Mock)。
假如我們有業務邏輯,資料存取,資料這三層邏輯。
現在需要對業務邏輯層進行單元測試,那麼我們可以使用Mock,對資料存取和資料層的内容進行模拟,進而使上面的單元測試是獨立的。
3 設計思路
下面來講解怎樣通過測試替身來寫單元測試:
單元測試case的核心與目前函數的功能實作,對于輸出資料做出具體的預期,即可把全部待測試的分支都羅列出來。
應用場景+輸入資料+功能實作=輸出資料。
4 斷言(Assertions)
斷言,是一種在Java單元測試中經常使用的測試方法,在單元測試中,我們使用斷言,來檢驗目前的測試結果是成功還是失敗。
常見的斷言有:
Assert.assertNotNull
、Assert.assertEquals、Assert.assertTrue、Assert.assertFalse、Assert.fail。無需人工對單元測試結果進行判斷。
4.2.2 單元測試的運作
單元測試的運作:
單元測試的運作分為手動與自動兩種,第一種是手動方式:
-
直接在IDE中執行
在開發編碼完成之後,開發人員可以直接在自己的環境和編譯器内運作單元測試。
-
使用Maven的mvn test
Maven是目前Java開發中最流行的項目建構工具,它包含了很多功能,非常全面。mvn test這個測試模型就可以為我們的單元測試提供極大的便利。
第二種方式是自動運作:
-
持續內建(Jenkins)
自動化持續內建是我們在項目中常用的一種單元測試的方法。通用工具為Jenkins,Jenkins是一種持續內建的工具,它的功能非常強大。他的主要的功能有軟體釋出和版本測試、外部調用測試。
4.2.3 如何判斷單元測試的品質
首先來看一下,單元測試的衡量标準。
從主觀層面,優秀的單元測試可讀性高、易于維護、值得信賴。
從客觀層面,使用單元測試代碼覆寫率來衡量,覆寫率工具包括:內建IDE和單獨部署。
4.3 如何做好Code Review
4.3.1 為什麼要做好Code Review
1 Code Review是提升代碼品質的最好方法
Code Review是提升代碼品質的最好方法,是提升代碼品質的第一選擇,在代碼開發過程中,我們越早發現問題,定位問題,在修複問題時付出的成本越小,大約有50%以上的Bug,都是在做Code Review時發現的。
前期做好Code Review,後期将會減少反複修改等不必要的複工。
2 Code Review能夠在團隊内傳遞知識
從知識傳遞的角度來看,Code Review是極為重要的。
做好Code Review,能夠幫助團隊傳遞知識、溝通交流、互相學習、能夠提升學習能力、提升編寫代碼能力、提升代碼品質、提升工作效率、降低項目風險。另外基于Codebase可以使我們了解項目全局,培養系統的思考方式。
3 Code Review是輔導怎麼寫代碼的最好方法
我們要意識到,做Code Review可以學習到别人的經驗,同時向别人傳遞我們的經驗,如果我們想輔導别人,最好的辦法就是讓對方先寫一段代碼,我們對他的的代碼進行Code Review,在輔導他人的過程中,我們可以快速的發現問題,進而幫助改進。
4 做好Code Review可以增加公司對最頂級開發者的吸引力
工作中是否有Code Review,對于公司或團隊來說非常重要,不但對于公司或團隊内的人員有提升,而且能夠吸引出色的開發者加入開發團隊。
未做好Code Review的公司或團隊,有如下特點:
- 1 代碼品質差
- 2 團隊内人員備份差
- 3 團隊開發人員得不到有效的輔導,提高慢
5 為什麼要提高代碼品質
為什麼要提高代碼品質的若幹理由,如下:
- ①提高代碼品質,可以提高代碼的可讀性
- ②提高代碼品質,可以提高代碼的複用性和參考性
- ③提高代碼品質,可以減少Bug出現的風險
- ④提高代碼品質,可以減少後期更新檔的風險
- ⑤提高代碼品質,可以降低代碼失控的風險
- ⑥提高代碼品質,可以降低項目重構和更新的麻煩
6 為什麼要提高寫代碼的能力
為什麼要提高寫代碼的能力的若幹理由,如下:
- ①代碼能力如果停滞不前,對于個人而言,将導緻職業危機。
- ②代碼能力如果停滞不前,對于團隊而言,将意味着團隊沒有成長。
Code Review是一個非常重要的,提升代碼品質和代碼能力的手段。
無論是從個人發展角度還是團隊發展角度,我們都需要重視Code Review。
4.3.2 如何做好Code Review
我們将從以下幾個次元進行闡述,如何進行Code Review。
1 在Code Review中可能發現的問題
在Code Review中可以發現如下問題:
- ①拼寫錯誤
- ②未優化的代碼
- ③不必要的複雜代碼
- ④已經實作過的代碼又重複實作
- ⑤注釋不全
- ⑥case沒有覆寫全
- ⑦...
2 在Code Review中應有的态度
基于以上問題,在Code Review中要有一個好的态度。
這就要求我們要做到以下幾點:
-
①對所有檢查的代碼邏輯要做到“完全看懂”
對于稽核的代碼,熟悉程度要做到如數家珍,如果在稽核代碼後,對代碼的邏輯和背後的原因仍然很模糊,則是一次失敗的Code Review。
- ②好代碼的标準,不僅僅是可以運作通過,在正确性、可讀性、可複用性、可運維性等方面上,都需要綜合考慮。
-
③建立Code Review和寫代碼一樣重要的意識。
(1) 即Code Review和寫代碼一樣,也有産出,即産出更高品質的代碼;
(2) 稽核代碼,在很多情況下比寫代碼還要辛苦,需要了解和找出問題等。
- ④以提升代碼品質為最終目标
-
⑤要投入足夠的時間和重視
(1) 稽核代碼花費的時間,經常和寫代碼一樣多。有時甚至比寫代碼的時間更多,是以要有時間意識。
(2) 要有責任意識,如果出現Bug不僅僅是寫代碼人員的職責,也不僅僅是QA的職責,代碼稽核者也需要承擔相當大的責任。
3 在Code Review之前,需要了解一流代碼的特性
除了态度之外,在Code Review之前,需要了解一流代碼的特性。
一流代碼有以下特性:
- (1) 高效性
- (2) 魯棒性
- (3) 簡潔
- (4) 簡短
- (5) 可共享
- (6) 可測試
- (7) 可移植
- (8) 可監控
- (9) 可運維
- (10) 可擴充
将以上十條标準進行總結精簡,可歸納為:
- 1 代碼的正确和性能
- 2 代碼的可讀和可維護性
- 3 代碼的可運維和可營運
- 4 代碼的可共享和可重用
在Code Review時,綜合考慮以上一流代碼的特性,可以快速提升代碼品質,提升編寫代碼的能力等。
4 在Code Review時,需要有對bad code進行簡單判斷的能力
除了要了解一流代碼的特性之外,在Code Review時,需要有對Bad Code進行簡單判斷的能力。
通常bad code有以下特點:
-
①5分鐘内不能看懂的代碼
不能快速看懂的代碼,一定是有問題的代碼。
可以先抛回給編寫代碼人員進行修正。
一般一個函數的操作,不能超過6個Step,如果超過這個數量,則需要重新調整編碼邏輯。
-
②需要思考才能看懂的代碼
好的代碼閱讀時基本不用動腦子,甚至看注釋就能看懂。
-
③需要來回翻屏才能看懂的代碼
好的代碼,經常在一屏内就是一個完整的邏輯。
-
④沒有空行或注釋的代碼
在Code Review時,在發現不會用段落,不會寫注釋的代碼,肯定部署好的程式員寫的代碼。可以直接打回給編寫代碼人員進行修正。
5 Code Review的注意事項
在Code Review時有以下注意事項:
-
1 在必要時,Review的雙方做面對面的溝通
面對面溝通,并不是單指當面溝通,還包括雲共享、電話、視訊溝通等。
在溝通時,對于背景、關鍵點等應進行說明,便于reviewer的了解。
在必要時,應提供設計文檔。
- 2 對于關鍵子產品,應該建立owner制度,所有送出的代碼,必須由owner做最終确認,由owner做最終确認,并建立明确的責任關系。
- 3 對于Review檢查中發現的問題,要一追到底。
-
4 要注意細節
對每一行送出的代碼,都要進行檢查。
-
5 Code Review的方式,要小步快跑。
每次調教review的代碼量不要太多,降低複雜度。
在特殊情況時,比如一個新子產品的建構,最好逐漸完成,通過多次進行送出。
-
6 要為Code Review預留出足夠的時間
Code Review VS Coding的時間,有時可能達到1:1。
在這裡需要考慮到有時會做大的修改,科學地規劃工作量,盡量避免出現時間倒排。
- 7 注意每天review代碼的數量,不宜過多。
6 Code Review的步驟
Code Review的步驟,主要為以下幾點:
-
Step1 先看系統全貌
不深究細節,浏覽系統全貌,理清子產品劃分的邏輯、子產品間的關系、如何構成的整個系統等。
-
Step2 進入子產品級别
同樣不深究細節,浏覽子產品内的全貌,判斷子產品切分是否合理、理清子產品内的邏輯、明确關鍵資料、關鍵的類和函數等。
- Step3 理清類、函數内部的邏輯
-
Step4 進入細節
比如Layout、命名等。
7 人為因素
除了代碼上的問題,在Code Review過程中,還會有一些人為因素。
比如:
-
1 QA人員
好的QA人員,不僅僅會發現系統中的Bug,還會質疑或提出産品需求。挑戰或優化系統架構和實作方式。
- 2 Code Reviewer
好的代碼稽核人員,不僅僅指出代碼表面的問題。
還會檢查系統需求分析的品質、接口或函數定義的合理性、子產品劃分的合理性、系統關鍵機制的合理性等。
4.3.3 例子:Python代碼的Code Review
我們從Phthon的編碼規範和Python程式設計規範的部分說明。
兩個次元,來看一下Code Review的細節。
這些Code Review的細節,在其他語言中基本都是相通的。
1 Python的程式設計規範
- (1) 代碼要寫的漂亮
-
(2) 代碼要明确直接
明确直接,不要含蓄表達。
-
(3) 代碼要簡潔
一個函數可以實作的功能,就不要寫兩個函數。
-
(4) 代碼深奧勝過代碼複雜
代碼可以寫的深奧難懂,但是不能寫的過于複雜。
-
(5) 代碼要平鋪直叙
平鋪直叙,不要層層嵌套
- (6) 代碼要做到合理間隔
- (7) 代碼可讀性非常重要
-
(8) 代碼要有普适性
盡量規避代碼特殊性,用最簡潔的代碼來實作。
- (9) 代碼要實用
- (10) 要重視所有發現的錯誤
-
(11) 代碼邏輯要清晰
在含糊混亂的面前,我們要拒絕猜測。讀寫代碼時,不要出現好像、可能、似乎等猜測。
當一段代碼很難懂的時候,代碼一定存在問題。
- (12) 寫代碼要注重行動
-
(13) 代碼實作方法要簡潔
如果一個方法很難解釋,就意味着這個方法存在一定的問題。
- (14) 要重視命名空間的使用
2 關于Python程式設計規範的部分說明
在關于Python程式設計規範的部分說明中,下面将從九個次元進行展開,分别是:
- 子產品的劃分
- 資料的封裝
- import
- 異常
- 構造函數
- 函數傳回值
- 代碼長度
- 空行、空格
- 注釋
(1) 子產品的劃分
首先來看子產品的劃分,我們要對子產品有概念,這是整個系統的基礎。
- ①一個.py檔案是一個子產品
- ②子產品的劃分,對軟體的長期維護非常重要
-
③每個子產品都應該有特定的功能
例如:配置檔案的讀取
網頁檔案的寫入
網頁檔案的解析
一個記憶體資料表
一個抓取的線程
- ④多個本應獨立的子產品,寫到一個.py檔案中是常見的錯誤。
從Code Review角度看,首先就是要看子產品切分的對不對。
(2) 資料的封裝
不管理好資料,是程式錯誤的重要來源,常見的程式錯誤是資料未封裝。
在Code Review時,要着重注意這一點。
(3) import
import在使用過程中,有以下注意事項:
- 禁止使用
文法直接導入類或函數。from xxx import yyy
- 禁止使用
from xxx import *
這樣的方法
這樣做的目的是,容易判斷代碼中使用外部變量或函數的來源。
如果使用禁止中的文法,會大大增加判斷來源的難度,以及代碼閱讀的難度。
在Code Review時,在遇到這種情況,應及時将代碼打回給程式設計人員進行修正。
(4) 異常
對于異常的處理,有以下幾點需要注意:
-
1 異常的使用
使用異常前,需要詳細了解異常的行為。不要主動抛出異常,使用傳回值。如果一定要抛異常,需要注釋進行說明。
-
2 異常的擷取強制
除非重新抛出異常,否則禁止使用except:捕獲所有異常,不建議捕獲Exception或StandardError。
在實際編碼中,建議Try中的代碼盡可能少,避免catch住未預期的異常,掩藏掉真正的錯誤。
底線是至少要列印異常的日志,而不是捕獲後直接pass通過。
在對異常進行處理時,盡量針對特定操作的特定異常來捕獲。
常犯的錯誤是,一是對IO等操作不捕獲異常,二是捕獲異常區域很大。
-
3 函數的傳回值
如果函數會抛出異常,需要在注釋中明确說明。
在Code Review時,需要注意上述問題,及時傳回給程式設計人員進行修正。
(5) 構造函數
對于構造函數,有以下幾點需要注意:
1 規範
- 類構造函數,應該盡量簡單,不能包含可能失敗或過于複雜的操作。
2 解讀
- 在構造函數中,常出現的錯誤是:無法判斷、或捕獲異常。
(6) 函數傳回值
對于函數傳回值,有以下幾點需要注意:
1 規範
-
函數傳回值,必須小于等于3個。
傳回值超過3個時,必須通過class/namedtuple/dict等具名形式進行包裝。
2 解讀
-
a.多數情況下的錯誤,是很多人不會思考和設計函數的語義。
函數描述涉及的三要素為:功能描述、傳入參數描述和傳回值描述。
每個函數都應該有足夠明确的語義。
基于函數的語義,函數的傳回值有三種類型:
(1) 在“邏輯判斷型”函數中,傳回布爾類型的值。——True或False,表示“真”或“假”。
(2) 在“操作型”函數中,作為一個動作,傳回成功或失敗的結果。——OK或ERROR。
(3) 在“擷取型”函數中,傳回一個“資料”,或者傳回“無資料/擷取資料失敗”。
- b.函數需要有傳回值,對于正确或錯誤的情況,在傳回值中要有展現。
-
c.還有一個問題是:Python的資料格式不需要定義,過于靈活。
當程式規模變大、維護周期變長時,會導緻後期極難維護。
應對措施是:多寫注釋,寫清楚傳回值說明、參數說明。
在Code Review時,注釋未寫清楚的代碼,一定要打回給程式設計人員,進行修正、補注釋。
(7) 代碼長度
關于代碼長度,有以下幾點需要注意:
-
1 每行不得超過120個字元
避免在終端上顯示出現折行
-
2 函數長度不得超出100行
函數過長會增加了解函數邏輯的難度
Python的函數應盡量控制在30~40行之間。
在Code Review時,代碼過長,建議全部打回給程式設計人員進行修正。
(8) 空行、空格
關于空行、空格,有以下幾點需要注意:
-
1 檔案及定義之間間隔兩個空行
比如類或全局函數、類方法之間隔一個空行。
-
2 空格
逗号、分号、冒号前不加空格。後邊加一個空格。
所有二進制運算符前後各加一個空格。
在Code Review時,要着重注意空行和空格。
空行和空格并不是可有可無的。
空行和空格的存在,是為了增加可讀性。
不好讀的代碼,一律打回給程式設計人員進行修正。
(9) 注釋
關于注釋,有以下幾點需要注意:
-
Python中的注釋有一個特殊之處是docstring,docstring要和“#”注意區分開。
相關規範有:
1 使用docstring描述module、function、class和method接口時,docstring必須用三個雙引号括起來。
2 對外接口部分,必須用docstring描述。内部接口視情況自行決定是否寫docstring。
3 接口的docstring描述,至少包括功能簡介、參數、傳回值。如果可能抛出異常,必須使用注釋進行說明。
4 每個檔案都必須有檔案聲明,檔案聲明必須包括以下資訊:版權聲明、功能和用途簡介、修改人及聯系方式。
- 不符合上述規則的,直接打回給程式設計人員進行修正。
4.3.4 如何成為一個好的reviewer
如何成為一個好的reviewer。
代碼稽核的品質,和稽核者的代碼能力直接相關。
代碼稽核的品質差,反映的是稽核者的代碼水準。
如果作為一個代碼稽核員,不會寫代碼,就要承認事實真相,并且要不斷提高自己的代碼能力。
在這裡推薦一些學習資料,來幫助大家進行學習。
1 關于代碼的書籍
《編寫可讀代碼的藝術》
《代碼整潔之道》
2 綜合的書籍
《代碼大全》
《201 principles of software development》
3 其他
《代碼的藝術》
《Python Good Coder考試指南》
4.3.5 公司針對Code Review的措施
1 建立高效可營運的代碼稽核機制
- 提升代碼品質
- 降低代碼評審成本
(1) 基于平台
icode+bugbye
(2) 代碼檢查規則分級
分為ERROR、WARNING、ADVICE三類。
- 對于ERROR級别,阻塞送出。
(3) 通過統計資料驅動代碼檢測規則的優化
2 通過工程能力地圖考察項目的Code Review情況
3 提供良好的工具或平台
所有的Code Review行為,都基于icode平台進行。
良好的工具或平台,可以幫助更好的進行代碼稽核。
4.3.6 Code Review課程總結
這本文内容中,分别從為什麼要做好Code Review、如何做好Code Review、Python代碼的Code Review、如何成為一個好的Reviewer、公司針對Code Review的措施幾個次元,學習了Code Review的相關知識,清楚了Code Review的重要性、方法步驟和注意事項。