The Pragmatic Programmer - 邁向大師之路
大家好,我是 Cindy,斷斷續續用零碎時間看了好久才把這本融合了做法與想法的書看完,覺得很好看,所以想把看到的重點記錄下來,接下來是每個章節我畫的一些重點:
務實的哲學
這章節講的比較偏軟實力的部分,從心態面開始 (我們都擁有改變的能量),講到態度面 (請提供解決問題的選擇,停止製造爛藉口),再到行為面 (請定期投資你的知識資產、批判式的分析你讀到或聽到的東西)、溝通面 (您說了什麼話,與您如何說這些話一樣地重要),很多東西其實是在社群參加活動都會從各界大大們聽到的東西,算是好的理念好的想法參加社群就會常聽到?例如在去年的 WEBCONF 的 工程師成長之路:由時間管理到職涯規劃 - 李智樺 Ruddy 這場演講其實就有提到類似的東西。
我自己感覺重點是要有正向的心態,持續學習,深入理解學習到的知識,負責任,看見問題就想辦法解決它,不要逃避,相信沒有解決不了的問題 (大不了改需求也是一種解決的方式),重視品質,並且要懂的溝通,並非工程師就不需要溝通,溝通是非常重要的技能,要用不同的方式,讓各方理解。
務實的方法
這章節更偏向於程式設計面,類似 Clean Code 或重構會提到的內容,包含以下重點:
一個好的設計比爛設計更容易改動 (ETC,Easier to Change)
有種總括了以前學過的知識,融合成一種價值觀,像是我們學過的低耦合,單一責任原則 (single responsibility principle),最終我們想要達成的就是更好改動的程式碼,而我們學過的那些方法就只是朝著這樣目標的手段之一,所以最根本的核心是要有 ETC 這樣的價值觀,在做選擇的時候可以選出當下最適合的手段。
DRY 的範圍不只是程式碼
許多人認為 DRY 的意思是不要複製和貼上程式碼,但這不是 DRY 全部的意思,DRY 是指知識以及意圖上的重複,它是在兩個不同的地方表達相同的東西,包含可能使用兩種完全不同的表達方式。
我在這邊的認知是,我們要先知道程式碼表達的意圖是否相等,表示的是否是完全相同的知識,讓我們可以判斷究竟是重複還是巧合,兩個巧合如果整理成一個方法,在需求改變的將來可能會是個災難!
正交性
用正交性 (如果其中一個的變化不影響其他任何一個,則兩個或多個事物是正交的) 的概念是設計系統或撰寫程式碼。
可逆性 (若您只有唯一一個想法,那麼這個想法就是最危險的)
主要就是關鍵的決定是否可以被逆轉。隨著時間的推移,當初的決策可能需要做變更,可能是要換一個資料庫或換個套件,當我們有抽象化,隨時可以簡單做更換,當沒做抽象化替換可能就是個巨大工程了,像是 Rails 的 ActiveJob 就是一個抽象化的例子,因為有了抽象化,我們可以隨時替換成想要的 Job Queue adapters,總歸就是根本不會有所謂的最終決定,所有的事物都是會改變的,我們能做的就是保持靈活的架構,不用去管未來。
曳光彈開發 (tracer bullet development) 和原型 (prototype)
原型生成的程式碼是用完就丟的,而曳光彈程式碼簡單但完整,也是最終系統的一部分。
曳光彈開發我本來沒聽過,這邊我理解為在開發一個從未實作過的東西時,先找出一條路走看看,先讓使用者用看看,而不是一口氣做完所有的需求,先將核心做出,讓使用者回饋,然後再繼續,修改開發,先求有再求好的感覺。而原型更類似於一種用來學習的實驗,先試作看看,之後要做也不會是用一樣的程式碼。
領域語言 (一個人的語言界線就是他世界的界線)
緊靠問題所在的領域。
評估
評估可以免除驚嚇。
基本工具
在純文字中保存知識
善用命令 Shell 的力量
熟練編輯器
一定要使用版本控制
除錯
- 解決問題,而不是責備某人 (
我發現最近太容易自責了,需要改進 QQ) - 在修復程式之前先進行錯誤測試
- 撰寫測試程式的舉動可能帶來解決方案
- 請一定要讀那該死的錯誤訊息
- 跨版本回歸
- 二元切分
這裡可以分成程式碼面的切分,和資料面的切分,分成兩個部分,一步步的找出錯誤的地方。 - log / trace
- 黃色小鴨
- 不要假設,請去證明
每次在除錯的時候,我總是想著要找到錯誤的那個點,相信唯有看見錯誤真正的地方,才能有效的解決問題,看了書後更證明了我是對的 XD
務實的偏執
完美的軟體並不存在。務實的程式設計師則會更近一步,他們連自己也不相信,所以務實的程式設計師會為自己的錯誤建立防禦機制。
合約式設計 (Design by Contract,DBC)
什麼是正確的程式?就是一個不會比它聲稱的做得更多或更少的程式。
- 前置條件 (Precondition):當一個函式的前置條件被違反時,它就不應該被呼叫。傳遞正確的資料是呼叫者的責任。
- 後置條件 (Postcondition):函式保證要做的事;函式完成時的狀態。
- 類別不變量 (Class invariant):從呼叫者的角度來看,類別必須確保類別不變量條件始終成立。可以想成是函式語言說的狀態不變。
如果呼叫者滿足了函式的所有前置條件,則函式應在完成時保證所有後置條件和不變量都成立。如果任何一方未能履行合約條款,就會呼叫補救措施,這種補救措施可能是引發例外,或者終止程式。不管發生什麼事,不能履行合約都是一個錯誤。 - 如何平衡資源:由取得資源的人負責釋放資源。
彎曲或弄壞
這章節提供了幾個技巧,讓我們知道如何可以撰寫更可逆、更靈活的程式,讓我們在瘋狂奔向未來的過程中不要被海放在後面。我這邊截取幾個重點如下:
去耦合:單個元件應該與盡可能少的其他元件耦合。
- 直接命令,不要詢問。
- 不要串聯呼叫方法。
- 避免全域資料
- 如果非得當成全域資料使用,請確保將它用 API 包裝起來。
行走江湖 (的策略)
- 有限狀態機 (Finite State Machine)
- 觀察者模式 (Observer Pattern)
- 發佈 / 訂閱 (Publish/Subscribe)
- 回應式程式設計 (Reactive Programming) 和串流 (Stream)
轉換式程式設計
如果您不能把您正在做的事情描述成一個處理流程,那表示您不知道自己在做什麼。
繼承稅
您只想要一根香蕉,但是您得到的卻是一隻拿著香蕉的大猩猩和整個叢林。
並行
並行 (concurrency) 是執行兩個或多個程式碼片段時,就好像他們同時執行一樣。平行 (parallelism) 是它們真的同時執行。有興趣更了解這兩個差別的朋友可以看看 ByteByteGo 的影片。我們需要能讓並行發生,並去掉時間或順序中產生的耦合。
不要共用狀態
- 原子性更新
- semaphore:任何想要更新內容的人只有在持有該 semaphore 的情況下才能更新。
- 其他:有些語言本身內建並行支援,例如,Rust 強化了資料擁有權的概念;一次只能有一個變數或參數可以參照到任何特定可變資料。
參與者 (actor) 與程序
由 Erlang 這個程式語言奠定了基礎。Erlang 將參與者 (actor) 稱為程序 (process),它們透過發送訊息進行通訊,每一個程序與其他的程序隔離,所以沒有狀態共用。
這裡我的理解是我們要從設計面來避免共用狀態的可能性,只要不共用狀態,個體之間可以更加獨立,所以會設計出獨立又抽象的參與者,透過訊息的傳遞讓程式可以彼此溝通。
關於訊息傳遞想到 Object Oriented Programming is not what I thought - Talk by Anjana Vakil 這個以前看過的影片,有興趣的朋友也可以看看。
另外 Ruby 3 的 Ractor 就是 Ruby 的參與者模式。
當您寫程式時
- 外面的世界很殘酷,到處都是壞人,他們積極地試圖闖入您的系統。
- 我們應該避免依靠巧合撰寫程式,即仰賴運氣與得到意外的成功,而應該蓄意地設計程式。
- 不要假設,要證明。
- 找到一個恰好合適的答案和找到正確答案是不一樣的兩件事。
- 了解演算法速度,懂得最快不一定最好,且要避免過早優化。
- 重構的定義:重組現有程式碼主體、改變其內部結構而不改變其外部行為的嚴格技術。
- 請測試您的軟體,否則將由您的使用者進行測試。
- 分析程式碼,找出可能出錯的地方,並將這些錯誤添加到您的測試套件中。
- 您還需要考慮外部參與者是如何故意將系統搞砸的。(
這個論點在我加入現在的 DEVCORE 公司之前我也很少如此思考) - 請好好命名;在有需要時重新密名。
安全基本原則
務實的程式設計師會是健康的偏執狂。
- 最小化攻擊表面積。
包含:程式碼複雜性、輸入的資料、未經身份驗證的服務、經過身份驗證的服務 (淘汰不使用的、舊的或過時的使用者和服務)、輸出資料和除錯資訊都可能會招來攻擊。 - 最小權限原則。
- 安全預設值。
- 對敏感性資料進行加密。
- 維護安全更新。歷史上最大的資料洩漏都是因為系統更新滯後造成的。
密碼的建議:您想要鼓勵使用者使用較長、高度亂度的隨機密碼。那就要注意人為限制將會限制資訊亂度,並且助長糟糕的密碼使用習慣,讓您的使用者的帳戶很容易被破解。
專案啟動前
需求坑
沒有人確切地知道自己想要什麼,程式設計師幫助人們了解需求。菜鳥開發人員經常犯的錯誤,是把需求宣告當真,並實作。但其實最初期的需求可能是一種要我們進一步探索的邀請。需求是從回饋的循環中了解的。讓我們站在客戶的立場思考。
敏捷的本質
- 敏捷指的是關於對變化的回應,對您出發後遇到的未知做出回應。
- 好的設計使事情容易改變,如果它很容易改變,我們可以馬上修正,沒有任何猶豫。
如何處理不確定性?
- 找到自己目前的處境。
- 朝您想要的方向邁出最小最有意義的一步。
- 評估您現在的處境,並修復您所破壞的一切。
務實的專案
- 不容許破窗。
- 用有效的開發方法,不要用流行的開發方法。
- 不讓同樣的 bug 出現第二次。
心得
看這本書會有很踏實的感覺,因為作者不只講概念還會適當的提出案例分享,以上內容不是全部,歡迎各位想成為大師?的人也買書看看。