再讀編程的智慧一文有感

記得是2015年還是2016年初讀過王垠的這篇文章–編程的智慧,收益良多。一些當時讓我影響深刻的點,自那以後就一直用於生產了。

今天重溫此文,感觸最深的有以下三個點:

  1. 循環時避免使用continue和break,並提供瞭如何去掉的方法
  2. 如何正確的處理Java裏的異常和錯誤
  3. 如何正確的處理Java裏的空指針

本文是編程的智慧一文的內容概要,當然最好的方式,是花上2到3小時認真閱讀王垠的原文,相信你會有很多感觸和收穫。

正文內容

推敲代碼

反覆推敲代碼,仔細領悟,積累靈感和智慧,爲了在遇到新問題的時候直接朝正確,或者接近正確的方向前進。

優雅代碼的形狀特徵

看起來像整整齊齊,套在一起的盒子。抽屜裏分門別類,再放幾個小盒子。

邏輯上是枝丫分明的樹狀結構。程序所做的幾乎一切事情,都是信息的傳遞和分支。

模塊化代碼

模塊化不是簡單的把代碼切割開來,分放在不同的位置。指的是邏輯上模塊化。

需要做到以下幾點:

  1. 一個函數不超過40行
  2. 製造小的工具函數。函數內聯,內聯擴展是用來消除函數調用時的時間開銷。它通常用於頻繁執行的函數,對於小內存空間的函數非常受益
  3. 每個函數只做一件簡單的事
  4. 避免使用全局變量和類成員來傳遞信息

可讀的代碼

使用有意義的函數和變量

局部變量應該儘量接近使用它的地方,加強讀者對於這裏的“計算順序”的理解,局部變量的本質——它們就是電路里的導線。

局部變量名字應該簡短

不要重用局部變量,否則會把局部變量的作用域不必要的增大。

把複雜邏輯提取出來,做成幫助函數

把複雜的表達式提取出來,做成中間變量

合理的地方換行

簡單的代碼

程序語言都喜歡標新立異,提供這樣那樣的“特性”,然而有些特性其實並不是什麼好東西。很多特性都經不起時間的考驗,最後帶來的麻煩,比解決的問題還多。很多人盲目的追求“短小”和“精悍”,或者爲了顯示自己頭腦聰明,學得快,所以喜歡利用語言裏的一些特殊構造,寫出過於“聰明”,難以理解的代碼。

並不是語言提供什麼,你就一定要把它用上的。實際上你只需要其中很小的一部分功能,就能寫出優秀的代碼。

避免使用自增減表達式(i++,++i,i–,–i)用在複雜的表達式裏面

永遠不要省略花括號

合理使用括號,不要盲目依賴操作符優先級,能降低視覺思考疲勞。

循環時避免使用continue和break。這點更新了我的認知。這兩個詞依靠“控制流”來描述“不做什麼”,“跳過什麼”,結果到最後你也沒搞清楚它到底“要做什麼”。

  1. 如果出現了continue,你往往只需要把continue的條件反向,就可以消除continue。
  2. 如果出現了break,你往往可以把break的條件,合併到循環頭部的終止條件裏,從而去掉break。
  3. 有時候你可以把break替換成return,從而去掉break。
  4. 如果以上都失敗了,你也許可以把循環裏面複雜的部分提取出來,做成函數調用,之後continue或者break就可以去掉了。

寫直觀的代碼

如果有更加直接,更加清晰的寫法,就選擇它,即使它看起來更長,更笨,也一樣選擇它

寫無懈可擊的代碼

處理所有可能出現的情況,避免漏掉corner case。if語句就要把else情況都寫上。

正確處理異常

Java的函數如果出現問題,一般通過異常(exception)來表示。你可以把異常加上函數本來的返回值,看成是一個“union類型”。

  1. catch異常的時候,你不應該使用Exception這麼寬泛的類型或者。你應該正好catch可能發生的那種異常A。使用寬泛的異常類型有很大的問題,因爲它會不經意的catch住另外的異常(比如B)
  2. 在自己函數的類型加上throws Exception,那麼你就不可避免的需要在調用它的地方處理這個異常,如果調用它的函數也寫着throws Exception,這毛病就傳得更遠
  3. try { … } catch裏面,應該包含儘量少的代碼,一個try裏包含做一件事的邏輯代碼

正確處理null指針

儘量不要產生null指針。儘量不要用null來初始化變量,函數儘量不要返回null。如果你的函數要返回“沒有”,“出錯了”之類的結果,儘量使用Java的異常機制

不要catch NullPointerException,而應該是在角色函數裏處理過濾空指針

不要把null放進“容器數據結構”裏面

要強硬的態度,你要告訴函數的使用者,我的參數全都不能是null,如果你給我null,程序崩潰了該你自己負責,採用強硬態度一個很簡單的做法是使用Objects.requireNonNull()

使用@NotNull和@Nullable標記,它們的作用是:IntelliJ本身會對含有這種標記的代碼進行靜態分析,指出運行時可能出現NullPointerException的地方。在運行時,會在null指針不該出現的地方產生IllegalArgumentException

使用Optional類型,設計原理,就是把“檢查”和“訪問”這兩個操作合二爲一,成爲一個“原子操作”。

附帶:Java裏closure的自由變量是隻讀的。所以內部類裏的函數可以讀外部的局部變量,但是不能對其進行寫操作。

過度工程的徵兆

  1. 就是當你過度的思考“將來”
  2. 過度的關心“代碼重用”
  3. 過度地關心“測試”

小結

如果對上面的概述若有所思,有更多詳細的細節在原文裏-編程的智慧

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章