date: 2017-12-26 22:52:46
title: 「編程風格: 好代碼的邏輯」 讀書筆記
編程風格 - 圖靈社區: http://www.ituring.com.cn/book/1724
編程風格 - 百度腦圖: http://naotu.baidu.com/file/3c02e1c237197b958ce2068fb8c297bf?token=9cc47ce46f4699e1
這引用圖靈社區的聽到的一個段子:
編程活久見, 你總有遇到的一天
看完這本書, 以后就不容易發出 還有這種操作 的感慨了.
悠久的歷史
往日的美好
就讓這 往日的美好 時刻警醒我們, 寬裕的內存與合適的名字 是多么的美好
Forth 風格
有一個 數據棧 有一個 數據堆, 開發者以 過程 的形式抽象(一組指令)
基本風格
單片風格
- 沒有命名的抽象對象
- 沒有或幾乎不使用庫
一長串的代碼, 而且從頭至尾沒有提出任何新的抽象概念, 也沒有使用許多庫里已有的抽象概念.
食譜風格
- 沒有長跳轉
- 過程函數
- 全局變量共享狀態
一般認為, 過程函數對這一變量具有副作用
流水線風格
- 函數間無狀態共享
- 復合函數
高爾夫風格
- 盡可能簡化代碼
函數組合
無限鏡像風格
- 使用歸納法, 對問題或其核心部分進行建模
骨牌風格 Kick Forward
- 每個函數都有一個額外的參數, 通常是最后一個, 該參數是另一個函數
- 在函數的末尾, 函數參數會被調用
單子風格
- 封裝數據, 使之抽象化
- 將若干函數逐個綁定在抽象上, 建立函數調用順序
- 打開封裝, 查看數據最終結果
對象與對象交互
對象風格
- 較大問題被分解為問題域相關的對象
- 每一個對象都是一個數據封裝, 過程暴露在外面
- 數據只能通過這些過程訪問, 不可直接訪問
- 每個對象可以重新定義在其他對象中已經定義好的過程
消息風格
- 較大問題被分解為問題域相關的對象
- 每個對象是僅公開一個過程的數據封裝, 只能接收和發送消息
- 消息分發機制能將消息發送至另一個封裝
閉域風格
- 較大問題被分解為問題域相關的對象
- 每個對象是一個鍵值映射, 其中某些值是 過程/函數
- 對象的方法引用對象自身的鍵, 使得映射是閉的
抽象對象風格
- 較大問題被分解為問題域相關的對象
- 抽象對象的定義是對對象抽象的行為
- 具體對象以某種方式與抽象對象綁定, 綁定機制不定
- 應用程序的其他部分并不依賴對象的內容, 而依賴對象的行為
好萊塢風格
- 利用不同形式的抽象(對象/模塊等), 將較大問題分解成若干個實體
- 這些實體不能被直接調用
- 這些實體為其他實體提供接口, 使其他函數能注冊回調
- 在計算的特定情景中,這些實體調用其它已注冊過回調的實體
公告板風格
- 發布事件訂閱事件
- 公告板執行所有事件管理和分配工作
反射與元編程
內省風格
- 利用不同形式的抽象(對象/模塊等)分解較大問題
- 抽象可以獲得自身以及其他抽象的信息, 但不能改變這些信息
反射風格
- 內省
- 程序在運行時, 可以通過增加對象/變量等方法進行自我修改
切面風格
- 問題的切面
- 一個外部綁定機制將抽象和切面綁定在一起
插件風格
- 主程序與每個包單獨被編譯
- 有一個外部說明來定義哪些包需要被加載, 通常形式為 配置文件/路徑約定/用戶輸入/其他用于運行時加載外部代碼的機制
異常處理
構建風格
- 每一個函數檢查自身參數的和合理性, 當參數不合理時, 返回合理的結果/給參數制定合理值
- 所有的代碼塊檢測可能存在的錯誤, 當發生錯誤時, 跳過代碼塊, 設置合理的狀態,并繼續執行函數的其他部分
Tantrum 風格
- 每一個函數檢查自身參數的和合理性, 當參數不合理時, 程序停止運行
- 所有的代碼塊檢測可能存在的錯誤, 當發生錯誤時, 可能將上下文相關的信息寫入日志, 同時將錯誤傳遞回函數調用鏈
消極攻擊風格
我現在是沒有抗議的, 但這是不對的, 我遲早會抗議的
- 每個過程和函數分別檢查參數的合理性, 當參數不合理時, 停止運行并跳出
- 在調用其他函數時, 程序僅檢測能夠提供有意義反饋的錯誤
- 異常處理在函數調用鏈中位于叫上層合適的位置, 僅在程序的最外層進行異常處理, 無視異常實際發生的位置
聲明意圖風格
- 類型申明
隔離風格
- 核心程序沒有任何副作用, 包括 IO
以數據為中心
持久表風格
- use db: 持久數據/查詢數據
試算表風格
- excel: 試算表 -> 數據流編程
漂流風格
- 數據可用形式為數據流, 而不是一個整體
- 函數是數據流的 過濾器/變換器
- 根據下游的需求對上游的數據進行處理
并發
參與的風格
- 與消息風格類似, 但其中每個對象在獨立線程中運行
數據空間風格
- 并發單元只能通過數據空間進行數據交換
Map Reduce 風格
數據分塊 -> 并行 Map -> Reduce 重組成輸出
雙重 Map Reduce 風格
第二個 Map 使用 Reduce 作為參數, 達到 Map/Reduce 都并行執行
交互
三層架構風格
- MVC
- 所有實體均與這三者之一相關, 每部分職責不同
Restful 風格
- 資源的 CRUD
詞匯表(知識點)
列表: list, 對應其他語言中 數組(array)
元組: tuple, 不可變列表, 其他語言中通常使用 常量(const)
列表下標: 數組下標, 著名的從 0 開始計數
上下界: 著名的 數值溢出/數組越界 問題
字典: dict, 對應其他語言的 hash/map
self: 對應其他語言的 this
構造函數: __init__
, 對應其他語言的 __construct()
OOP: object-oriented programming
類 對象 屬性 方法 擴展/繼承/覆蓋 實例 單例
基類 = 超類 vs 繼承類 = 子類
抽象類: 不能直接實例化的類, 只能被其它類繼承
代理: 某個對象使用其他對象的方法執行過程的能力
消息分發: 接受消息/解釋消息標簽并確定執行步驟的過程. 該過程可能是 方法執行/錯誤返回/向其他對象轉發消息
原型: 無類面向對象語言中的對象. 原型帶有自己的數據和函數, 可以自由的改變而不影響其他對象. 新原型可以通過復制已存在的原型獲得
抽象數據類型: 通過自身操作抽象定義的實體
裝飾器: 其設計目的在于允許行為被增加在個別對象上, 能夠在不改變源代碼的情況下改變函數和方法
控制反轉: 任何支持獨立開發的代碼, 被通用庫和組件調用的技術
事件 - 發布 - 訂閱
內省: 程序獲取自身信息的能力
反射: 程序獲取自身信息并自我修改的能力
什么時候需要反射: 在設計過程中, 當無法預期代碼被修改的方式時, 會使用反射
eval
切面: 受限制的反射; 關注于分析已有問題分解的實現是否違背使用非反射分解方式集中代碼程序; 關于高熵源代碼的話題
AOP: aspect-oriented programming, 面向切面編程
依賴注入: 支持動態加載函數和對象具體實現的技術
插件: plugin/addon
錯誤代碼: errorno, 特定組件指示錯誤信息
異常: 程序運行中超出正常預期的情景; 一種 有結構的/良性的/受限制 的 GOTO 語言替代方案
動態類型檢查 vs 靜態類型檢查
顯示類型 vs 隱式類型
強制類型轉換 vs 類型推理 vs 類型安全
ACID: atomicity consistency isolation durability -> 保證一致性
Tantrum-ish: 保守方式
RDB
NoSql: 對象關系型
公式: 函數 -> 根據其他值, 在數據空間上, 更新某個值
協同程序: 支持推遲和恢復執行的多個入口和出口的程序
生成器: (即半協同程序)一種特殊的協同程序, 用于控制值的迭代. 生成器通將控制返回至調用方, 而不是程序任意一處
迭代器: 用于遍歷值的對象
參與者: 擁有獨立線程的對象/網絡中每某個處理節點. 參與者擁有一個接收消息的隊列, 參與者之間通過發送消息交互
異步請求: 在異步請求中, 請求者不等待回復, 回復在請求結束后返回
消息: 發送者與接收者之間信息的數據結構, 該過程可能通過網絡實現
基底(substrate) 元組 數據 空間: 類型數據對象
數據操作三個原語: in / out / read; put / get / sense
主動 MVC vs 被動 MVC
主存: RAM, 內存, 能夠被 CPU 直接訪問
輔存: 借助內存才能被 CPU 訪問(硬盤等)
棧: 數據結構; 支持內存執行的活動區域; 過程/函數調用的數據
堆: 數據結構; 動態內存的分配和釋放
棧機器: 使用棧而不是寄存器來支持程序表達式的計算
棧溢出: 程序耗盡棧內存的情況
尾遞歸: 在函數尾部發生的遞歸調用
尾遞歸優化
控制流: 程序指令的執行順序和表達式的評估順序, 包括 條件/迭代/函數調用/返回等
副作用: 副作用是指一個程序中能觀察到的變化部分. 副作用包括 向文件/屏幕寫 / 讀取輸入 / 改變可觀測變量的值 / 引起異常等. 程序通過副作用與外部相互作用
冪等性: 若一個函數和過程是冪等的, 對其進行多次調用將觀察到同樣的結果, 與一次調用的效果毫無二致
不可變變量 vs 可變變量
過程函數
高級函數: 把函數作為輸入或者輸出的函數
柯里化: 一種將多參數函數轉化成一系列高階函數的組合技術, 其中每個高階函數只帶有一個參數
函數: 在數學中, 函數是一種輸入映射到輸出的關系; 在編程中, 函數是接收輸入并產生輸出的過程
純函數 vs 非純函數: 是否受外界因素影響
惰性計算: 一種程序執行策略, 直到需要計算結果時才執行計算
后續: 后續是一個表示 程序剩余部分 的函數. 該概念服務于不同目的, 優化編譯器/提供指稱語義/異步處理. 又因為能夠為函數的非本地返回, 提供一般化的機制, 后續也作為 goto 語句/異常 等語言結構的替代方案
回調地獄: 一種面條是代碼的形式, 因嵌套了過多重匿名函數作為參數而形成
單子: 一種將已定義的計算步驟封裝的結構. 一個單子包含兩個主要操作: 構造函數創建單子的同時封裝數據; 綁定操作以函數作為參數以某種方式將函數綁定在單子上, 并返回單子(可能是單子本身). 除此之外的第三種操作用于 打開封裝/輸出/計算 此單子
回調函數
框架: 一類特殊庫/可重用組件, 提供一個能被進一步開發的通用應用程序功能
圈復雜度: 一個用來衡量代碼復雜度的標準 CC = E - N + 2P
LOC: line of code; SLOC, source line of code