讀書筆記---《編寫可讀代碼的藝術》

前言

咱們曾經在很是成功的軟件公司中和出色的工程師一塊兒工做,然而咱們所遇到的代碼仍有很大的改進空間。實際上,咱們曾見到一些很難看的代碼,你可能也見過。可是當咱們看到寫得很漂亮的代碼時,會很受啓發。好代碼會很明確告訴你它在作什麼。使用它會頗有趣,而且會鼓勵你把本身的代碼寫得更好。本書旨在幫助你把代碼寫得更好。程序員

每一章都會深刻編程的某個方面來討論如何使代碼更容易理解。本書分紅四部分:表面層次上的改進命名、註釋以及審美——能夠用於代碼庫每一行的小提示。簡化循環和邏輯在程序中定義循環、邏輯和變量,從而使得代碼更容易理解。從新組織你的代碼在更高層次上組織大的代碼塊以及在功能層次上解決問題的方法。spring

第1章 代碼應當易於理解

  • 代碼的寫法應當使別人理解它所需的時間最小化。
  • 減小代碼行數是一個好目標,但把理解代碼所需的時間最小化是一個更好的目標。
  • 常常想想其餘人是否是會以爲你的代碼容易理解

第一部分 表面層次的改進

  • 選擇好的名字
  • 寫好的註釋
  • 把代碼整潔地寫成更好的格式

第2章 把信息裝到名字裏

  • 把信息裝進名字中
  • 選擇專業的詞
    • 避免使用tmp、retval、it、foo泛泛的詞
    • 若是不把循環索引命名爲(i、j、k),另外一個選擇能夠是(clubi、membersi、user_i)或者,更簡化一點(ci、mi、ui)
  • 用具體的名字替代抽象的名字
  • 使用前綴和後綴來給名字附帶更多信息
  • 決定名字的長度
    • 在小的做用域裏可使用短的名字
  • 利用名字的格式來表達含義

第3章 不會誤解的名字

  • filter是個二義性單詞。咱們不清楚它的含義究竟是「挑出」仍是「減掉」。最好避免使用「filter」這個名字,由於它太容易誤解。
  • 推薦用min和max來表示(包含)極限
  • 建議 命名極限最清楚的方式是在要限制的東西前加上max或者min
  • 推薦用first和last來表示包含的範圍
  • 推薦用begin和end來表示包含/排除範圍
  • 一般來說,加上像is、has、can或should這樣的詞,能夠把布爾值變得更明確。
  • 不少程序員都習慣了把以get開始的方法當作「輕量級訪問器」這樣的用法,它只是簡單地返回一個內部成員變量。若是違背這個習慣極可能會誤導用戶。相反,這個方法應當重命名爲像computeMean()這樣的名字,後者聽起來更像是有些代價的操做。

第4章 審美

你們都願意讀有美感的代碼。經過把代碼用一致的、有意義的方式「格式化」,能夠把代碼變得更容易讀,而且能夠讀得更快。下面是討論過的一些具體技巧:編程

  • 若是多個代碼塊作類似的事情,嘗試讓它們有一樣的剪影,使用一致的佈局,讓讀者很快就習慣這種風格
  • 把代碼按「列」對齊可讓代碼更容易瀏覽
  • 若是在一段代碼中提到A、B和C,那麼不要在另外一段中說B、C和A。選擇一個有意義的順序,並始終用這樣的順序
  • 用空行來把大塊代碼分紅邏輯上的「段落」。

第5章 該寫什麼樣的註釋

註釋的目的是幫助讀者瞭解做者在寫代碼時已經知道的那些事情。本章介紹瞭如何發現全部的並不那麼明顯的信息塊而且把它們寫下來。什麼地方不須要註釋:mybatis

  • 能從代碼自己中迅速地推斷的事實
  • 用來粉飾爛代碼(例如蹩腳的函數名)的「柺杖式註釋」——應該把代碼改好。你應該記錄下來的想法包括:
    • 對於爲何代碼寫成這樣而不是那樣的內在理由(「指導性批註」)
    • 代碼中的缺陷,使用像TODO:或者XXX:這樣的標記
    • 常量背後的故事,爲何是這個值。
    • 站在讀者的立場上思考:預料到代碼中哪些部分會讓讀者說:「啊?」而且給它們加上註釋
    • 爲普通讀者意料以外的行爲加上註釋
    • 在文件/類的級別上使用「全局觀」註釋來解釋全部的部分是如何一塊兒工做的
    • 用註釋來總結代碼塊,使讀者不致迷失在細節中

第6章 寫出言簡意賅的註釋

本章是關於如何把更多的信息裝入更小的空間裏。下面是一些具體的提示:框架

  • 當像「it」和「this」這樣的代詞可能指代多個事物時,避免使用它們
  • 儘可能精確地描述函數的行爲
  • 在註釋中用精心挑選的輸入/輸出例子進行說明
  • 聲明代碼的高層次意圖,而非明顯的細節
  • 用嵌入的註釋(如Function(/arg =/...))來解釋難以理解的函數參數
  • 用含義豐富的詞來使註釋簡潔

第二部分 簡化循環和邏輯

第7章 把控制流變得易讀

有幾種方法可讓代碼的控制流更易讀函數式編程

  • 在寫一個比較時(while (bytesexpected > bytesreceived)),把改變的值寫在左邊而且把更穩定的值寫在右邊更好一些(while (bytesreceived <; bytesexpected))
  • 你也能夠從新排列if/else語句中的語句塊。一般來說,先處理正確的/簡單的/有趣的狀況。有時這些準則會衝突,可是當不衝突時,這是要遵循的經驗法則
  • 某些編程結構,像三目運算符(:?)、do/while循環,以及goto常常會致使代碼的可讀性變差。最好不要使用它們,由於老是有更整潔的代替方式
  • 嵌套的代碼塊須要更加集中精力去理解。每層新的嵌套都須要讀者把更多的上下文「壓入棧」。應該把它們改寫成更加「線性」的代碼來避免深嵌套。一般來說提前返回能夠減小嵌套並讓代碼整潔。「保護語句」(在函數頂部處理簡單的狀況時)尤爲有用。

第8章 拆分超長表達式

  • 把超長表達式拆成更容易理解的小塊
  • 引入解釋變量

第9章 變量與可讀性

關於程序中的變量是如何快速累積而變得難以跟蹤的。你能夠經過減小變量的數量和讓它們儘可能「輕量級」來讓代碼更有可讀性。具體有:函數

  • 減小變量,即那些妨礙的變量。咱們給出了幾個例子來演示如何經過馬上處理結果來消除「中間結果」變量
  • 減少每一個變量的做用域,越小越好。把變量移到一個有最少代碼能夠看到它的地方。眼不見,心不煩
  • 只寫一次的變量更好。那些只設置一次值的變量(或者const、final、常量)使得代碼更容易理解。

第三部分 從新組織代碼

咱們會講到三種組織代碼的方法:工具

  • 抽取出那些與程序主要目的「不相關的子問題」
  • 從新組織代碼使它一次只作一件事情
  • 先用天然語言描述代碼,而後用這個描述來幫助你找到更整潔的解決方案

第10章 抽取不相關的子問題

  • 所謂工程學就是關於把大問題拆分紅小問題再把這些問題的解決方案放回一塊兒。把這條原則應用於代碼會使代碼更健壯而且更容易讀。
  • 積極地發現並抽取出不相關的子邏輯
    • 純工具代碼
      • 一般來說,若是你在想:「我但願咱們的庫裏有XYZ()函數」,那麼就寫一個!(若是它還不存在的話)通過一段時間,你會創建起一組不錯的工具代碼,後者能夠應用於多個項目。
    • 其餘多用途代碼
      • 當format_pretty()中的代碼自成一體後改進它變得更容易。當你在使用一個獨立的小函數時,感受添加功能、改進可讀性、處理邊界狀況等都更容易。
    • 建立大量通用代碼
    • 項目專有的功能
    • 簡化已有接口
    • 按需重塑接口
    • 過猶不及
      • 引入這麼多小函數實際上對可讀性是不利的,由於讀者要關注更多東西,而且按照執行的路徑須要跳來跳去

第11章 一次只作一件事

  • 應該把代碼組織得一次只作一件事情。

第12章 把想法變成代碼

  • 用天然語言描述程序而後用這個描述來幫助你寫出更天然的代碼。這個技巧出人意料地簡單,但很強大。看到你在描述中所用的詞和短語還能夠幫助你發現哪些子問題能夠拆分出來。 可是這個「用天然語言說事情」的過程不只能夠用於寫代碼。

第13章 少寫代碼

  • 不是全部的程序都須要運行得快,100%準確,而且能處理全部的輸入。若是你真的仔細檢查你的需求,有時你能夠把它削減成一個簡單的問題,只須要較少的代碼。
  • 咱們所描述的是宇宙的天然法則——隨着任何座標系統的增加,把它粘合在一塊兒所需的複雜度增加得更快。 最好的解決辦法就是「讓你的代碼庫越小,越輕量級越好」,就算你的項目在增加。那麼你就要:
    • 建立越多越好的「工具」代碼來減小重複代碼(見第10章)
    • 減小無用代碼或沒有用的功能
    • 讓你的項目保持分開的子項目狀態
    • 總的來講,要當心代碼的「重量」。讓它保持又輕又靈。
  • 熟悉你周邊的庫
    • 不少時候,程序員就是不知道現有的庫能夠解決他們的問題。或者有時,它們忘了庫能夠作什麼。知道你的庫能作什麼以便你可使用它,這一點很重要。

個人總結

在平常開發中,比較注重編碼規範及命名等細節,我的認爲命名和註釋寫得好是須要觀察、積累和總結的,這也很重要,同時在閱讀jdk、spring、mybatis等優秀框架源碼也發現好的命名的重要性,下面總結了一些命名及編碼方式,周知的駝峯命名、常量大寫等就不列舉了。只寫一些書中沒提到的。佈局

命名相關

  • 動賓格式命名方法
    • prepareContext、prepareEnvironment
  • 前綴命名
    • spring中doXXX是真正作事情的方法,如doLoadBeanDefinitions、doRegisterBeanDefinitions
    • preXXX、postXXX:前置、後置處理方法
    • loadXXX:loadBeanDefinitions
  • 後綴命名
    • XXXListener:一看就知道是監聽器
    • XXXFactory、XXXDelegate、XXXTemplate:使用了工廠模式、委派模式、模板模式等
  • 善用詞性
    • listeners.starting()、listeners.started(context)等不用說就知道區別,表示不一樣階段
  • 名詞單複數
    • user、users:分別表明一個用戶和多個用戶

代碼風格

  • 按功能劃分代碼,一個類不超過千行
  • 常量統一寫在頭部
  • 屢次使用的抽象成工具類
  • 語義化、函數式編程

更多信息能夠關注個人我的博客:逸竹小站逸竹小站post

也歡迎關注個人公衆號:yizhuxiaozhan,二維碼:公衆號二維碼

相關文章
相關標籤/搜索