![]() |
VOOZH | about |
花了幾天時間略讀完了《程式設計師修煉之道——從小工到專家》(The Pragmatic Programmer: From Journeyman to Master)。總體感覺就像是一位多年開發經驗的軟體工程師,在身旁諄諄教導。其中的大部分內容,要在工作中不斷實踐,才能有深刻的體會。也許是自身層次原因,其中一部分內容不是很能理解,也許在多年之後,第二次讀這本書的時候,會有更加深刻的認識和理解吧。
下面是關於知識點的總結:
如果你不在乎能否漂亮地開發出軟體,你又為何要耗費生命去開發軟體呢?
PS:態度很重要,如果並不喜歡軟體開發,花時間去開發軟體,無異於浪費生命。
關閉自動駕駛儀,接管操作。不斷地批評和評估你的工作。
PS:自己每次所寫出來的代碼,自己是否能夠理解,是否去記錄那些當時沒能理解的代碼,現在再去看那些代碼,能否理解。
要提供各種選擇,而不是找藉口。不要說事情做不到,說明能夠做什麼。
PS:寫好的代碼要記得備份,不要為自己做不到某件事情找藉口,想想現如今自己能夠為這件事做些什麼。
當你看到糟糕的設計、錯誤的決策和糟糕的代碼時,修正它們。
PS:有什麼問題必須立即解決,不要拖,拖到後面,小問題也會變成大問題的。
你不能強迫人們改變。相反,要向他們展示未來可能會怎樣,並幫助他們參與對未來的創造。
PS:當某件事情懸而不定時,可以通過對事情的理解,做出相應的原始模型(原型),引誘團隊裡的其他成員,對你這個原型進行擴展。
不要太過專注於細節,以致於忘了查看你周圍正在發生什麼。
PS:先整體在細節,先抽象再具體並且隨時觀察外界的變化。
讓你的用戶參與確定項目真正的質量需求。
PS:有時候並不需要做到最完美,如果做到最完美要用戶等幾年,那用戶寧願用那些幾個月就能做出,並在不斷改進的毛邊產品。
讓學習成為習慣。
PS:時代進步,IT業也呈現爆發式發展,也許今年用的技術,三五年以後就會被淘汰,這時候就需要做到及時充電,更新知識庫存。
不要被供應商、媒體炒作、或教條左右。要依照你自己的看法和你的項目的情況去對信息今進行分析。
PS:不要完全相信別人的說法,即使是專家說的也不一定完全正確,通過結合自己的思想,參考別人的意見,做出當前情況下儘可能最好的判斷。
如果你不能有效地向他人傳達你的了不起的想法,這些想法就毫無用處。
PS:不僅要成為技術上的專家,還要成為社交上的能手。
系統中的每一項知識都必須具有單一、無歧義、權威的表示。
PS:大量的重複不僅會浪費空間,也會造成效率低下問題。
如果復用很容易,人們就會去復用。創造一個支持復用的環境。
PS:代碼的復用,無疑會讓我們效率更高,但是為了復用,花大量的時間在琢磨怎麼去復用上面就得不償失了。所以,儘量在初次開發時,就考慮代碼的復用問題。
設計自足、獨立。並具有單一、良好定義的目的的組件。
PS:如果有n個文件,在最壞的情況下,修改一個文件的原始碼,同時也要修改其餘n-1個文件的原始碼。
沒有決策是澆灌在石頭上的。相反,要把每項決策都視為是寫在沙灘上的,並為變化做好計劃。
PS:考慮到隨時變化的環境,要在寫代碼之前就考慮清楚,這些代碼能不能在決策發生變化後還能使用。或者是花費很小的代價就能適應於變化。
曳光彈能通過試驗各種事物並檢查它們離目標有多遠來讓你追蹤目標。
PS:曳光彈法表示的是建立一個可用但是功能不全的版本來判別所做設計是否符合客戶需要,和原型這種用完即扔的方法不同,曳光彈法的代碼都是後期擴展所必需的。
原型製作是一種學習經驗。其價值並不在於所產生的代碼,而在於所學到的經驗教訓。
PS:原型也是探索新事物的一種方法,通過建立原型,可以快速的了解當前事物的各種特性,雖然原型的代碼用完即扔,但是所用的思想是需要保存的。
用你的用戶的語言進行設計和編碼。
PS:設計不同領域的軟體時,可能有其領域的規範和業務邏輯,通過熟悉該領域,能寫出更符合業務邏輯的代碼。
在著手之前先進行估算。你將提前發現潛在的問題。
PS:估算不僅僅是對預算的估量,也包括了做軟體各個方面的考慮,比如:時間,質量,範圍,干係人之類的等等。
用你在進行實現時獲得的經驗提煉項目的時間標度。
PS:進度往往是由代碼的完成度來進行決定的,代碼完成度高,則進度離完成不遠了,相反,如果某一時段內,代碼的平均完成率低於預計水平,那麼,實際進度可能就會慢於計劃進度了。
純文本不會過時。它能夠幫助你有效利用你的工作,並簡化調試和測試。
PS:純文本是有一定意義的文字,當我們將知識保存至純文本文件中時,並通過一定的形式進行組織,這樣它就永遠有意義的保存下來了,如果以後需要,就能直接派上用場。
當圖形用戶界面無能為力時使用shell。
PS:shell,dos這種命令行的威力是巨大的,也許圖形界面需要很多步驟才能實現的功能,通過命令行短短一兩行代碼就能實現。
編輯器應該是你的手的延伸;確保你的編輯器是可配置、可擴展和可編程的。
PS:基本上所有的計算機語言都是能夠用文本編輯器來進行編寫代碼的。雖然現在開發都是用IDE,但是IDE會自動給你做很多細節的事,這很好,但是請不要忘記了,如果你初學一門語言就用IDE的話,會丟失很多該語言的細節信息。同時,要學會一種編輯器的各種使用方法,常用的編輯器有EditPlus、Sublime Text等等。
源碼控制是你的工作的時間機器——你能夠回到過去。
PS:學會使用版本控制軟體(過段時間了解下)。
bug是你的過錯還是別人的過錯,並不是真的很有關係——它仍然是你的問題,它仍然需要修正。
PS:當有bug需要修復時,不要總想著去指責別人,或者是怎麼去逃避指責,這都不重要,重要的是什麼時候能將這個bug修復。
做一次深呼吸,思考什麼可能是bug的原因。
PS:尋找bug一直是一件很頭疼的事,也許我們因為時間問題,急於修復bug,但是不要恐慌,不要陷入混亂,這樣只會使你的效率更低,如果陷入混亂,請站起來去外面走一圈,放鬆下再來,也許就能尋覓見遲遲不出現的bug。
在OS或編譯器、甚或是第三方產品或庫中很少發現bug。bug很可能在應用中。
PS:不要想當然的以為自己的代碼沒有問題,不可能出現問題。問題往往就出現在你的代碼中,要永遠對自己的代碼持懷疑態度。
在實際環境中——使用真正的數據和邊界條件——證明你的假設。
PS:不要理所當然的認為自己所有的假設都是正確的,如果想要證明自己的假設,可以去測試它。
你用每天的很大一部分時間處理文本,為什麼不讓計算機替你完成部分工作呢?
PS:不是很能理解文本操縱語言的定義。
代碼生成器能提高你的生產率,並有助於避免重複。
PS:那些範式的代碼就可以通過代碼生成器來生成。
軟體不可能完美。保護你的代碼和用戶,使它(他)們免於能夠預見的錯誤。
PS:軟體不可能完美,真是因為不可能完美,才需要在編程時,多加小心,預防出錯。正如書中講到的,注重實效的的程式設計師連自己的代碼都不相信。
使用合約建立文檔,並檢查代碼所做的事情正好是它聲明要做的。
PS:在java中,合約規定類,接口及其所實現的功能。(並不是很能理解)
死程序造成的危害通常比有問題的程序要小得多。
PS:通過讓程序儘早的崩潰(找出bug),所付出的代價會少很多。
斷言驗證你的各種假定。在一個不確定的世界裡,用斷言保護你的代碼。
PS:現在並沒有用過斷言,等以後用了再說(據說現在Java用的比較多的是JUnit)。
異常可能會遭受經典的義大利麵式代碼的所有可讀性和可維護性問題的折磨。將異常保留給異常是事物。
PS:通過異常處理,可以省略大塊的if -else if - else 的判斷,當出現異常事件時,就可以用異常處理來進行捕獲並處理。java中,不要以為在異常處理catch塊中簡簡單單的寫個e.printStackTrace;就行了,用戶並不會看到,也不見得看得懂這個消息,我們能做的就是儘量處理這個異常,使之回到正常流程中。
只要可能,分配某資源的例程或對象也應該負責解除其分配。
PS:學會配平資源,也就是說獲取資源的時候想到怎麼去釋放它。很多時候可以在代碼內部結尾處加上釋放資源的代碼,但是這樣的一個壞處就是,如果調用者想保持該資源的占用是做不到的。由此出現了一種是誰調用,誰就負責關閉的機制。當然,還有其他機制,比如說Java中的垃圾回收機制,就是通過在堆棧中的資源塊加上一個使用者個數的屬性,當使用者個數為0時,就自動釋放資源。
通過編寫「羞澀的」代碼並應用德墨忒耳法則來避免耦合。
PS:德墨忒耳法則是一種軟體設計的方法,限制某個對象的方法的調用來避免耦合。具體為:使用自身,使用傳入參數,使用所創建對象,使用組件對象。
class Demeter { public: void example(B &b); private: A *a; int func{} } void Demeter::example(B &b) { C c; int f = func; <1. 它自身 b.invert; <2. 傳入該方法的任何參數 a = new A; a->setActive; <3. 它創建的任何對象 c.print; <4. 任何直接持有的組件對象 }得墨忒耳法則縮小了調用類中的響應集的規模,結果以這種方式設計的類的錯誤也往往更少。
要將應用的各種技術選擇實現為配置選項,而不是通過集成或工程方法實現。
PS:使用配置往往比集成的擴展性更好(並不是很能理解)。
為一般情況編程,將細節放在被編譯的代碼庫之外。
PS:元數據被定義為:描述數據的數據,對數據及信息資源的描述性信息。
利用你的用戶的工作流中的並發性。
PS:在同一時刻,某些事情是可以同時發生的,譬如流水線技術。可以去調查用戶的工作的步驟(工作流),來設計同步並行的處理方法,以此來提高效率。
根據服務——獨立的、在良好定義、一致的接口之後的並發對象——進行設計。
PS:並不能理解。
容許並發,你將會設計出更整潔、具有更少假定的接口。
PS:控制並發是一件很頭疼的事,如果寫代碼之前就考慮好了並發這一特性,那麼就會迫使你去考慮很多你本來不會考慮的問題,這樣寫出的代碼bug會少很多。
要根據模型和視圖設計你的應用,從而以低廉的代碼獲取靈活性。
PS:MVC的設計模式就是一種很好的設計模式,通過將視圖、業務邏輯和資料庫訪問進行分層隔離,這樣無論是改變哪一層的代碼都不會影響其它層的代碼。
用黑板協調完全不同的事實和因素,同時又使各參與方保持獨立和隔離。
PS:黑板只是一個比喻,黑板象徵著那種能夠自由發表言論的地方。通過黑板這一介質,能將很多零散的東西組合成我們所需要的東西。
只依靠可靠的事物。注意偶發的複雜性,不要把幸運的巧合與有目的的計劃混為一談。
PS:正如前面所說的,不要相信你的代碼,既然如此,為什麼僅憑自己巧合通過的測試,就能證明,代碼沒問題了呢?
在你編寫代碼之前,先大致估算事情需要多長時間。
PS:算法的階大致分為:
c < log2N < n < n * Log2N < n^2 < n^3 < 2^n < 3^n < n!
一般來說會用大O法(O(n)),來表示該算法的數量級,再通過分析,得出相應的時間複雜度T(n)和空間複雜度S(n)。
對算法的數學分析並不會告訴你每一件事情。在你的代碼的目標環境中測試它的速度。
PS:根據硬體環境,軟體環境的不同,相同的算法,其速度也有差異。
就和你會在花園裡除草、並重新布置一樣,在需要時對代碼進行重寫、重做和重寫架構。要剷除問題的根源。
PS:重構雖然可能耽誤一點時間,但是比起與不重構的花費來比,完全可以忽略不計。
在你還沒有編寫代碼時就開始思考測試的問題。
PS:就像硬體開始設計時,就考慮到了測試的問題一樣,軟體也應該考慮測試問題。
無情地測試。不要讓你的用戶為你查找bug。
PS:如果軟體做到要實際用戶去測試bug,這樣的軟體任何一個用戶都不想在使用第二次。如果想要節省花費,可以通過測試版本推送給同意參加測試的用戶。
嚮導可以生成大量代碼。在你把他們合併進你的項目之前,確保你理解全部這些代碼。
PS:通過IDE能夠生成一大堆嚮導代碼,但是這些代碼會加入你的項目,成為你項目的組成部分。不想要後期修改的時候頭疼,儘早弄懂這些代碼。
需求很少存於表面上。它們深深地埋藏在層層假定、誤解被政治手段的下面。
PS:這也是為什麼需求分析那麼難的原因了。
要了解系統實際上將如何被使用,這是最好的辦法。
PS:了解業務邏輯了,寫起代碼來才會得心應手。
「投資」於抽象,而不是實現。抽象能在來自不同的實現和新技術的變化的「攻擊」之下存活下去。
PS:抽象的事物,其所涵蓋的範圍相對於具體的事物更廣,所能夠表達的信息也就越多。
創建並維護項目中使用的專用術語和詞彙的單一信息源。
PS:不同的人在對同一件事物的表達上可能不同,這樣的話,通過統一的規範會取得更好的效果。
在遇到不可能解決的問題時,要確定真正的約束。問問你自己:「它必須以這種方式完成嗎?它真的必須完成嗎?」
PS:找到問題的關鍵所在。(不是很能理解)
你的一生都在積累經驗。不要忽視反覆出現的疑慮。
PS:無法理解。
不要掉進規範的螺旋——在某個時刻,你需要開始編碼。
PS:一大堆規範文檔看得頭疼欲裂,為什麼不自己收集需求,理解業務邏輯,然後開始編碼呢?在編碼後,再仔細審閱文檔(不是很能理解)
如果你沒有把某項技術放進你的開發實踐和能力的語境中,不要盲目地採用它。
PS:掌握一種描述方法比了解十門描述方法更好。
小心供應商的炒作,行業教條、以及價格標籤的誘惑。要根據工具的價值判斷它們。
PS:就像Oracle在低性能的伺服器表現力不一定有MySQL好一樣,找到最適合的更重要。
不要把設計師與編碼員分開,也不要把測試員與數據建模員分開。按照你構建代碼的方式構建團隊。
PS:無法理解。
shell腳本或批文件會一次次地以同一順序執行同樣的指令。
PS:正如資料庫的備份一樣,如果設置好時間進行自動備份的話,就不需要人來手工備份了,而且這樣出錯的機率也低很多。
與呆在書架上的測試計劃相比,每次構建時運行的測試要有效的多。
PS:就像你很難發現三個月前寫得代碼的bug一樣,儘早、常常測試將幫助你更早發現它,儘可能的寫一些自動測試的腳本,來節省你花在測試上的時間。
就是這樣。
PS:沒通過全部測試,怎麼可能是複合要求的代碼。
在單獨的軟體副本上故意引入bug,以檢驗測試能夠抓住它們。
PS:就像前面所說的一樣,沒有完美的代碼,那麼測試代碼也有可能出錯,這時候就可以引入一些既定的bug來測試,測試代碼。
確定並測試重要的程序狀態。只是測試代碼行是不夠的。
PS:單元測試的方法有很多種,條件覆蓋,路徑覆蓋,基本路徑覆蓋等等,但是很明確的一點就是,這些測試都是通過關鍵代碼的狀態來進行組合的。
一旦測試員找到一個bug,這應該是測試員最後一次找到它。此後自動測試應該對齊進行檢查。
PS:找到bug就要想方設法修復,並且實現該bug的自動檢查(不是很能理解)。
像你編寫代碼一樣編寫文檔:遵守DRY原則、使用元數據、MVC、自動生成,等等。
PS:無法理解。
與代碼分離的文檔不太可能被修正和更新。
PS:寫注釋就是為了在讀原始碼的時候方面,如果將注釋和原始碼分開,可能讀取來就很麻煩了。不過注釋的原則是要有意義,要注釋類,方法的功能,成員變量的用途,方法參數列表的意義等等。
要理解你的用戶的期望,然後給他們的東西要多那麼一點。
PS:如果能在完成用戶所預想的東西的基礎上加上一些便捷性的功能,無疑是錦上添花,這就能打下良好的聲譽。
過去時代的手藝人為能在他們的作品上簽名而自豪。你也應該如此。
PS:署名是一種良好的習慣,證明你願意為你寫的代碼負責,由此你就會更細心的寫出更好的代碼。通過你的不斷努力,代碼寫得非常好,那麼別人看到你的署名就知道這代碼質量很好。而不願意花心思在這上面的程式設計師恰恰相反,不願意署名,也不敢署名。
1、要學習的語言
厭倦了C、C++和JAVA?試試CLOS、Dylan、Eiffel、Object-C、Prolog、Smalltalk或TOM。它們每一種都有不同的能力和不同的「風味」。用其中的一種或多種語言在家裡開發一個小項目。
2、WISDOM離合詩
What do you want them to learn? 你想讓他們學到什麼?
What is their interest in what you』ve got to say? 他們對你講的什麼感興趣?
How sophisticated are they? 他們有多富有的經驗?
How much detail do they want? 他們想要多少細節?
Whom do you want to own the information? 你想要讓誰擁有這些信息?
How can you motivate them to listen to you? 你如何促使他們聽你說話?
3、怎樣維持正交性
4、應製作原型的事物
5、架構問題
6、調試檢查清單
7、函數的德墨忒耳法則
某個對象的方法應該只調用屬於以下情形的方法:
8、怎樣深思熟慮地編程
9、何時進行重構
10、劈開戈爾迪斯結
在解決不可能解決的問題時,問問你自己:
11、測試各個方面
參考《程式設計師修煉之道——從小工到專家》