程式設計師修煉之道(通俗版) 第四章

2021-08-13 22:35:20 字數 2555 閱讀 9156

《程式設計師修煉之道》這本書中的內容挺不錯,裡面包含了很多精華,但一些句子很拗口,所以我就根據國人的閱讀習慣,在不改變原意的情況下對詞句稍加修改,標題中的「通俗版」就是這麼來的。

1、繼承和多型是物件導向語言的基石,是合約可以真正閃耀的領域。說到這裡,你或許會想到黎克特制替換原則:子類必須要能通過基類的介面使用,而使用者無須知道其區別。

換句話說,你想要確保你建立的新子型別是基類的「一種」——它支援同樣的方法,這些方法有同樣的含義。我們可以通過合約做到這一點,要讓合約自動應用於將來的每個子類,我們只須在基類中規定合約一次。子類可以(可選地)接受範圍更廣的輸入,或是做出更強的保證,但它所接受的和所保證的至少與其父類一樣多。

2、我們曾經編寫過乙個借記卡交易交換系統。乙個主要的需求是借記卡使用者的同一筆交易不能被記錄兩次。換句話說,不管發生何種方式的失敗,結果都應該是:不處理交易,而不是重複地處理交易。

這個簡單的法則,直接由需求驅動,被證明非常有助於處理複雜的錯誤恢復情況,並且可以在許多領域中指導詳細的設計和實現。

一定不要把固定的需求、不可違反的法則與那些僅僅是政策的東西混為一談,後者可能會隨著新的管理制度的出台而改變。這就是我們為什麼要用術語「語義不變項」的原因——它必須是事物的確切含義和中心,而不受反覆無常的政策的支配。

3、每個程式設計師似乎都必須在其職業生涯的早期記住一段曼特羅(mantra)。它是計算機技術的基本原則,是我們學著應用於需求、設計、**、注釋——即我們所做的每一件事——的核心信仰。那就是:這決不會發生……

「這些**不會被用上30年,所以用兩位數字表示日期沒問題」「這個應用決不會在國外使用,那麼為什麼要使其國際化?」「count不可能為負數」「這個printf不可能失敗」

我們不要這樣自我欺騙,特別是在編碼時。

4、關於斷言,有一種常見的誤解:

斷言給**增加了一些開銷,因為它們檢查的是決不應該發生的事情,所以只會由**中的bug觸發。一旦**經過了測試並發布出去,它們就不必存在,應該被關閉,以使**執行得更快。斷言是一種除錯設施。

這裡有兩個明顯錯誤的假定。首先,他們假定測試能找到所有的bug。現實情況是,對於任何複雜的程式,你甚至不知道有多少種可能的情況。其次,樂觀主義者忘記了你的程式執行在乙個危險的世界上。在測試過程中,老鼠可能不會啃咬通訊電纜、某個玩遊戲的人不會耗盡記憶體、日誌檔案不會塞滿硬碟,但這些事情可能會在實際工作環境中發生。你的第一條防線是檢查任何可能的錯誤,第二條防線是使用斷言設法檢測你疏漏的錯誤。

在把程式交付使用時關閉斷言就像是因為你曾經成功過,就不用保護網去走鋼絲。那樣做有極大的價值,卻沒有人身保險。

也許你的應用的關鍵部分對效能有很高的要求,增加檢查意味著又一次通過資料,這不太能讓人接受。讓那個檢查成為可設定的,但讓其餘的留下來。

5、分配某項資源的例程或物件應該負責解除該資源的配置,讓我們通過乙個糟糕 的**例子來看一看該提示的應用方式,這是乙個開啟檔案、從中讀取消費者資訊、更新某個字段然後寫回結果的應用。我們除去了其中的錯誤處理**,以讓例子更清晰:

void readcustomer(const

char *fname, customer *crec)

void writecustomer(customer *crec)

void updatecustomer(const

char *fname, double newbalance)

乍看上去,例程updatecustomer相當好。它似乎實現了我們所需的邏輯——讀取記錄、更新餘額、寫回記錄。但是,這樣的整潔掩蓋了乙個重大的問題:readcustomer和writecustomer緊密地耦合在一起,因為它們共享全域性變數cfile,這個全域性變數甚至沒有出現在updatecustomer例程中。

這為什麼不好?讓我們考慮一下,程式設計師被告知規範發生了變化——餘額只應在新的值不為負時更新,他進入原始碼,改動updatecustomer:

void updatecustomer(const

char *fname, double newbalance)

}

在測試時似乎一切都好,但當**投入實際工作,若干小時後它就崩潰了,抱怨說開啟的檔案太多了。因為writecustomer在有些情況下不會被呼叫,檔案也就不會被關閉。

這個問題的乙個非常糟糕的解決方案是在updatecustomer中對該特殊情況進行處理:

void updatecustomer(const

char *fname, double newbalance)

else

}

void readcustomer(file *cfile, customer *crec)

void writecustomer(file *cfile, customer *crec)

void updatecustomer(const

char *fname, double newbalance)

fclose(cfile);

}

現在updatecustomer例程承擔了關於該檔案的所有責任,它開啟檔案並在退出前關閉它。例程配平了對檔案的使用:開啟和關閉在同乙個地方,而且顯然每一次開啟都有對應的關閉。重構還移除了醜陋的全域性變數。

《道德經》程式設計師版第四章

道衝而用之或不盈。淵兮,似萬物之宗。挫其銳,解其紛,和其光,同其塵。湛兮,似或存。吾不知誰之子,象帝之先。程式的執行過程雖然是虛的。程式設計師秉承這個思路開發出各種程式,並且永遠不會感到滿足。程式的執行過程就像黑洞,它是各種程式的 新手程式設計師會有種銳氣,看到漂亮的效果,神奇的功能,就想直接cop...

《學習之道》第四章能力錯覺

大多數學生不斷重複閱讀筆記或課本,卻很少有人在學習時進行自我測驗或做提取練習。當書本 或谷歌 擺在眼前時,大腦會產生錯覺,以為學習材料也同樣存入了大腦,可這只是小和尚念經。看書畢竟比回想簡單多了,學生因此執迷於自己的錯覺,堅持低效率的學習方式。如出一轍的是,學生也常誤以為重新讀一遍面前的教材就能學會...

程式設計師修煉之道閱讀筆記(四)

最真實的就是程式了,對就是對,錯就是錯,不會因為任何原因而改變。文章一直在提做乙個注重成效的程式設計師,注重成效的程式設計師會告訴自己,乙個錯誤的發生,就說明已經發生了很糟糕很糟糕的事情。每個程式設計師在編寫 時都會告訴自己一些不可能發生的事,因此在書寫時就把這些問題簡單化了,去不曾想在這些被忽略的...