程序員修煉之道-從小工到專家讀後感
前言:
- 書的內容是從開發經驗中總結出的一些軟件開發的指導原則。所有內容都是圍繞核心主題開展的。
- 書的核心主題是”Progmatic”即實效。實效的具體含義是->高效並且有效地完成任務,即速度要快,質量要高。
- 讓書中的內容落地就要內化原則,內化是指把書中的經驗原則融入自己的知識體系,在實際的開發中去應用這些指導原則。
如何落地執行:
- 本書含有一些經驗總結出的tip,如DRY(dont repeat yourself),如何執行這些tip:
- 頻繁的高強度的外部刺激和自主的有意識的反覆提醒是加速內化的兩個重要方法。如看到if分支就要看是否有else分支。
- 需要抽象出一些簡單的詞句和規則(如if,else分支查看),靠記憶和不斷地提醒,小規模地內化這些小聲音。
- 實踐:先大致理解和記住一些tip,然後每週實踐2到3個。實踐的方式包含1,2。
一些tips: 這些tips都是以實效爲核心
- 使用靠近問題的領域語言來書寫僞代碼。這樣有利於僞碼直接轉爲代碼實現。
- 不要預設立場。如檢查if,else分支是否覆蓋所有情況,如果沒有,需要說明。(預設立場非常普遍)
- 不要容忍破窗戶,破窗戶指存在問題的代碼和設計,即使小問題也要解決,防患於未然。如果無法解決,添加註釋信息,記錄問題。–>總之,要讓問題得到暴露和修復。(暴露問題,解決問題,不要隱藏問題,逃避問題)
- 不要過分地陷入到細節當中,要時刻記得項目的架構。(在項目實現過程中抓大放小)
- 批判性的分析你獨到的和聽到的。(即要有個人判斷優劣,對錯的能力)
- 把問題放到更大的語境中去考慮。(在需求分析中要抓大放小)
- 要負責:提供解決方案,而非尋找藉口(提高效率,以解決問題爲核心,這條比較反人性,在出問題時要記着這條tip)
- 接受變化。(在所有階段都需要考慮可能的變化,言下之意就是要做靈活的設計,可擴展的實現)
- 交流(和所有項目相關人員,目的是爲了達成一致,及時反饋,不斷調整)
- 當多種數據元素互相依賴時,要保證這種依賴關係。當保證這種依賴關係的開銷過大時,需要解除依賴關係,此時可以使影響局部化,不要把這種變化過多地暴露。
注重實效的途徑:
DRY原則:
- 即dont repeat yourself,含義是系統中的每一項知識都必須具有單一,無歧義,權威的表示。即要避免重複。
- 程序員需要持續不斷的維護,這是整個開發過程中的例行事務。DRY使開發更易於理解和維護。
- 重複的類型:
- 強加的重複,指環境因素導致的重複.解決需要智慧。
- 信息的多種表示(如不同平臺不同語言對同一信息的表示),這樣可能導致不一致,通過編寫簡單的過濾器或代碼生成器來解決,即從同一個源(信息的表示)來生成。
- 要把低級的知識放在代碼中,把註釋保留給其他的高級說明。即指分層設計,高層的邏輯儘量抽象以避免修改。這樣底層和高層解耦,也防止註釋過期。
- 無意的重複和無耐性的重複要被避免。
- 開發者之間的重複。
- 強加的重複,指環境因素導致的重複.解決需要智慧。
正交性:
- 含義就是解耦。用來表示某種不相互依賴性或者解耦性。
- 需要消除無關事務之間的影響。組合正交組件提高效率。不要依賴你無法控制的事務屬性。
- 建立正交的系統:
- 模塊化
- 層次化。
- AOP讓你在一個地方表達本來會分散在源碼各處的某種行爲。
- 限制模塊之間的交互。
- 遵守得墨忒耳法則縮小了調用類中的相應集的規模。
- 在編碼上:
- 讓代碼保持解耦
- 避免使用全局數據
- 避免編寫相似的函數
可撤銷性
- 含義是不存在最終決策,所以功能要可撤銷。即代碼可回滾。
- 使用版本控制系統。
- 採用靈活的架構。
- 設計正交的系統。
曳光彈和原型化
- 區別在於原型化更注重爲交互建立原型,最終會被丟棄。
- 而曳光彈更偏重對核心功能的實現,最終會成爲系統的一部分。
- 曳光彈的使用場景是當需求模糊,無法做出宏觀上完善的系統設計時。採用盲人摸象的方式進行開發,即先實現確定的地方.
估算:從已有的類似項目來進行估算比較靠譜
- 確定估算粒度。如天,周,月。
- 確定問題的範圍,即制定約束條件。
- 所有的估算都以問題的模型爲基礎。去問已經做過這件事的人
- 估算系統:建立系統模型->把模型分解爲組件->給每個參數指定值->計算答案->追蹤估算能力
基本工具:
- 構建自己的工具庫。
- 使用源碼控制。
- 調試bug:
- 找到問題根源
- 可以快速**復現**bug。
- 代碼跟蹤。
- 向別人解釋程序以找到問題所在。
- 找bug範圍:先自己代碼–>確定無誤再找類庫或系統問題。不要固執的認爲自己的代碼沒問題。
- 不要假設,要驗證。
注重實效的偏執:
- 放棄寫出完美軟件的偏執。
- 進行防禦性編程。
- 合約。規定代碼的權力和責任,即圈定範圍。
- 用文檔(其他形式:斷言,註解等)記載以下聲明,並進行校驗,是按合約設計(簡稱DBC)的核心所在。
- 前置條件
- 後置條件
- 類不變項
- 當代碼發現某種被認爲不可能的事情已經發生時,終止它。
- 斷言式編程:
- 斷言檢查的是絕不應該發生的事情。
- 斷言可能會有副作用,引入新的錯誤。
- 異常
- 異常表示即時的,非局部的控制轉移,是一種級聯的goto。
- 把異常當做處理邏輯。破壞了封裝,通過異常處理,例程和它們的調用者被更緊密的耦合在一起。
當你編碼時:
- 代碼需要演化,它不是靜態的事務。
- 重構
- 不要試圖在重構的同時增加功能。
- 在開始重構之前,確保你擁有良好的測試。
- 採用短小,深思熟慮的步驟。
- 從一開始就可以把可測試性構建進軟件中,並且在把各個部分連接在一起之前對每個部分進行徹底的測試。
在項目開始之前:
- 需求需要挖掘,而不僅僅是收集。找出用戶爲何要做特定事情的原因,而不是他們目前做這件事情的方式。
- 建立需求文檔:把形式化的模板做備忘錄
- 好的需求文檔會保持抽象
- 項目範圍的增大需要被記錄和可追溯,以及可評價(通過統計信息)
- 需求的收集和設計實現不是單向的線性關係,而是雙向關係。它們是“交付高質量的系統”的不同方面。
- 解開謎題
- 解開謎題的關鍵在於確定施加的各種約束,並確定你確實擁有的自由度
- 確定真正的約束
- 對約束進行分類,並劃定優先級
- 你所需要的知識真正的約束,令人誤解的約束,還有區分它們的智慧。
- 編寫程序規範
- 編寫程序規範是一個交流活動,旨在解釋並闡明系統的需求
- 不要追求捕捉系統或需求的每一處細節和細微差別,因爲細節不一定可以被自然語言以可理解的方式定義。
- 不要陷入對規範的追求中,在合適的時候編碼,反哺規範。
- 不要做方法的奴隸,適合的就是最好的,能解決問題就行。
注重實效的項目的標準:
- 不符合用戶期望的項目註定是失敗的。即以用戶爲中心。
- 使項目級活動保持一致和可靠的一個最重要的因素是使你的各種工作流程自動化。
- 項目的各種活動,分析,設計,編碼,測試不會孤立地發生,它們是看待同一問題的不同方式。
- 在開發一個項目時,我們再尋求內聚的,在很大程度上自足的團隊。使用組織代碼使用的技術,像合約,解耦,正交性,這樣的技術來組織各種資源,有助於使團隊作爲整體與變化的各種效應隔離開來。
- 測試:
- 早測試,常測試,自動測試。
- 要通過全部的測試,編碼纔算完成。
- 集成測試說明組成項目的主要子系統能工作,並且能很好的協同。
- 測試狀態覆蓋,而不是代碼覆蓋。
- 大多數測試都應該自動完成。
- 註釋:註釋應該討論爲何要做某事,它的目的。代碼已經說明了它是怎樣完成的。
我自己的一些tips:
- 以實用爲主,快速學習。而不是拿到一個東西就系統性的去學習。
- 當然,深度鑽研還是需要的,但是後邊再說,儘快上手工作是第一位的。
- 交流溝通很重要,不懂就問,不能閉門造車。
- 在Microservices時代,我們更建議外部化你的軟件產品差異化配置管理,儘量減少Profile的濫用甚至不用。
- 可以多看官方文檔。
- 想清楚再去敲代碼,這句話可以用一輩子,
- 備份,版本管理很重要。
- 有想法,有問題要寫下來,不能止步於口頭和心裏。
- 公司的各種設計指南、編程規範、XXX規範要仔細學習
- 公共配置項不要亂動,特別是配置庫和編譯器的
- 編碼的時候只思考同一個思維層次的邏輯,在這層完成之後再思考下一層。
- 計算機科學中的問題都可以通過改變使用方式來解決。
- 針對數據庫相關的操作一定要考慮到在大數據量下的性能問題。
- 通過加點記錄程序段運行時間的方式判斷性能瓶頸所在。
- 修復一個Bug往往會引入一個更爲隱祕的Bug,所以在進行Bug修復時需要對修復後的程序邏輯重新進行檢查,避免引入Bug。
- 在針對解決問題的態度方面,不要輕易得出”問題無法解決”這樣的結論,需要有”問題總是可以解決的”的態度和信念。
- 在代碼風格方面,需要更加規範和一致。
- 編寫關於數據庫操作的代碼時。一定要考慮到索引的問題,sql的性能的問題。
- 代碼中如果需要生成大量對象,一定要考慮到內存佔用的問題。
- 在對工具的學習中,如git中,充斥着大量的命令和用法,很難一下子熟練掌握。所以對於這種工具的學習,我覺得
首先熟悉高頻命令+學習其工作原理的方式可以起到較好地作用。對應於git就是着重理解其工作區,暫存區,分支和時
間線的概念。