LinkedIn 頂級工程師分享|超過1000次 code review 你應該知道的事

DORA
多多設計
Published in
5 min readSep 14, 2018

翻譯自 LinkedIn 工程師文章

我在 LinkedIn 的工作中,有很大一部分是負責 code reviews ,而在 review 的過程中,我發現幾個程式設計師很容易犯的錯誤,所以決定將他們整理出來一方面提醒自己的團隊另一方面也希望給其他人一些啟發。

以下是 3 個是我最常説的 code review 建議。

建議 1: 在可能發生錯誤的地方,拋出例外處理。

下面是做搜索時常做的一般處理:

上面的方法可能是很多新手工程師的做法,但是因為沒有拋出例外曾導致我開發中的 APP 發生故障而我渾然不知。在用戶搜索開始之後,我們的後端發生錯誤開始拋出例外,但在 APP 的 API server 中並沒有拋出例外,因此從 APP 的角度來看,前端將會收到好幾百個成功的 response ,然後很開心地顯示空白的搜尋結果給使用者,而團隊卻渾然不知。

如果由 API 可以正確的丟出例外訊息,那我們的監控系統就可以立即掌握狀況並且馬上進行修復。

很多遇到例外的情況下,程式設計師只回傳空物件而沒有拋出例外,這是寫 code 的一種壞習慣。特別是在處理 URL 的場合,在回傳 nil 出現時我們必須先問問自己:“為什麼這個 URL 的處理是異常的?這是因為更上層發生異常嗎?”

傳空物件並不是面對這個問題的正確方法,如果出現錯誤你必須拋出一個例外來降低風險。

建議 2: 盡可能地使用具體型態(強型別)

但是這個意見基本上與 stringly typed programming 的看法相反。

Stringly typed programming 舉例:

使用具體的型別可以避免掉大部分的 bug ,這也是我們為什麼會選擇支援強行別語言的重要理由之一(eg. Java)。

所以現在問題來了:為什麼咱們善良可愛的工程師要去寫都是字串型別 (stringly type) 的程式碼呢? 答案很簡單:因為外面的世界並不是強型別,以下這些我們常用的外部資源,都不支援強型別。

  • 透過 url 發出請求的參數
  • JSON
  • 不支援 enums 的資料庫系統
  • 寫不好的 libraries ( 譯:作者好壞啊XD )

在支援度不夠的情況下,你應該考慮使用以下的策略來避免這些問題:讓字串解析和序列化排在程式中的上下邊緣化。下面是一個例子:

這會帶來許多優點,在程式撰寫的過程中我們可以在第一時間發現格式的錯誤,如果有任何問題程式會提前出現錯誤,我們不必在整個應用程序中去辛苦尋找解析異常。而且使用強型別之後,你每個方法的描述都更加具體正確,省下寫許多寫註釋文件的時間。

建議 3: 使用 Optioals 而非 nulls

在 Java 8 新增了 Optional 這個新的 class 用來表示這個實體是否合理的存在,解決原本的大量的空值判斷寫法。 ( 譯:如果對 Optional 不熟悉的小夥伴可以參考這裡)。

🙂 小問題:唯一擁有自己縮寫的例外是什麼?答案:NPE 或你可以說 Null Pointer Exception。這是目前為止 Java 中最常出現的錯誤,而且它還有一個可愛的暱稱:十億美元的錯誤

Optional 可以讓你在程式中完全規避 NPEs 的風險。但是前提是你必須正確地使用它,這裡是使用 Optiona 的一些小建議:

  • 在你擁有 Optional 的時候你不應該只是傻傻的使用 .get(),而是應該去思考哪些時候 Optional 無法被顯示,並適時給他一個合理的默認值。
  • 如果你還沒辦法給定他合理的默認值,善用 .mpa().flatMap() 可以讓你延後去賦予這些值。
  • 如果你使用外部的 library 而他會回傳空值或是 null ,那麼你應該馬上幫他包上 Optional.ofNullable() 。相信我你等等會感謝自己的。nulls 的 bug 會像泡泡一樣跟著你的程式慢慢浮出來,在根源就解決他們是最好的辦法。
  • 在回傳的方法時候使用 Optional 來接回傳值是非常好的辦法,因為你就不用花大把時間翻閱文件檢查他是否會回傳 null ,而是可以直接使用這些方法。

額外建議:盡可能平面化方法

你應該避免使用下面幾種方法:

以上這些該被避免的方法有哪些共通點呢?他們使用 container objects :Optional、List、或是 Task 這些類別當作方法的參數,要是他們放在回傳參數將會是更悲劇的災難,而這是為什麼呢?

1) Promise<A> method(Promise<B> param)
應該直接使用 2) 的方法更彈性

2) A method(B param)

如果你擁有 Pormise<B> 這個參數,那麼你可以選擇使用1)的方法,但是更好的辦法是使用 .map (ie. promise.map(metohd)) 將他套入 2) 的方法。這會讓你的 method 使用起來更加彈性。

此篇為翻譯文章。翻譯已取得原作者同意,原文:https://hackernoon.com/what-i-learned-from-doing-1000-code-reviews-fe28d4d11c71

--

--

DORA
多多設計

高興的就 Coding,不開心就 Drawing 。這輩子的目標是靠做自己想做的事情賺到錢。