程式碼的藝術 - 章淼講座筆記
清華大學計算機博士;百度雲前端技術負責人;百度Golang
&Python
技術委員會成員;
筆記
對比 Google 的工程師,國內的工程師寫程式碼的佔用時間顯然過多了,而不太注重提前設計 ;Google 工程師們在開始實現某一模組或功能時,會事先在程式碼庫中搜索是否已經有可重用的程式碼,並且程式碼庫中的程式碼具有完整的註釋和文件。
提前設計的重要性
儘可能地提前 完成兩個文件
- 需求分析文件
- 系統設計文件
原因:在未啟動實現細節程式碼之前構思設計時發現問題的修改,對比後期真正已經開始 Coding 的時候,對比發現問題進行修改,成本要低很多。文件一般只寫主要邏輯,而程式碼涉及更多細節。
筆者備註:但這不是絕對的,修改是正常的,不要懼怕修改,反覆嘗試積累經驗。
- 需求分析文件:主要是在定義黑盒狀態,描述外在,描述 WHAT 要做什麼?
- 系統設計文件:主要實在定義白盒狀態,描述內在,描述 HOW 怎麼做?
兩者要有區分,不要混淆 ,也不要混在一起寫!
-
需求分析文件的誤區
不要過早提前構想實現細節,我們的大腦會下意識地在我們構想如何實現時遇到的各種難題,而將原本的需求分析的思考掛起;舉例:導彈 vs 炸彈,兩者都有摧毀目標的能力,但是很明顯導彈的價值更高,重要的是制導的功能,而不是爆炸本身。 -
系統設計文件的誤區
主要要寫定義系統的架構、模組、介面、資料、關鍵演算法、設計思路等等得過程記錄。
系統架構要寫什麼以及方法
概念、模型、檢視等等。
- 靜:系統靜態的樣子,功能模組如何劃分等
- 動:系統運轉起來,各模組聯動起來的樣子
-
細:不同角度,不同層次去描述
-
每一個元件(模組、函式)保證單一性,Single purpose. 只做一件事!
- 輕耦合,低內聚(避免全域性變數(多處操作難以控制))
- 當前系統設計所受到的約束(當前設計的瓶頸在哪?比如網路、吞吐量、佔用 CPU 或檔案位置資源等)
- 需求分析是系統設計的來源
- 模型和抽象的思維能力很重要(涉及概念:模型、資料結構、演算法等等)
設計介面(Interface)要注意什麼?
- 介面定義系統外在的功能
- 介面定義當前系統與外部系統之間的關係
介面 Interface 定義了系統對外的介面,往往比系統實現內部細節程式碼更重要,不要過於草率,因為一旦定義了介面,提供出去給呼叫方使用,想修改就太難了。所以設計介面有重要原則,站在使用者的角度考慮問題!
兩點細節:
- 向前相容(儘量不要介面已升級,老介面全不能用,那就不是好的介面設計)
- 使用方便(讓呼叫者可以一目瞭然知道介面的作用,簡化傳參,說明返回值等等)
如何寫程式碼?
程式碼是一種表達的方式。是寫給人看的,要有程式設計規範 。
擁有程式設計規範的理想狀態:1. 看別人程式碼就像看自己程式碼一樣易懂;2. 看程式碼主要看邏輯,不要過多注重細節;3. 程式碼儘可能地不要讓人去多想。
Don’t make me think!
Moudle 模組
緊內聚,低耦合。單一功能。反例,定義一個utils.py
內部包含諸多方法,不易懂。
模組一般可以分為兩類:
- 資料類的模組(1. 主要完成對資料的封裝; 2. 對外提供的資料介面)
- 過程類的模組(1. 不要包含資料,可以是呼叫資料類的模組或者呼叫其他過程類模組; 2. 具備操作性質的模組)
模組的重要性:1. 降低維護成本; 2. 更好地複用
Class 類 和 Function 函式
兩者是不同的模型,各自有各自適用的範圍。
推薦方法:和類的成員無關的函式,儘量獨立出去單獨一個函式,不建議作為類的成員函式。
面向物件思想的討論:多型和繼承,需要謹慎適用,作為Python
的工程師,不太推崇Java
中繼承和多型,因為系統是逐漸長起來的,並不是從一開始就是一個成熟的樣子,所以很難憑空去設計一個繼承的關係。
模組的構成
檔案頭(註釋)
- 模組的說明,簡要功能
- 修改歷史(時間、修改人,修改的內容)
- 其他特殊細節的說明
函式(重要性僅次於模組)
- 描述功能
- 傳入引數的描述(含義、型別、限制條件等等)
-
返回值得描述(有足夠明確的語義說明)
- 邏輯判斷型 check isXXX
- 操作型(成功 or 失敗)
- 資料獲取型(狀態 + 資料)
- 異常如何處理(是丟擲?還是內部catch?要明確)
- 明確單入口和單出口(多執行緒開發時尤為重要)
函式要儘可能的規模小,足夠短(BUG 往往出現在非常長的一個函式裡)
程式碼塊的分段 也很重要,分段背後是劃分和邏輯表達。
程式碼是一種表達能力的體現,也算是文科的範疇!註釋不是補出來的!
命名的重要性:要準確、易懂、可讀性強,儘量做到望名生義
。
網際網路時代的系統是運營 出來的。
可檢測性也是尤其重要的。(埋點、監控等等)
沒有資料的收集,等於系統沒有上線。
監控不單單隻有傳統意義上的記憶體、CPU、網路、崩潰率的監控,還應有線上真實資料監控,需要有足夠多的狀態記錄。
日誌是很有限的一種監控手段,並且採集日誌也是一種資源耗費。推薦的手段:可以使用埋點,對外提供介面,有單獨的系統呼叫介面進行有針對性的採集。
修身
好的程式員,與工作年限 無關,與學歷 無關
學習-思考-實踐
學習:主觀意願地學習,途徑也有很多,例如書籍、開原始碼、社群。忌諱夜郎自大、井底之蛙。注重培養自己學習吸收的能力,多讀多看但是數量不是最終目的。
Stay Hungry, Stay Foolish. – Steve Jobs
思考:學習需要經過思考,形成自己的思維。
實踐:《卓有成效的時間管理者 - 德魯克》推薦閱讀
知識-方法-精神
知識過時會非常快!
方法:分析問題、解決問題的能力尤其重要(定義問題、識別問題、定義關鍵問題)
精神:決定型,要做就要堅持做
前進的道路上不能永遠都是鮮花和掌聲。
基礎乃治學之根本。
資料結構、軟體工程、邏輯思維能力、研究能力,需要5-8年時間磨鍊。