隨手扎
【閱讀筆記】編寫可讀代碼的藝術
編寫可讀代碼的藝術(The Art of Readable Code) - 閱讀筆記
這本書有些地方是不合時宜的、我不太認同的,尤其是關於JS的部份,畢竟ES6後JS這個語言本身變化得非常多。我還是想引用Bob大叔在《Clean Code》的裡寫的:
當然,本書的許多建議是具爭議性的,你或許不會完同意這些意見,…… ,我們也無法主張自己的看法就是最終的權威。……。所以先不論你是否同意我們的想法,如果你根本沒有看到,或尊重我們的看法,你應該要感到羞愧。
– by Robert C. Martin(人稱Bob大叔(Uncle Bob))。Clean Code無暇的程式碼。
總之,儘管有些部份與自己作法略有不同,但不管是內容,還是內文漫畫(cartoon1真的話的很有趣)都有很大閱讀的價值,非常推薦!
推薦指數:★★★★☆
閱讀日期:2020/05/07
Yourdon 和 Constantine在其著作《Structured Dsign》中寫到: 軟體成本由開發成本與維護成本組成,而往往維護成本要高於開發成本。
…。最後,作者還給出了3個解決方案的比較,從程式碼行數、時間複雜度、記憶體消耗和準確率4個因素出發,全面權衡了各個解決方案的優劣,以此來印證作者在本書中一直推崇的編碼技巧。
– 節錄 推薦序
在《Clean Code》一書中Bob大叔認為在代碼閱讀過程中人們說髒話的頻率是衡量代碼品質的唯一標準。
– 節錄 譯者序
其實我沒啥印象這句話,但兩本書都有寫到應該是了吧。之後在考慮回去翻翻Clean Code,或是帶去營中重看一遍。
不過我好像應該先看這本再去看重構的XD。(罷了,重構好像還有一兩本在我的待讀書單內)
值得注意的章節目錄
- 第一部份 表面層次的改進
- 把資訊裝到名字裡
- 不會誤解的名字
- 審美(排版)
- 該寫怎樣的註釋
- 寫出言簡意賅的註釋
- 第二部份 簡化循環和邏輯
- 把控制流程變得更易讀
- 從函數中提前返回
- 最小化嵌套
- 拆分超長的表達式(解釋變量)
- 減少變量與縮小作用域
- 第三部份 重新組織代碼
- 抽取不相關的子問題(拆分問題)
- 一次只做一件事
- 把想法變成程式碼
- 少寫代碼
- 別費神實現那個功能–你不會需要它
- 質疑拆分你的需求
- 保持最小代碼庫
關鍵思想
- 代碼應當易於理解
- 代碼的寫法應該使別人理它所需要的時間最小化(別人有可能是幾個月後的自己)
當我們說"理解"時,我們對於這個詞有很高的標準。如果有人真的完全了解你的代碼,他就應該能夠改動它、找出缺陷並且明白它是如何與你的代碼的其他部份交互的。
……。那個"其他人"可能就是6個月後的你自己,…- 可讀性基本定理總是優先於本書中任何其他條例或原則 。而且,有些開發人員對於任何沒有完美地分解的代碼都不自覺地想要修正它。這時很重要的是要停下來並且想一下:“這段程式碼容易理解嗎?“如果容易,可能轉而關注其他程式碼是沒有問題的。
把資訊裝到名字裡 - 輸入長名字不再是個問題
現在編輯器軟體自動補全都很好用,而且越來越聰明。
編輯器 命令 Vi Ctrl+p Emacs Meta+/(先按 ESC
,然後按/
。或是Alt+/
)Eclipse Alt+/ IntelliJ IDEA Alt+/ TextMate ESC
有些還可以自定義按鍵。看到這表格,不禁讓我在想Eclipse和IntelliJ IDEA可能也有受到Emacs的影響。
儘管如此,名字也不該太長,應該具體、有意義、不容易誤解,必要時使用專業詞彙。
名字越長越南紀,在螢幕上佔據的地方也越大,可能此為產生更多的換行。…
…在小的作用域裡可以使用短的名字。
審美
有三條原則:
- 使用一致的布局,讓讀者很快就習慣這種風格。
- 讓相似的程式碼看上去相似。
- 把相關的程式碼分組,形成不同區塊
關鍵思想 : 一致的風格比"正確"的風格更為重要
※ 注意第三點不表示要拆分成許多不同的函式。
審美。常常能大幅地提高可讀性。
註釋
關鍵思想
- 註釋的目的是盡量幫助讀者了解和作者一樣多。
- 註釋應當有很高的訊息/空間率。
- 不要為註釋而註釋。有時候只是需要改個名字或寫法。
- 紀錄你的思想
- 有些可能嘗試過未果的事情,可以紀錄下來避免其他人再去嘗試而浪費時間
- 紀錄程式碼中的瑕疵(TODO、WARN、FIXME等)。
- 給常量加註釋
- 總結性註釋
註釋應該說明"做什麼”、“為什麼”、“怎麼做”?
我們的建議是你可以做任何能幫助讀者更容易理解代碼的事。
我們把註釋這件事拆成了幾個簡單的步驟:
- 不管你心裡想什麼,先把他寫下來。
- 讀一下這段註釋,看看有沒有什麼地方可以改進。
- 不斷改進
邏輯
關鍵思想:
- 相對於追求最小化程式碼行數,一個更好的度量方法是最小話人們理解它所需要的時間。
- 少用尤達表達式2,現在編譯器/直譯器夠聰明了,還有其他輔助檢測工具。
- 優先使用正邏輯而不是負邏輯的情況(用
if(debug)
而不是if(!debug)
)
函數中提前返回
想要單一出口點的一個動機是保證調用的函數結尾的清理代碼。但現在的程式語言為這種保證提供了更精細的方式:
語言 清理代碼的結構化術語 C++ 析構函數 Java、Python try finally Python with C# using
關於goto
有些時候使用goto更易讀(記得最重要的關鍵思想)。但是Python並沒有goto
3,這是因為結構化風格認為,goto
會造成程式碼的混亂。記得有一篇討論說到,如果你必須使用goto
,那你更可能需要將程式碼拆分成不同函式。(注:後來查過,那篇討論的是label break
4,不過有些相似就不改原本寫法了XD)
儘管如此,我還是喜歡保留goto
,畢竟有時寫起來好看也比較自由。(當然可能跟人合作時封印比較好)
關鍵思想:
當你對程式碼做改動時,從全新的角度審視它,把他作為一個整體來看待。
你能理解執行的流程嗎
理想的情況是,整個程序的執行路徑都容易理解–從main()開始,然後在腦海中一步步執行代碼,一個函數調用另一個函數,直到程序結束。
儘管如此,有些寫法無法單一流向那麼清晰,比如使用到Thread。 關鍵是不要讓程式碼中使用這些結構的比例太高。
最近有研究表明,我們大多數人同時只能考慮3~4件"事情”。
關鍵思想 :把你的超長表達是拆分成更容易理解的小塊。
- 拆分表達式最簡單的方法就是引入一個額外的解釋變量。
- 使用笛摩根定理
關於巨集/宏
請注意,我們不鼓吹經常使用宏–事實上,我們通常避免使用宏,因為它們會讓程式碼變得令人困惑並且引入細微的bug。但有時,就像在本例中,它們很簡單而且對可讀性有明顯好處。
– page.89
小節
解釋變量的三個好處:
- 把巨大表達式拆成小段
- 通過簡單的名字讓程式碼文檔化(程式碼本身可以解釋自己,無須註釋)
- 幫助讀者識別程式碼中的主要概念
你希望你的同事隨時都覺得是在面試嗎?(面試題目會故意難,以測驗出程度)
變量與可讀性
關鍵思想:
- 讓你的變量對盡量少的程式碼中可見。(縮小作用域)
- 操作一個變量的地方越多,越難確定它的當前值。
簡少變量
我們感興趣的是減少不能改進可讀性的變量。(Ex:臨時變量)
重新組織代碼
三種組織程式碼的方法:
- 抽取那些與程序主要目的的"不相關子問題”。
- 重新組織程式碼它一次只做一件事情。
- 先用自然語言描述代碼,然後用這個描述來幫助你找到更簡潔的解決方案。
抽取不相關子問題
純工具代碼 / 創建大量通用程式碼
通常來講,如果你在想:“我希望我們的庫裡有XYZ()函數”,那麼就寫一個!(如果它還不存在)經過一段時間,你會建立一組不錯的工具代碼,後者可以應用於多個項目。
從你的項目拆分出越多獨立的庫越多越好,因為你的程式碼的其他部份會更小而且更容易思考。
簡化 / 包裝 界面(wrap interface)
簡單說…如果原本API命名不足以明確表達意思,那就包一個名字上去(還可以簡化參數)。
把想法變成程式碼
這件事情覺得很有意思,記下。
某個大學計算機實驗室的規定聲稱當有學生需要別人幫它調試程式時,他首先要對房間角落的一只專用的泰迪熊解釋他遇到的問題。
自然語言描述程序然後用這個描述來幫助你寫出更自然的程式碼。
如果你不能把問題說明白或者用詞語來做設計,估計是缺少了什麼東西或者什麼東西缺少定義。把一個問題(或想法)變成語言真的可以讓它更具體。
這讓我想到松本行弘說的5:
最根本的理由是:語言體現了人類思源的本質。
「把想法變成語言」恩?程式語言也是語言吧?真貼切。
少寫程式碼
關鍵思想:
最好讀的程式碼就是沒有程式碼。冒險、興奮–絕地武士追求的並不是這些。
– 尤達大師
別費神實現那個功能–你不會需要它
…。我們熱關地估計了實現一個粗造原形所要花的時間,但忘記了將來程式碼的維護、文件以及後增的"重量"所帶來的額外時間。
質疑和拆分你的需求
不是所有程序都需要運行的很快,100%正確,並且能處理所有的輸入。如果你真的仔細檢查你的需求,有時候你可以把它消滅成一個簡單的問題,只需要較少的程式碼。
讓你的程式碼庫越小,越輕量級越好
刪除沒用的程式碼
…一個有創造性的領域–攝影家、作者和電影製作人也不會保留他們的所有工作。
也是,電影花絮外,聽說還有一堆未公開的刪除片段。
熟悉你週邊的函式庫
每個一段時間,花15分鐘來閱讀標準函式庫中的所有函數/模塊/類型的名字。…下次你寫新程式碼時會想到:“等下,這聽起來和我在API中見到的東西有點像…”
這沒問題,我都偶爾會去看下Python有啥新東西。其他語言也會去看下。(不過目前不大行QQ,營區無法自由上網…
測試的可讀性
測試與一般程式不同,但也是程式。那就應該盡可能遵守核心思想:程式碼應該易讀。
關鍵思想:
測試應該具有可讀性,以便其他程式開發人員可以舒服地改變或者增加測試。最為一條普遍的測試原則,你應當” 對使用者隱去不重要的細節,以便更重要的細節會更突出 “。
※ “測試"是指任何僅以檢查另一段程式碼行為為目的的程式碼。
測試驅動開發(TDD)
這是一個爭論很激烈的話題,我們不想攪近來。至少, 我們發現僅通過在寫程式時想著測試這件事就能幫助程式碼寫得更好。
別走得太遠
別忘了核心原則。有些原則衝突時,通常以可讀性優先。
!!不要!!:
- 犧牲程式碼的可讀性,只是為了能夠測試。
- 著迷於100%的測試覆蓋率。
實際上你永遠也部會達到100%的測試覆蓋率。如果不是因為漏掉bug,也可能是因為漏掉的功能或者你沒想到說明書應該改一改。
如果你在見一個網站原型,可能寫任何測試程式都是不值得的。 - 讓測試成為產品開發的阻礙。
其他
透過同事來幫助我們解決問題。
如果你不能把一件事情解釋給你祖母聽的話說明你還沒有真正理解他。
– 阿爾博特˙愛因斯坦
延伸閱讀
- 【心得筆記】軟體品質相關文章閱讀心得
- 【心得筆記】這幾天看完的文章 紀錄
- Clean Code 無暇的程式碼
- 無瑕的程式碼 JavaScript
- 可不可以不要寫糙 code
- Code Complete
- Refactoring: Improving the Design of Existing Code
- The Pragmatic Programmer: From Journeyman to Master
- JavaScript: The Good Parts 我猜這本可能有點舊了。JS在ES6變化很多。但可能有些思想還是值得盤借。
- Effective Java
- 設計模式
- Programming Pearls
- Joel on Software: And on Diverse and…
- Smalltalk Best Practice Patterns
- The Elements of Programming Style
- Literate Programming
與其把我們主要的任務想像成指示給幾算機做什麼,不如讓我們關注解釋給人類希望我們讓機算機做什麼
卡通為英語cartoon的音譯,是指圖畫,是創造性思維的非寫實風格以及超脫現實和夢想的藝術,或是故事連環畫和四幅一組的漫畫。(維基百科) ↩︎
尤達條件式。維基百科。是一種計算機編程中的編程風格,其中表達式的兩個部份與條件語句中的典型順序相反。尤達條件式將表達式的常數部份放在條件語句的左側。這個風格的名稱源於星際大戰絕地大師尤達的角色,他以非標準語法講英語。 ↩︎