程式設計師修煉之道 閱讀筆記
本文是程式員修煉之道的閱讀筆記和自己的經歷以及思考
-
提供各種選擇,不要找蹩腳的藉口
如果你犯錯了,那麼勇敢的承認它,並且承擔後果,而不是找各式各樣的藉口或者撒謊.如果從一開始就判定 當前的做法可能會有問題,那麼應該提出來,並且拒絕為此承擔後果,當然,同時應當提供更多的,更好的選擇.
-
不要容忍破窗戶
"這程式碼太搓了,看都不想看到它", "算了,等有空的時候再來修一下吧" --- 錯. 一旦發現破窗戶,我們應該 立即修掉它,而不是讓他繼續留著.在日常的軟體開發中我們肯定有過類似的想法,但最後的實踐證明,幾乎不會 再去修.甚至 "TODO = never do",所以如果我們發現了破窗,或者是聞到了程式碼的壞味道,應當立即修掉他. 整個專案都是爛的,怎麼辦?重構或者跳槽.
-
要做變化的催化劑
-
記住大背景
每個人都會想,這破玩意兒都這麼破了,懶得改,我只要維護好我自己的那一部分就好了.但事實上,也許維護 自己那一部分程式碼的時候又會這麼想:反正大家都寫的那麼爛,我這裡也不用太講究.如此惡性迴圈下去,整個 專案就會垮掉.所以我們應當主動承擔起帶動變化的角色.
- 首先要堅決維護好自己(一個人)開發的專案 - 然後要在發現大專案中的壞味道的時候除掉他 - 至於大背景,則是首先你要確定你所做的對專案是真正有益的
-
使質量成為需求問題
程式碼不可能完美,日常的程式設計中,總是把質量權衡在某個度上,因為,優化是無止境的.當然,這並不意味著寫出 質量低下的程式碼是可以理解和原諒的(所以這個度其實很難把控).
-
定期為你的只是資產投資
程式設計師所學的知識其實同樣也有時間價值 --- 和金融資產一樣. --- 有的知識從出生到現在都沒有過時,例 如學習UNIX相關的知識,有的知識火一陣子就開始走下坡路.
- 定期投資 - 多元化投資 --- 不要把你所有的技術都放在一個籃子裡,首先從你所在專案使用到的技術瞭解起,例如 如果是web開發專案,你所需要知道的知識可能有:HTTP協議,HTML/CSS/JS,熟悉所使用的框架,RPC和JSON, 關係型資料庫和ORM,快取和CDN,負載均衡/單點故障,非同步任務,事務,資料庫擴充套件,測試/自動化測試等. 當你瞭解了這些之後,再去尋找更多的知識. - 管理風險 --- 像投資一樣,不能總是追求新興的東西,但是也不能太過於保守. - 低買高賣 --- 如果你看好一門新出的技術,那麼就應該立即學習它,就像在一隻你看好的股票剛出的 時候就買入 - 重新評估和平衡 --- 你需要定期的評估,目前所掌握的知識,有哪些需要重新整理一下自己的"快取",是不 是有哪些新的知識需要去了解一下
可以為自己設定一系列目標,例如:
- 每年至少學習一種新語言, 這點我做的還不夠好 --- 2015-2017上半年這段時間一直都在用Python, 2017年下半年開始才接觸Golang,之後會計劃的更好(當然,此前接觸的C/C++/Java等都忘了,所以不能算) - 每季度閱讀一本技術書籍, 這點我做的比較好,每天我都會看一點書,技術有關或無關,但每季度絕對 不止讀一本 - 也要讀非技術書籍,這點做的不夠好,2017年之前幾乎都是隻讀技術書籍,2017年之後才開始改變 - 上課,這點做的不夠好,我幾乎不去本地的大學上課,因為比較麻煩...不過我會看一些公開課 - 參加本地組織,這點我做的很不好,幾乎不去,主要是參加過幾次,覺得太水了,很無聊 - 試驗不同的環境,嗯,Windows和Linux我都用,不過,前者娛樂後者工作.IDE極少用. - 跟上潮流,這點我得說,目前沒有這樣的計劃,因為畢業的前幾年,給自己定的計劃是打造紮實的基礎 - 上網,我天天上...
-
批判的分析你讀到的和你聽到的
自然,所有人嘴裡說出來的都會加以粉飾,你看到的也未必就是事實.在高中的時候我明白了這個道理,所以 給自己的簽名一直都是"你的眼睛能看多遠".看一門技術也是如此,批判的看,看到優點,也要看到缺點,知道 什麼情況下是最佳使用場景,什麼時候不適合.
然而我必須承認,要做到非常準確的識別事實,很難 --- 要不然我就不會買錯一堆書了,目前get到的買書技能:
- 上評分網看看網民的評論,但是當心,可能是刷出來的,也可能你並沒有和他們處在同一個階段. - 問你身邊愛讀書,讀過很多書的人,求他們給予推薦
-
你說什麼和你怎麼說同樣重要
我一直認為程式設計師非常重要的三個能力:硬實力,溝通能力和抽象能力. 記住程式是為人服務的,你最終的溝通 物件是人 --- 產品經理或者客戶. 你要考慮你的聽眾是不是聽得懂,你可以跟程式設計師說術語,但是不要跟他們 說術語,不是所有人都知道一切的,你也不知道世界上的一切.其實道理很簡單,設身處地站在別人的角度上考慮 一下就好.
-
DRY原則 --- Don't Repeat Yourself.
不要到處複製貼上,要不然改起來你就知道了,我的個乖乖,會累死的.把重複的程式碼和邏輯抽象抽離出來,變成 工具函式(utils)或者類內方法,或者服務類(service),或者微服務等.總而言之,不要重複.
i += 1
-
讓複用變得容易
-
消除無關事物之間的影響
關於這兩點,我們聽到的最多的詞語大概是:高內聚,低耦合;針對介面程式設計等.微服務最近這麼火爆,我個人認為 歸功於它的特點 --- 強制解耦. 不再是到處都是錯綜複雜的import然後函式呼叫,每個子系統維護自己的小 領域就好.同時也就降低了自身的複雜性.
時刻想到,如果我們改了這裡,會有幾個地方受到影響?正交系統給出的答案應該是一個.
KISS原則也是和這個有關係的, Keep it simple, stupid.
-
不存在最終決策
-
用曳光彈找到目標
在現實程式設計過程中,我們總是要對需求作出一定範圍內的界定,以及,假設.假如不這麼做的話,需求根本無邊 無界,完成不了.但是,與之相悖的,我們的假設做的越多,那麼抽象程度就越低,可移植能力就越差.因此,對於 做假設這件事情,只能說我們要做到"謹慎且大膽".
但是對於一個從來沒有做過的大型的系統,應該快速出一個最小的可用的系統然後開始完善而不是無止境的 定好文件等.這樣我們能儘早得到反饋,同時也能讓客戶安心.這和快速出原型很類似,區別在於,如果我們說 快速出原型,那麼這個原型很可能會被我們丟棄.
-
為了學習而製作原型
製作原型,是為了快速體驗一下既定方案,從而從中體驗到這種方案的優缺點,利弊等.不過通常原型都很醜陋, 因為它只是原型而已.
-
靠近問題領域程式設計
DSL很強大,但是對使用它的使用者也會有要求.日常很少用到.
-
估算,以避免發生意外
-
通過程式碼對進度表進行迭代
估算,我們日常中很多時候都會遇到這種問題,比如你彙報給上級,這個任務你需要多久來完成. 我們進行估算, 然後,用現實結果來評判它, 並且吸取經驗, 在下一次估算的時候用上它, 那麼我們的估算將會越來越準確.
書中給了我們一種萬能回覆: "我等會兒回答你" :).
-
用純文字儲存知識
- 利用命令列的力量
-
用好一種編輯器
你懂的 :)
-
總是使用原始碼控制
吃過虧你就知道你需要這個
-
要修正bug,而不是發出指責
- 不要恐慌
- "select"沒有問題
-
不要假定,要證明
儘管我們會發出吐槽,但是我們會修復這個問題.
修bug要冷靜,理性的分析. 而不是胡亂猜測亂碰亂撞.
常見的除錯方式:
- 找辦法復現bug
- 首先應當懷疑自己寫的程式碼 --- 而不是編譯器,OS等
- 列印棧
- 列印日誌
- 單步跟蹤
- 向別人/小黃鴨講你的程式碼思路
-
學習一種文字文字操作語言
其實web開發就是文字操縱...
學習Python和Shell吧
-
編寫能編寫程式碼的程式碼
如果說通過編寫程式碼來生成程式碼,我一般都不太贊成,生成的程式碼通常意味著重複的,meaning-less的.我相信會有更好的辦法來解決. 但是如果是從一種程式碼轉換到另一種程式碼,我是支援的,例如我很喜歡的一個工具:pandoc. 我就用它把Markdown轉換成網頁或者是pdf.
-
你不可能寫出完美的軟體
so it is.
-
通過合約進行設計
-
早崩潰
編譯過程中的檢查其實就是這麼一回事兒,早點幫你檢查出來總歸比上線之後崩潰更好.
-
如果它不可能發生,用斷言確保它不會發生
注意前提,如果它不可能發生. 也就是說, 千萬千萬千萬不要用斷言替代錯誤處理!
-
將異常用於異常的問題
不要濫用異常
-
要有始有終
記住自己關閉開啟的檔案啦,釋放申請的記憶體啦... 這點來說,Golang的defer是個好東西, Python的with(這個context manager)也 是個好東西
-
使模組之間的耦合減至最少
- 要配置,不要整合
-
把抽象放進程式碼,細節放進元資料
使用配置檔案而不是寫死在程式碼裡,會讓軟體獲得更大的靈活性,比如SQL/">MySQL Server提供了各式各樣的引數,讓使用者得以控制Server的 表現和資源佔用等.
讓應用變成可配置的,就可以獲得最大的靈活性.
-
分析工作流,改善併發性
不要對流程發生的前後順序做太多假設,而應該看是否有地方可以併發.
-
用服務進行設計
-
總是為併發進行設計
總是要考慮,這一段程式碼是否執行緒安全?是否可重入?如果能滿足併發安全,那麼單執行緒執行也會很安全.
-
使檢視與模型分離
MVC在今天應當是大行其道,背後原因就在於,把檢視中的無關部分抽象出來,得以解耦和重用程式碼.
-
用黑板協調工作流
-
不要靠巧合程式設計
我對自己的要求一直都是,自己寫下的每一行程式碼,都需要知道它背後發生了什麼.你要知道自己在做什麼,軟體是怎麼跑起來的,而不是 碰巧跑起來了.
-
估算你的演算法的階
-
測試你的估算
if i in ("hello", "world", "this", "is", "a", "string")
和if i in set(["hello", "world", "this", "is", "a", "string"])
的效率有什麼區別?心中有估計之後,要去驗證這個估算是否是正確的,並且將驗證結果加入自己的反饋系統中.
-
早重構,常重構
等你發現專案已經大到改不動了...那時候重構就很麻煩了.
-
為測試而設計
-
測試你的軟體,否則你的使用者就得測試
這應當是和測試驅動開發類似的思想. 實際上測試是個好東西,只不過有時候寫測試確實挺煩的...但是,如果我們經常要作出改動, 那麼測試是一件非常好的事情,可以幫助我們省去重複的手工測試,可以幫助我們保證相容性等.
-
不要使用你不理解的嚮導程式碼
-
不要蒐集需求---挖掘它們
-
與使用者一同工作,這樣才能像使用者一樣思考
確實,真正的弄清楚需求非常重要,要不然遲早要被坑的.可以跟有信用的產品經理一一確定自己理解的需求是否完全對了,並且明確 告知對方不會有改動的機會 --- 你知道的,不能培養他們想改就改的習慣.
但是這裡也有一個陷阱,就是有些人喜歡把所有的細節都弄清楚,然後再開始動手.做不到的,不要過度陷入細節.
-
抽象比細節活得更長久
-
使用專案詞彙表
這樣就能讓跟多人更容易溝通吧,不過我沒有用過...
-
不要在盒子外面思考 --- 要找到盒子
面對棘手的問題時,列出所有的可能的途徑,然後逐一檢查列表中的每一項,然後想為什麼不能用某個特定的途徑,真的嗎?證明一下. 在思考難題的時候,更不能做過多的假設,現有假設也應該逐一檢查.
-
傾聽反覆出現的疑惑 --- 等你準備好再開始
-
有些事情,do it比describe it更好
-
不要做形式方法的奴隸
-
圍繞功能,而不是工作職務進行組織
我一直認為,不要拘泥於形式,而要理解真正的內涵.就像敏捷開發,並不要一步一步完全遵循步驟,而理解其真正內涵才是最重要的.
-
昂貴的工具不一定能製作出更好的設計
其實設計是否良好,還是取決與設計者的品味
-
不要使用手工流程
- 早測試,常測試,自動測試
- 要通過全部測試,編碼才算完成
- 通過"蓄意破壞"測試你的測試
-
測試覆蓋狀態,而不是程式碼覆蓋
自動化測試啊哥!千萬不要手動點點點...
- 單元測試
- 整合測試
- 邊界測試
- 驗證和校驗
- 效能測試
- 迴歸測試
- 可用性測試
- 資源耗盡,錯誤及恢復
- ...
-
一個bug只抓一次
找到一個bug,修復之後記得補上一些測試,這樣如果下次再出現,就可以在自動化測試中發現. 而不是修完之後就想,好了,修好了,下 次不會在出現了.
-
把英語當作另一種程式語言
-
把文件放在程式碼裡,而不是程式碼外
-
溫和的超出使用者的期望
-
在你的作品上簽名
實際上,版本控制工具已經幫你幹了這個事情了. 當然原作是指,可以通過增加自豪感而增加責任感.