天天看點

百度高效研發實戰訓練營-Step4

百度高效研發實戰訓練營-Step4

4.1 代碼檢測規則:Java案例詳解

以Java的案例進行代碼檢查規則解釋,代碼檢測規則可以分為以下十類:

4.1.1 源檔案規範

該類規範,主要為從檔案名、檔案編碼、特殊字元等三個方面制定的規則。

百度高效研發實戰訓練營-Step4
  • 檔案名方面:Java源檔案名,必須和它包含的頂層類名保持一緻,包括大小寫,并以.java作為字尾名。
  • 檔案編碼方面:為了保持編碼風格的一緻性,避免編碼不一緻導緻的亂碼問題,要求所有源檔案編碼必須使用UTF-8格式。
  • 特殊字元方面:針對換行、縮進、空格等操作而制定,有以下強制規則:
  • 1 換行符以外,ASCII空格(0x20)是唯一合法的空格字元。
  • 2 由于不同系統将Tab轉換成空格的數目不一緻,統一使用空格進行縮進。
  • 3 檔案的換行符統一使用Unix格式(\n),而不要使用Windows格式(\r\n)

4.1.2 源檔案組織結構規範

這一大類規則規定了源檔案所應包含的具體組成部分,和各個部分間應遵循的一系列規則。

對于源檔案的組成部分,規定如下:

源檔案,必須按照順序包含以下内容,許可證或版權聲明、package、import、唯一的頂層類四個方面的内容。同時,每兩個部分之間用一個空行進行分隔,不允許出現多餘空行,對于以上四個方面的内容,每個組成部分又有相應的編碼規則。

1 許可證或版權聲明

百度高效研發實戰訓練營-Step4
  • 如果檔案有許可證或版權聲明,應放在最開頭,如果沒有,則可以忽略這部分。

2 package語句

百度高效研發實戰訓練營-Step4
  • package語句一定單獨占一行不換行
  • 允許超過Java的120字元列寬限制

3 import語句

百度高效研發實戰訓練營-Step4
  • 對于所有非靜态導入,禁止使用通配符import
  • 所有未使用的import語句均應删除,并且與package語句相同
  • 每條import語句單獨占據一行不換行,允許超出120字元列寬限制

4 唯一的頂層類

類聲明規範

百度高效研發實戰訓練營-Step4
  • 每個源檔案隻允許包含唯一一個頂層類,若需要定義其他的類,可将多餘的類放在另外一個獨立的源檔案中,或者可将其作為一個内部類,定義在頂層類中來使用
  • 重載的方法必須放在一起,即同名的構造函數或方法之間禁止插入其他成員

4.1.3 代碼結構規範

這一部分規則,主要是對花括号(即大括号),縮進與換行、空行的一系列規範和其他說明。

1 花括号

花括号,經常在類和方法定義以及代碼塊劃分中使用,花括号在使用中常需要合理的換行操作進行配合,規定為:

  • 在非空代碼塊中使用花括号時,要遵循K&R風格(Kernighan and Ritchie Style)。
百度高效研發實戰訓練營-Step4

三個主要原則為:

  • ①在左花括号({})前不能換行,在其後換行
  • ②在右花括号(})前應有盡有
  • ③表示終止的右花括号(})後必須換行,否則,右花括号後不換行。

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 基本流程

單元測試的基本流程如下,首先,環境初始化,其次準備輸入參數,再次,調用待測試方法,然後檢查輸出,最後測試完成後環境複原。

百度高效研發實戰訓練營-Step4

環境初始化=>準備輸入參數=>調用待測試方法=>檢查輸出=>測試完成後環境複原。

2 測試替身

下面來介紹一下什麼是測試替身。

測試替身,可用于隔離被測試的代碼,加速執行順序,使得随機行為變得确定,模拟特殊情況,以及能夠使測試通路隐藏資訊等。

在Java代碼開發過程中,替身測試能夠保證單元測試的獨立性與重複性。

常見的測試替身有四類:樁(Stub)、僞造對象(Fake)、測試間諜(Spy)、模拟對象(Mock)等。

百度高效研發實戰訓練營-Step4

對于以上四個類别:

1 樁(Stub)

對于樁,一般什麼都不做,實作空的方法調用或者簡單的寫死傳回即可。

2 僞造對象(Fake)

真實資料的簡單版本,僞造真實對象的欣慰,但是沒有副作用或者使用真實事物的其他後果。比如替換資料庫的對象,而得到虛假的僞造對象。

3 測試間諜(Spy)

需要得到封閉對象内部狀态的時候,就要用到測試間諜,事先學會回報資訊,然後潛入對象内部去擷取對象的狀态。測試間諜是一種測試替身,它用于記錄過去發生的情況,這樣測試在事後就能知道所發生的一切。

4 模拟對象(Mock)

模拟對象是一個特殊的測試間諜。是一個在特定的情況下可以配置行為的對象,規定了在什麼情況下,傳回什麼樣的值的一種測試替身。目前Mock已經有了非常成熟的對象庫,包括JMock、Mockito和EasyMock等。

下面重點講一下,模拟對象(Mock)。

百度高效研發實戰訓練營-Step4

假如我們有業務邏輯,資料存取,資料這三層邏輯。

現在需要對業務邏輯層進行單元測試,那麼我們可以使用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 如何判斷單元測試的品質

百度高效研發實戰訓練營-Step4

首先來看一下,單元測試的衡量标準。

從主觀層面,優秀的單元測試可讀性高、易于維護、值得信賴。

從客觀層面,使用單元測試代碼覆寫率來衡量,覆寫率工具包括:內建IDE和單獨部署。

4.3 如何做好Code Review

4.3.1 為什麼要做好Code Review

1 Code Review是提升代碼品質的最好方法

Code Review是提升代碼品質的最好方法,是提升代碼品質的第一選擇,在代碼開發過程中,我們越早發現問題,定位問題,在修複問題時付出的成本越小,大約有50%以上的Bug,都是在做Code Review時發現的。

前期做好Code Review,後期将會減少反複修改等不必要的複工。

2 Code Review能夠在團隊内傳遞知識

百度高效研發實戰訓練營-Step4

從知識傳遞的角度來看,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中可能發現的問題

百度高效研發實戰訓練營-Step4

在Code Review中可以發現如下問題:

  • ①拼寫錯誤
  • ②未優化的代碼
  • ③不必要的複雜代碼
  • ④已經實作過的代碼又重複實作
  • ⑤注釋不全
  • ⑥case沒有覆寫全
  • ⑦...

2 在Code Review中應有的态度

基于以上問題,在Code Review中要有一個好的态度。

這就要求我們要做到以下幾點:

  • ①對所有檢查的代碼邏輯要做到“完全看懂”

    對于稽核的代碼,熟悉程度要做到如數家珍,如果在稽核代碼後,對代碼的邏輯和背後的原因仍然很模糊,則是一次失敗的Code Review。

  • ②好代碼的标準,不僅僅是可以運作通過,在正确性、可讀性、可複用性、可運維性等方面上,都需要綜合考慮。
  • ③建立Code Review和寫代碼一樣重要的意識。

    (1) 即Code Review和寫代碼一樣,也有産出,即産出更高品質的代碼;

    (2) 稽核代碼,在很多情況下比寫代碼還要辛苦,需要了解和找出問題等。

  • ④以提升代碼品質為最終目标
  • ⑤要投入足夠的時間和重視

    (1) 稽核代碼花費的時間,經常和寫代碼一樣多。有時甚至比寫代碼的時間更多,是以要有時間意識。

    (2) 要有責任意識,如果出現Bug不僅僅是寫代碼人員的職責,也不僅僅是QA的職責,代碼稽核者也需要承擔相當大的責任。

3 在Code Review之前,需要了解一流代碼的特性

百度高效研發實戰訓練營-Step4

除了态度之外,在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
百度高效研發實戰訓練營-Step4

好的代碼稽核人員,不僅僅指出代碼表面的問題。

還會檢查系統需求分析的品質、接口或函數定義的合理性、子產品劃分的合理性、系統關鍵機制的合理性等。

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的重要性、方法步驟和注意事項。

百度高效研發實戰訓練營-Step4
百度高效研發實戰訓練營-Step4