• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>

            牽著老婆滿街逛

            嚴(yán)以律己,寬以待人. 三思而后行.
            GMail/GTalk: yanglinbo#google.com;
            MSN/Email: tx7do#yahoo.com.cn;
            QQ: 3 0 3 3 9 6 9 2 0 .

            摘自《代碼閱讀方法與實踐》

            摘自《代碼閱讀方法與實踐》

             

            第一章:導(dǎo)論

            1. 要養(yǎng)成一個習(xí)慣,經(jīng)常花時間閱讀別人編寫的高品質(zhì)代碼。
            2. 要有選擇地閱讀代碼,同時,還要有自己的目標(biāo)。您是想學(xué)習(xí)新的模式、編碼風(fēng)格、還是滿足某些需求的方法?
            3. 要注意并重視代碼中特殊的非功能性需求,這些需求也許會導(dǎo)致特定的實現(xiàn)風(fēng)格。
            4. 在現(xiàn)有的代碼上工作時,請與作者或維護(hù)人員進(jìn)行必須的協(xié)調(diào),以避免重復(fù)勞動或因此而產(chǎn)生厭惡情緒。
            5. 請將從開放源碼軟件中得到的益處看作是一項貸款,盡可能地尋找各種方式來回報開放源碼社團(tuán)。
            6. 多數(shù)情況下,如果您想要了解別人會如何完成這個功能呢?,除了閱讀代碼以外,沒有更好的方法。
            7. 在尋找 BUG時,請從問題的表現(xiàn)形式到問題的根源來分析代碼。不要沿著不相關(guān)的路徑(誤入岐途)
            8. 我們要充分利用調(diào)度器,編譯器給出的警告或輸出的符號代碼,系統(tǒng)調(diào)用跟蹤器,數(shù)據(jù)庫結(jié)構(gòu)化查詢語言的日志機(jī)制、包轉(zhuǎn)儲工具和Windows的消息偵查程序,定出BUG的位置。
            9. 對于那些大型且組織良好的系統(tǒng),您只需要最低限度地了解它的全部功能,就能夠?qū)λ龀鲂薷摹?span lang=EN-US>
            10. 當(dāng)向系統(tǒng)中增加新功能時,首先的任務(wù)就是找到實現(xiàn)類似特性的代碼,將它作為待實現(xiàn)功能的模板。
            11. 從特性的功能描述到代碼的實現(xiàn),可以按照字符串消息,或使用關(guān)鍵詞來搜索代碼。
            12. 在移植代碼或修改接口時, 您可以通過編譯器直接定位出問題涉及的范圍,從而減少代碼閱讀的工作量。
            13. 進(jìn)行重構(gòu)時,您從一個能夠正常工作的系統(tǒng)開始做起,希望確保結(jié)束時系統(tǒng)能夠正常工作。一套恰當(dāng)?shù)臏y試用例可以幫助您滿足此項約束。
            14. 閱讀代碼尋找重構(gòu)機(jī)會時,先從系統(tǒng)的構(gòu)架開始,然后逐步細(xì)化,能夠獲得最大的效益。
            15. 代碼的可重用性是一個誘人的,但難以掌握的思想;降低期望就不會感到失望。
            16. 如果您希望重要的代碼十分棘手,難以理解與分離,可以試著尋找粒度更大一些的包,甚至其他代碼。
            17. 在復(fù)查軟件系統(tǒng)時,要注意,系統(tǒng)是由很多部分組成的,不僅僅只是執(zhí)行語句。還要注意分析以下內(nèi)容:文件和目錄結(jié)構(gòu)、生成和配置過程、用戶界面和系統(tǒng)的文檔。
            18. 可以將軟件復(fù)查作為一個學(xué)習(xí)、講授、援之以手和接受幫助的機(jī)會。

            第二章:基本編程元素

            1. 第一次分析一個程序時,main是一個好的起始點。
            2. 層疊if-else if-... -else 序列可以看作是由互斥選擇項組成的選擇結(jié)構(gòu)。
            3. 有時,要想了解程序在某一方面的功能,運行它可能比閱讀源代碼更為恰當(dāng)。
            4. 在分析重要的程序時,最好首先識別出重要的組成部分。
            5. 了解局部的命名約定,利用它們來猜測變量和函數(shù)的功能用途。
            6. 當(dāng)基于猜測修改代碼時,您應(yīng)該設(shè)計能夠驗證最初假設(shè)的過程。這個過程可能包括用編譯器進(jìn)行檢查、引入斷言、或者執(zhí)行適當(dāng)?shù)臏y試用例。
            7. 理解了代碼 的某一部分,可能幫助您理解余下的代碼。
            8. 解決困難的代碼要從容易的部分入手。
            9. 要養(yǎng)成遇到庫元素就去閱讀相關(guān)文檔的習(xí)慣;這將會增強(qiáng)您閱讀和編寫代碼的能力。
            10. 代碼閱讀有許多可選擇的策略:自底向上和自頂向下的分析、應(yīng)用試探法和檢查注釋和外部文檔,應(yīng)該依據(jù)問題的需要嘗試所有這些方法。
            11. for(i=0; i<n; i++) r 形式的循環(huán)執(zhí)行n次;其他任何形式都要小心。
            12. 涉及兩項不等測試(其中一項包括相等條件)的比較表達(dá)式可以看作是區(qū)間成員測試。
            13. 我們經(jīng)常可以將表達(dá)式應(yīng)用在樣本數(shù)據(jù)上,借以了解它的含義。
            14. 使用De Morgan法則簡化復(fù)雜的邏輯表達(dá)式。
            15. 在閱讀邏輯乘表達(dá)式時,總是可以認(rèn)為正在分析的表達(dá)式以左的表達(dá)式均為true;在閱讀邏輯和表達(dá)式時,類似地,可以認(rèn)為正在分析 的表達(dá)式以左的表達(dá)式均為false
            16. 重新組織您控制的代碼,使之更為易讀。
            17. 將使用條件運算符?:的表達(dá)式理解為if代碼。
            18. 不需要為了效率,犧牲代碼的易讀性。
            19. 高效的算法和特殊的優(yōu)化確實有可能使得代碼更為復(fù)雜,從而更難理解,但這并不意味著使代碼更為緊湊和不易讀會提高它的效率。
            20. 創(chuàng)造性的代碼而已可以用來提高代碼的易讀性。
            21. 我們可以使用空格、臨時變量和括號提高表達(dá)式的易讀性。
            22. 在閱讀您所控制的代碼時,要養(yǎng)成添加注釋的習(xí)慣。
            23. 我們可以用好的縮進(jìn)以及對變量名稱的明智選擇,提高編寫欠佳的程序的易讀性。
            24. diff程序分析程序的修訂歷史時,如果這段歷史跨越了整體重新縮排,常常可以通過指定-w選項,讓diff忽略空白差異,避免由于更改了縮進(jìn)層次而引入的噪音。
            25. do循環(huán)的循環(huán)體至少執(zhí)行一次。
            26. 執(zhí)行算術(shù)運算時,當(dāng)b=2^n-1時,可以將a&b理解為a%(b+1)
            27. a<<n理解為a * k , k = 2 ^ n
            28. 每次只分析一個控制結(jié)構(gòu),將它的內(nèi)容看作是一個黑盒。
            29. 將每個控制結(jié)構(gòu)的控制表達(dá)式看作是它所含代碼的斷言。
            30. return, goto, break continue語句,還有異常,都會影響結(jié)構(gòu)化的執(zhí)行流程。由于這些語句一般都會終止或重新開始正在進(jìn)行的循環(huán),因此要單獨推理它們的行為。
            31. 用復(fù)雜循環(huán)的變式和不變式,對循環(huán)進(jìn)行推理。
            32. 使用保持含義不變的變換重新安排代碼,簡化代碼的推理工作。

             

            第三章:高級C數(shù)據(jù)類型

            1. 了解特定語言構(gòu)造所有服務(wù)的功能之后,應(yīng)能夠更好地理解使用它們的代碼。
            2. 識別并歸類使用指針的理由。
            3. C程序中,指針一般用來構(gòu)造鏈?zhǔn)綌?shù)據(jù)結(jié)構(gòu)、動態(tài)分配的數(shù)據(jù)結(jié)構(gòu)、實現(xiàn)引用調(diào)用、訪問和迭代數(shù)據(jù)元素、傳遞數(shù)組參數(shù)、引用函數(shù)、作為其他值的別名、代表字符串、以及直接訪問系統(tǒng)內(nèi)存。
            4. 以引用傳遞的參數(shù)可以用來返回函數(shù)的結(jié)果,或者避免參數(shù)復(fù)制帶來的開銷。
            5. 指向數(shù)組元素地址的指針,可以訪問位于特定索引位置的元素。
            6. 指向數(shù)組元素的指針和相應(yīng)的數(shù)組索引,作用在二者上的元素具有相同的語義。
            7. 使用全局或static局部變量的函數(shù)大多數(shù)情況都不可重入(reentrant)。
            8. 字符指針不同于字符數(shù)組。
            9. 識別和歸類應(yīng)用結(jié)構(gòu)或共用體的每種理由。
            10. C語言中的結(jié)構(gòu)將多個數(shù)據(jù)元素集合在一起,使得它們可以作為一個整體來使用。用來從函數(shù)中返回多個數(shù)據(jù)元素,構(gòu)造鏈?zhǔn)綌?shù)據(jù)結(jié)構(gòu)、映射數(shù)據(jù)在硬件設(shè)備、網(wǎng)絡(luò)鏈接和存儲介質(zhì)上的組織方式、實現(xiàn)抽象數(shù)據(jù)類型,以及以面向?qū)ο蟮姆绞骄幊獭?span lang=EN-US>
            11. 共用體在C語言中主要用于優(yōu)化存儲空間的利用,實現(xiàn)多態(tài)、以及訪問數(shù)據(jù)不同的內(nèi)部表達(dá)方式。
            12. 一個指針,在初始化為指向N個元素的存儲空間之后,就可以作為N個元素的數(shù)組來使用。
            13. 動態(tài)分配的內(nèi)存塊可以顯式地釋放,或在程序結(jié)束時釋放,或由垃圾回收器來完成回收;在棧上分配的內(nèi)存塊當(dāng)分配它的函數(shù)退出后釋放。
            14. C程序使用typedef聲明促進(jìn)抽象,并增強(qiáng)代碼的易讀性,從而防范可移植性問題。并模擬C++Java的類聲明行為。
            15. 可以將typedef聲明理解成變量定義:變量的名稱就是類型的名稱;變量的類型就是與該名稱對應(yīng)的類型。

             

            第四章:C數(shù)據(jù)結(jié)構(gòu)

            1. 根據(jù)底層的抽象數(shù)據(jù)類型理解的數(shù)據(jù)結(jié)構(gòu)操作。
            2. C語言中,一般使用內(nèi)建的數(shù)組類型實現(xiàn)向量,不再對底層實現(xiàn)進(jìn)行抽象。
            3. N個元素的數(shù)組可以被序列for(i=0; i<N; i++)完全處理;所有其他變體都應(yīng)該引起警惕。
            4. 表達(dá)式sizeof(x)總會得到用memsetmemcpy處理數(shù)組x(不是指針)所需的正確字節(jié)數(shù)。
            5. 區(qū)間一般用區(qū)間內(nèi)的第一個元素和區(qū)間后的第一個元素來表示。
            6. 不對稱區(qū)間的高位邊界等于低位邊界代表區(qū)間的第一個元素:高位邊界代表區(qū)間外的第一個元素。
            7. 結(jié)構(gòu)的數(shù)組常常表示由記錄和字段組成的表。
            8. 指向結(jié)構(gòu)的指針常常表示訪問底層記錄和字段的游標(biāo)。
            9. 動態(tài)分配的矩陣一般存儲為指向數(shù)組列的指針或指向元素指針的指針:這兩種類型者可以執(zhí)照二維數(shù)據(jù)進(jìn)行訪問。
            10. 以平面數(shù)組形式存儲的動態(tài)分配矩陣,用自定義訪問函數(shù)定們它們的元素。
            11. 抽象數(shù)據(jù)類型為底層實現(xiàn)元素的使用(或誤用)提供了一種信心的量度。
            12. 數(shù)組用從0開始的順序整數(shù)為鍵,組織查找表。
            13. 數(shù)組經(jīng)常用來對控制結(jié)構(gòu)進(jìn)行高效編碼,簡化程序的邏輯。
            14. 通過在數(shù)組中每個位置存儲一個數(shù)據(jù)元素和一個函數(shù)指針(指向處理數(shù)據(jù)元素的函數(shù)),可以將代碼與數(shù)據(jù)關(guān)聯(lián)起來。
            15. 數(shù)組可以通過存儲供程序內(nèi)的抽象機(jī)(abstract machine)或虛擬機(jī)(virtual machine)使用的數(shù)據(jù)或代碼,控制程序的動作。
            16. 可以將表達(dá)式sizeof(x)/sizeof(x[0])理解為數(shù)組x中元素的個數(shù)。
            17. 如果結(jié)構(gòu)中含有指向結(jié)構(gòu)自身,名為next的元素,一般說來,該結(jié)構(gòu)定義的是單向鏈表的結(jié)點。
            18. 指向鏈表結(jié)點的持久性(如全局、靜態(tài)或在堆上分配)指針常常表示鏈表的頭部。
            19. 包含指向自身的nextprev指針的結(jié)構(gòu)可以是雙向鏈表的結(jié)點。
            20. 理解復(fù)雜數(shù)據(jù)結(jié)構(gòu)的指針操作可能將數(shù)據(jù)元素畫為方框、指針畫為箭頭。
            21. 遞歸數(shù)據(jù)結(jié)構(gòu)經(jīng)常用遞歸算法來處理。
            22. 重要的數(shù)據(jù)結(jié)構(gòu)操作算法一般用參數(shù)參數(shù)或模板參數(shù)來參數(shù)化。
            23. 圖的結(jié)點常常順序地存儲在數(shù)組中,鏈接到鏈表中,或通過圖的邊鏈接起來。
            24. 圖中的邊一般不是隱式地通過指針,就是顯式地作為獨立的結(jié)構(gòu)來表示。
            25. 圖的邊經(jīng)常存儲為動態(tài)分配的數(shù)組或鏈表,在這兩種情況下,邊都錨定在圖在的結(jié)點上。
            26. 在無向圖中,表達(dá)數(shù)據(jù)時應(yīng)該將所有的結(jié)點看作是等同的。類似地,進(jìn)行處理任務(wù)的代碼也不應(yīng)該基于它們的方向來區(qū)分連。
            27. 在非連通圖中,執(zhí)行代碼應(yīng)該能夠接通孤立的子圖。
            28. 處理包含回路的圖時,代碼應(yīng)該避免在處理圖的回路時進(jìn)入循環(huán)。
            29. 復(fù)雜的圖結(jié)構(gòu)中,可能隱藏著其他類型的獨立結(jié)構(gòu)。

             

            第五章:高級控制流程

            1. 采用遞歸定義的算法和數(shù)據(jù)結(jié)構(gòu)經(jīng)常用遞歸的函數(shù)定義來實現(xiàn)。
            2. 推理遞歸函數(shù)時,要從基準(zhǔn)范例測試開始,并論證每次遞歸調(diào)用如何逐漸接近非遞歸基準(zhǔn)范例代碼
            3. 簡單的語言常常使用一系列遵循該語言語法結(jié)構(gòu)的函數(shù)進(jìn)行語法分析。
            4. 推理歸調(diào)用等同于一個回到函數(shù)開始處的循環(huán)。
            5. throws子句從方法的定義中移除,然后運行Java編譯器對類的源代碼進(jìn)行編譯,就容易地找到那些可能隱式地生成異常的方法。
            6. 在多處理器計算機(jī)上運行的代碼常常圍繞進(jìn)程或線程進(jìn)行組織。
            7. 工作群并行模型用于在多個處理器間分配工作,或者創(chuàng)建一個任務(wù)池,然后將大量需要處理的標(biāo)準(zhǔn)化的工作進(jìn)行分配。
            8. 基于線程的管理者/工人并行模型一般將耗時的或阻塞的操作分配給工人子任務(wù),從而維護(hù)中心任務(wù)的響應(yīng)性。
            9. 基于進(jìn)程的管理者/工人并行模型一般用來重用現(xiàn)有的程序,或用定義良好的接口組織和分離粗粒度的系統(tǒng)模塊。
            10. 基于流水線的并行處理中,每個任務(wù)都接收到一些輸入,對它們進(jìn)行一些處理,并將生成的輸出傳遞給下一個任務(wù),進(jìn)行不同的處理。
            11. 競爭條件很難捉摸,相關(guān)的代碼常常會將競爭條件擴(kuò)散到多個函數(shù)或模塊;因而,很難隔離由于競爭條件導(dǎo)致的問題。
            12. 對于出現(xiàn)在信號處理品中的數(shù)據(jù)結(jié)構(gòu)操作代碼和庫調(diào)用要保持高度警惕。
            13. 在閱讀包含宏的代碼時,要注意,宏既非函數(shù),也非語句。
            14. do ... while(0)塊中的宏等同于控制塊中的語句。
            15. 宏可以訪問在它的使用點可見的所有局部變量。
            16. 宏調(diào)用可以改變參數(shù)的值。
            17. 基于宏的標(biāo)記拼接能夠創(chuàng)建新的標(biāo)記符。

            6章:應(yīng)對大型項目

            1. 我們可以通過瀏覽項目的源代碼樹--包含項目源代碼的層次目錄結(jié)構(gòu),來分析一個項目的組織方式。源碼樹常常能夠反映出項目在構(gòu)架和軟件過程上的結(jié)構(gòu)。
            2. 應(yīng)用程序的源代碼樹經(jīng)常是該應(yīng)用程序的部署結(jié)構(gòu)的鏡像。
            3. 不要被龐大的源代碼集合嚇倒,它們一般比小型的專門項目組織得更出色。
            4. 當(dāng)您首次接觸一個大型項目時,要花一些時間來了解項目的目錄樹結(jié)構(gòu)。
            5. 項目的源代碼遠(yuǎn)不只是編譯后可以獲得可執(zhí)行程序的計算機(jī)語言指令;一個項目的源碼樹一般還包括規(guī)格說明、最終用戶和開發(fā)人員文檔、測試腳本、多媒體資源、編譯工具、例子、本地化文件、修訂歷史、安裝過程和許可信息。
            6. 大型項目的編譯過程一般聲明性地借助依賴關(guān)系來說明。依賴關(guān)系由工具程序,如make及其派生程序,轉(zhuǎn)換成具體的編譯行動。
            7. 大型項目中,制作文件常常由配置步驟動態(tài)地生成;在分析制作文件之前,需要先執(zhí)行項目特定的配置。
            8. 檢查大型編譯過程各個步驟時,可以使用make程序的-n形狀進(jìn)行預(yù)演。
            9. 修訂控制系統(tǒng)提供從儲存庫中獲取源代碼最新版本的方式。
            10. 可以使用相關(guān)的命令,顯示可執(zhí)行文件中的修訂標(biāo)識關(guān)鍵字,從而將可執(zhí)行文件與它的源代碼匹配起來。
            11. 修訂日志中出現(xiàn)的bug跟蹤系統(tǒng)內(nèi)的編號,可以在bug跟蹤系統(tǒng)的數(shù)據(jù)庫中找到有關(guān)問題的說明。
            12. 可以使用修訂控制系統(tǒng)的版本儲存庫,找出特定的變更是如何實現(xiàn)的。
            13. 定制編譯工具用在軟件開始過程的許多方面,包括配置、編譯過程管理、代碼的生成、測試和文檔編制。
            14. 程序的調(diào)度輸出可以幫助我們理解程序控制流程和數(shù)據(jù)元素的關(guān)鍵部分。
            15. 跟蹤語句所在的地點一般也是算法運行的重要部分。
            16. 可以用斷言來檢驗算法動作的步驟、函數(shù)接收的參數(shù)、程序的控制流程、底層硬件的懺悔和測試的結(jié)果。
            17. 可以使用對算法進(jìn)行檢驗的斷言來證實您對算法動作的理解,或?qū)⑺鳛橥评淼钠饋怼?span lang=EN-US>
            18. 對函數(shù)參數(shù)和結(jié)果的斷言經(jīng)常記錄了函數(shù)的前置條件和后置條件。
            19. 我們可以將測試整個函數(shù)的斷言作為為每個給定函數(shù)的規(guī)格說明。
            20. 測試可以部分地代替函數(shù)規(guī)格說明。
            21. 可以使用測試的輸入數(shù)據(jù)對源代碼序列進(jìn)行預(yù)演。

            7章:編碼規(guī)范和約定

            1. 了解了給定代碼庫所遵循的文件組織方式后,就能更有效率地瀏覽它的源代碼。
            2. 閱讀代碼時,首先要確保您的編輯器或優(yōu)美打印程序的tab設(shè)置,與代碼遵循的風(fēng)格規(guī)范一致。
            3. 可以使用代碼塊的縮進(jìn),快速地掌握代碼的總體結(jié)構(gòu)。
            4. 對于編排不一致的代碼,應(yīng)該立即給予足夠的警惕。
            5. 分析代碼時,對標(biāo)記為XXXFIXMETODO的代碼序列要格外注意:錯誤可能就潛伏在其中。
            6. 常量使用大寫字母命名,單詞用下劃線分隔。
            7. 在遵循Java格式的程序中,包名(package name)總是從一個頂級的域名開始(例如,orgcomsun),類名和接口名由大寫字母開始,方法和變量名由小寫字母開始。
            8. 用戶界面控件名稱之前的匈牙利記法的前綴類型標(biāo)記可以幫助我們確定它的作用。
            9. 不同的編程規(guī)范對可移植構(gòu)造的構(gòu)成有不同的主張。
            10.  在審查代碼的可移植性,或以某種給定的編碼規(guī)范作為指南時,要注意了解規(guī)范的對可移植性需求的界定與限制。
            11. 如果GUI功能都使用相應(yīng)的編程結(jié)構(gòu)來實現(xiàn),則通過代碼審查可以輕易地確定用戶界面的規(guī)格說明是否被正確地采用。
            12. 了解項目編譯過程的組織方式與自動化方式之后,我們就能夠快速地閱讀與理解對應(yīng)的編譯規(guī)則。
            13. 當(dāng)檢查系統(tǒng)的發(fā)布過程時,常常可以將相應(yīng)發(fā)行格式的需求作為基準(zhǔn)。

            8章:文檔

            1. 閱讀代碼時,應(yīng)該盡可能地得到任何能夠得到的文檔。
            2. 閱讀一小時代碼所得到的信息只不過相當(dāng)于閱讀一分鐘文檔。
            3. 使用系統(tǒng)的規(guī)格說明文檔,了解所閱讀代碼的運行環(huán)境。
            4. 軟件需求規(guī)格說明是閱讀和評估代碼的基準(zhǔn)。
            5. 可以將系統(tǒng)的設(shè)計規(guī)格說明作為認(rèn)知代碼結(jié)構(gòu)的路線圖,閱讀具體代碼的指引。
            6. 測試規(guī)格說明文檔為我們提供可以用來對代碼進(jìn)行預(yù)演的數(shù)據(jù)。
            7. 在接觸一個未知系統(tǒng)時,功能性的描述和用戶指南可以提供重要的背景信息,從而更好地理解閱讀的代碼所處的上下文。
            8. 從用戶參考手冊中,我們可以快速地獲取,應(yīng)用程序在外觀與邏輯上的背景知識,從管理員手冊中可以得知代碼的接口、文件格式和錯誤消息的詳細(xì)信息。
            9. 得到文檔可以快捷地獲取系統(tǒng)的概況,了解提供特定特性的代碼。
            10. 文檔經(jīng)常能夠反映和提示出系統(tǒng)的底層結(jié)構(gòu)。
            11. 文檔有助于理解復(fù)雜的算法和數(shù)據(jù)結(jié)構(gòu)。
            12. 算法的文字描述能夠使不透明(晦澀,難以理解)的代碼變得可以理解。
            13. 文檔常常能夠闡明源代碼中標(biāo)識符的含義。
            14. 文檔能夠提供非功能性需求背后的理論基礎(chǔ)。
            15. 文檔還會說明內(nèi)部編程接口。
            16. 由于文檔很少像實際的程序代碼那樣進(jìn)行測試,并受人關(guān)注,所以它常常可能存在錯誤、不完整或過時。
            17. 文檔也提供測試用例,以及實際應(yīng)用的例子。
            18. 文檔常常還會包括書籍的實現(xiàn)問題或bug
            19. 環(huán)境中已知的缺點一般都會記錄在源代碼中。
            20. 文檔的變更能夠標(biāo)出那些故障點。
            21. 對同一段源代碼重復(fù)或互相沖突的理性,常常表示存在根本性的設(shè)計缺陷,從而使得維護(hù)人員需要用一系列的修補(bǔ)程序來修復(fù)。
            22. 相似的修復(fù)應(yīng)用到源代碼的不同部分,常常表示一種易犯的錯誤或疏忽,它們同樣可能會在其他地方存在。
            23. 文檔常常會提供不恰當(dāng)?shù)男畔ⅲ`導(dǎo)我們對源代碼的理解。
            24. 要警惕那些未歸檔的特性:將每個實例歸類為合理、疏忽或有害,相應(yīng)地決定是否修復(fù)代碼或文檔。
            25. 有時,文檔在描述系統(tǒng)時,并非按照已完成的實現(xiàn),而是按照系統(tǒng)應(yīng)該的樣子或?qū)淼膶崿F(xiàn)。
            26. 在源代碼文檔中,單詞gork的意思一般是指理解
            27. 如果未知的或特殊用法的單詞阻礙了對代碼的理解,可以試著在文檔的術(shù)語表(如果豐碩的話)、New Hacker's Dictionary[Ray96]、或在Web搜索引擎中查找它們。
            28. 總是要以批判的態(tài)度來看待文檔,注意非傳統(tǒng)的來源,比如注釋、標(biāo)準(zhǔn)、出版物、測試用例、列表、新聞組、修訂日志、問題跟蹤數(shù)據(jù)庫、營銷和源代碼本身。
            29. 總是要以批判的態(tài)度來看待文檔;由于文檔永遠(yuǎn)不會執(zhí)行,對文檔的測試和正式復(fù)查也很少達(dá)到對代碼的同樣水平,所以文檔常常會誤導(dǎo)讀者,或者完全錯誤。
            30. 對于那些有缺陷的代碼,我們可以從中推斷出它的真實意圖。
            31. 在閱讀大型系統(tǒng)的文檔時,首先要熟悉文檔的總體結(jié)構(gòu)和約定。
            32. 在對付體積龐大的文檔時,可以使用工具,或?qū)⑽谋据敵龅礁咂焚|(zhì)輸出設(shè)備上,比如激光打印機(jī),來提高閱讀的效率。

            9章:系統(tǒng)構(gòu)架

            1. 一個系統(tǒng)可以(在重大的系統(tǒng)中也確定如此)同時展示出多種不同的構(gòu)架類型。以不同的方式檢查同一系統(tǒng)、分析系統(tǒng)的不同部分、或使用不同級別的分解,都有可能發(fā)現(xiàn)不同的構(gòu)架類型。
            2. 協(xié)同式的應(yīng)用程序,或者需要協(xié)同訪問共享信息或資源的半自治進(jìn)程,一般會采用集中式儲存庫構(gòu)架。
            3. 黑板系統(tǒng)使用集中式的儲存庫,存儲非結(jié)構(gòu)化的鍵/值對,作為大量不同代碼元件之間的通信集線器。
            4. 當(dāng)處理過程可以建模、設(shè)計和實現(xiàn)成一系列的數(shù)據(jù)變換時,常常會使用數(shù)據(jù)流(或管道--過濾器)構(gòu)架。
            5. 在批量進(jìn)行自動數(shù)據(jù)處理的環(huán)境中,經(jīng)常會采用數(shù)據(jù)流構(gòu)架,在對數(shù)據(jù)變換工具提供大量支持的平臺上尤其如此。
            6. 數(shù)據(jù)流構(gòu)架的一個明顯征兆是:程序中使用臨時文件或流水線(pipeline)在不同進(jìn)程間進(jìn)行通信。
            7. 使用圖示來建模面向?qū)ο髽?gòu)架中類的關(guān)系。
            8. 可以將源代碼輸入到建模工具中,逆向推導(dǎo)出系統(tǒng)的構(gòu)架。
            9. 擁有大量同級子系統(tǒng)的系統(tǒng),常常按照分層構(gòu)架進(jìn)程組織。
            10. 分層構(gòu)架一般通過擁有標(biāo)準(zhǔn)化接口的軟件組件來實現(xiàn)。
            11. 系統(tǒng)中每個層可以將下面的層看作抽象實體,并且(只要該層滿足它的需求說明)不關(guān)心上面的層如何使用它。
            12. 層的接口既然可以是支持特定概念的互補(bǔ)函數(shù)族,也可以是一系列支持同一抽象接口不同底層實現(xiàn)的可一互換函數(shù)。
            13. C語言實現(xiàn)的系統(tǒng),常常用函數(shù)指針的數(shù)組,表達(dá)層接口的多路復(fù)用操作。
            14. 用面向?qū)ο蟮恼Z言實現(xiàn)的系統(tǒng),使用虛方法調(diào)用直接表達(dá)對層接口的多路復(fù)用操作。
            15. 系統(tǒng)可以使用不同的、獨特的層次分解模型跨各種坐標(biāo)軸進(jìn)行組織。
            16. 使用程序切片技術(shù),可以將程序中數(shù)據(jù)和控制之間依賴關(guān)系集中到一起。
            17. 在并發(fā)系統(tǒng)中,一個單獨的系統(tǒng)組件起到集中式管理器的作用,負(fù)責(zé)啟動、停止和協(xié)調(diào)其他系統(tǒng)進(jìn)程和任務(wù)的執(zhí)行。
            18. 現(xiàn)實的系統(tǒng)都會博采眾家之長。當(dāng)處理此類系統(tǒng)時,不要徒勞地尋找無所不包的構(gòu)架圖;應(yīng)該將不同構(gòu)架風(fēng)格作為獨立但相關(guān)的實體來進(jìn)行定位、并了解。
            19. 狀態(tài)變遷圖常常有助于理清狀態(tài)機(jī)的動作。
            20. 在處理大量的代碼時,了解將代碼分解成單獨單元的機(jī)制極為重要。
            21. 大多數(shù)情況下,模塊的物理邊界是單個文件、組織到一個目錄中的多個文件或擁有統(tǒng)一前綴的文件的集合。
            22. C中的模塊,由提供模塊公開接口的頭文件和提供對應(yīng)實現(xiàn)的源文件組成。
            23. 對象的構(gòu)造函數(shù)經(jīng)常用來分配與對象相關(guān)的資源,并初始化對象的狀態(tài)。函數(shù)一般用來釋放對象在生命期中占用的資源。
            24. 對象方法經(jīng)常使用類字段來存儲控制所有方法運行的數(shù)據(jù)(比如查找表或字典)或維護(hù)類動作的狀態(tài)信息(例如,賦給每個惟一標(biāo)識符的計數(shù)器)。
            25. 在設(shè)計良好的類中,所有的字段都應(yīng)聲明為private,并用公開的訪問方法提供對它們的訪問。
            26. 在遇到friend方法時,要停下來分析一下,看看繞過類封裝在設(shè)計上的理由。
            27. 可以有節(jié)制地用運算符增強(qiáng)特定類的可用性,但用運算符重載,將類實現(xiàn)為擁有內(nèi)建算術(shù)類型相關(guān)的全部功能的類數(shù)字實體,是不恰當(dāng)?shù)摹?span lang=EN-US>
            28. 泛型實現(xiàn)不是在編譯期間通過宏替換或語言所支持的功能(比如C++模板和Ada的泛性包)來實現(xiàn),就是在運行期間通過使用數(shù)據(jù)元素的指針和函數(shù)的指針、或?qū)ο蟮亩鄳B(tài)性來實現(xiàn)。
            29. 抽象數(shù)據(jù)類型經(jīng)常用來封裝常用的數(shù)據(jù)組織方案(比如樹、列表或桟),或者對用戶隱藏數(shù)據(jù)類型的實現(xiàn)細(xì)節(jié)。
            30. 使用庫的目標(biāo)多種多樣:重用源代碼或目標(biāo)代碼,組織模塊集合,組織和優(yōu)化編譯過程,或是用來實現(xiàn)應(yīng)用程序各種特性的按需載入。
            31. 大型的、分布式的系統(tǒng)經(jīng)常實現(xiàn)為許多互相協(xié)作的進(jìn)程。
            32. 對于基于文本的數(shù)據(jù)儲存庫,可以通過瀏覽存儲在其中的數(shù)據(jù),破譯出它的結(jié)構(gòu)。
            33. 可以通過查詢數(shù)據(jù)字典中的表,或使用數(shù)據(jù)庫專用的SQL命令,比如show table,來分析關(guān)系型數(shù)據(jù)庫的模式。
            34. 識別出重要的構(gòu)架元素后,可以查找其最初的描述,了解正確地使用這種構(gòu)架的方式,以及可能出現(xiàn)的誤用。
            35. 要詳細(xì)分析建立在某種框架之上的應(yīng)用程序,行動的最佳路線就是從研究框架自身開始。
            36. 在閱讀向?qū)傻拇a時,不要期望太高,否則您會感到失望。
            37. 學(xué)習(xí)幾個基本的設(shè)計模式之后,您會發(fā)現(xiàn),您查看代碼構(gòu)架的方式會發(fā)生改變:您的視野和詞匯將會擴(kuò)展到能夠識別和描述許多通用的形式。
            38. 頻繁使用的一些模式,但并不顯式地指出它們的名稱,這是由于構(gòu)架性設(shè)計的重用經(jīng)常先于模式的形成。
            39. 請試著按照底層模式來理解構(gòu)架,即便代碼中并沒有明確地提及模式。
            40. 大多數(shù)解釋器都遵循類似的處理構(gòu)架,圍繞一個狀態(tài)機(jī)進(jìn)行構(gòu)建,狀態(tài)機(jī)的操作依賴于解釋器的當(dāng)前狀態(tài)、程序指令和程序狀態(tài)。
            41. 多數(shù)情況下,參考構(gòu)架只是為應(yīng)用程序域指定一種概念性的結(jié)構(gòu),具體的實現(xiàn)并非必須遵照這種結(jié)構(gòu)。

            10章:代碼閱讀工具

            1. 詞匯工具可以高效地在一個代碼文件中或者跨多個文件查找某種模式。
            2. 使用程序編輯器和與此同時表達(dá)式命令,瀏覽龐大的源代碼文件。
            3. 以只讀方式瀏覽源代碼文件
            4. 使用正則表達(dá)式 ^function name可以找出函數(shù)的定義。
            5. 使用正則表達(dá)式的字符類,可以查找名稱遵循特定模式的變量。
            6. 使用正則表達(dá)式的否定字符類,可以避免非積極匹配。
            7. 使用正則表達(dá)式symbol-1.*symbol-2,可以查找出現(xiàn)在同一行的符號。
            8. 使用編譯器的tags功能,可以快速地找出實體的定義。
            9. 可能用特定的tag創(chuàng)建工具,增加編輯器的瀏覽功能。
            10. 使用編輯器的大綱視圖,可以獲得源代碼結(jié)構(gòu)的鳥瞰圖。
            11. 使用您的編輯器來檢測源代碼中圓括號、方括號和花括號的匹配。
            12. 使用grep定位符號的聲明、定義和應(yīng)用。
            13. 當(dāng)您不能精確地要查找的內(nèi)容時,請使用關(guān)鍵單詞的詞干對程序的源代碼進(jìn)行查找。
            14. grep過濾其他工具生成的輸出,分離出您要查找的項。
            15. grep的輸出輸送到其他工具,使復(fù)雜處理任務(wù)自動化。
            16. 通過對grep的輸出進(jìn)行流編輯,重用代碼查找的結(jié)果。
            17. 通過選取與噪音模式不匹配的輸出行(grep -v),過濾虛假的grep輸出。
            18. 使用fgrep在源代碼中查找字符串列表。
            19. 查找注釋,或標(biāo)識符大小寫不敏感的語言編寫的代碼時,要使用大小寫不敏感的模式匹配(grep -i)。
            20. 使用grep -n命令行開關(guān),可以創(chuàng)建與給定正則表達(dá)式匹配的文件和等號的檢查表。
            21. 可以使用diff比較文件或程序不同版本之間的差別。
            22. 在運行diff命令時,可以使用diff -b,使文件比較算法忽略結(jié)尾的空格,用-w忽略所有空白區(qū)域的差異,用-i使文件比較對大小寫不敏感。
            23. 不要對創(chuàng)建自己的代碼閱讀工具心存畏懼。
            24. 在構(gòu)建自己的代碼閱讀工具時:要充分利用現(xiàn)代原型語言所提供的能力;從簡單開始,根據(jù)需要逐漸改進(jìn);使用利用代碼詞匯結(jié)構(gòu)的各種試探法;要允許一些輸出噪音或寂靜(無關(guān)輸出或缺失輸出);使用其他工具對輸入進(jìn)行預(yù)處理,或者對輸出進(jìn)行后期處理。
            25. 要使編譯器成為您的朋友;指定恰當(dāng)級別的編譯器警告,并小心地評估生成的結(jié)果。
            26. 使用C預(yù)處理器理清那些濫用預(yù)處理器特性的程序。
            27. 要徹底地了解編譯器如何處理特定的代碼塊,需要查看生成的符號(匯編)代碼。
            28. 通過分析相應(yīng)目標(biāo)文件中的符號,可以清晰地源文件的輸入和輸出。
            29. 使用源代碼瀏覽器瀏覽大型的代碼集合以及對象類型。
            30. 要抵制信按照您的編碼規(guī)范對外部代碼進(jìn)行美化的誘惑;不必要的編排更改會創(chuàng)建不同的代碼,并妨礙維護(hù)工作的組織。
            31. 優(yōu)美打印程序和編輯器語法著色可以使得程序的源代碼更為易讀。
            32. cdecl程序可以將難以理解的CC++類型聲明轉(zhuǎn)換成純英語(反之亦然)。
            33. 實際運行程序,往往可以更深刻地理解程序的動作。
            34. 系統(tǒng)調(diào)用、事件和數(shù)據(jù)包跟蹤程序可以增進(jìn)對程序運作的理解。
            35. 執(zhí)行剖析器可以找出需要著重優(yōu)化的代碼,驗證輸入數(shù)據(jù)的覆蓋性,以及分析算法的運作。
            36. 通過檢查從未執(zhí)行的代碼行,可以找出測試覆蓋的弱點,并據(jù)此修正測試數(shù)據(jù)。
            37. 要探究程序動態(tài)運行時的每個細(xì)節(jié),需要在調(diào)度器中運行它。
            38. 將您覺得難以理解的代碼打印到紙上。
            39. 可以試著向別人介紹您在閱讀的代碼,這樣做一般會增進(jìn)您對代碼的理解。
            40. 理解復(fù)雜的算法或巧妙的數(shù)據(jù)結(jié)構(gòu),要選擇一個安靜的環(huán)境,然后聚精會神地考慮,不要借助于任何算機(jī)化或自動化的幫助。

            11章:一個完整的例子

            1. 模仿軟件的功能時,要依照相似實體的線路(類、函數(shù)、模塊)。在相似的現(xiàn)有實體中,為簡化對源代碼庫的文本查找,應(yīng)選取罕見的名稱。
            2. 自動生成的文件常常會在文件的形狀有一段注釋,說明這種情況。
            3. 如果試圖精確地分析代碼,一般會陷入數(shù)量眾多的類、文件和模塊中,這些內(nèi)容會很快將我們淹沒;因此,我們必須將需要理解的代碼限定在絕對必需的范圍之內(nèi)。
            4. 采用一種廣度優(yōu)先查找策略,從多言攻克代碼閱讀中存在的問題,直到找出克服它們的方法為止。

             

            posted on 2007-12-01 21:16 楊粼波 閱讀(878) 評論(4)  編輯 收藏 引用

            評論

            # re: 摘自《代碼閱讀方法與實踐》 2007-12-03 10:46 金慶

            > 閱讀代碼尋找重構(gòu)機(jī)會時,先從系統(tǒng)的構(gòu)架開始,然后逐步細(xì)化,能夠獲得最大的效益。

            可能是我理解錯誤,我認(rèn)為重構(gòu)是從細(xì)節(jié)開始的,如先改改變量名,當(dāng)對整體把握更大時,才會對構(gòu)架進(jìn)行重構(gòu)。  回復(fù)  更多評論   

            # re: 摘自《代碼閱讀方法與實踐》[未登錄] 2007-12-03 19:01 楊粼波

            真正有效的重構(gòu)應(yīng)該是針對架構(gòu)的,
            那些改改名字的小重構(gòu)只是對代碼可讀性造成改觀.
            而對架構(gòu)的改觀是客觀的,
            主要表現(xiàn)于:更好的可維護(hù)性,更好的可擴(kuò)展性等.  回復(fù)  更多評論   

            # re: 摘自《代碼閱讀方法與實踐》 2007-12-04 15:01 金慶

            我的觀點是:從微型的重構(gòu)開始。
              回復(fù)  更多評論   

            # re: 摘自《代碼閱讀方法與實踐》[未登錄] 2007-12-04 19:13 楊粼波

            如果把架構(gòu)的重構(gòu)實施,
            從某種意義上說,是多個微型重構(gòu)的復(fù)合.
            重構(gòu)的過程是持續(xù)的.
            往往很多大到架構(gòu)的重構(gòu)都是由小重構(gòu)引起的,
            但是小重構(gòu)不一定會引起架構(gòu)的重構(gòu).
            改改名字根本是微不足道的,僅僅對可讀性造成影響.
            現(xiàn)實實施中,
            事實上所謂的大的重構(gòu)都是由持續(xù)不斷的小重構(gòu)積累而成的.
            也有可能我覺得架構(gòu)不好,一下子就把架構(gòu)給改了.
            一切看實施情況吧.
            我對重構(gòu)理解不夠深入,
            但是我認(rèn)為實施重構(gòu)是根據(jù)重構(gòu)的目的來決定的.  回復(fù)  更多評論   


            只有注冊用戶登錄后才能發(fā)表評論。
            網(wǎng)站導(dǎo)航: 博客園   IT新聞   BlogJava   博問   Chat2DB   管理


            色天使久久综合网天天| 精品免费久久久久国产一区| 一日本道伊人久久综合影| 91精品国产高清久久久久久国产嫩草| 午夜精品久久久久久99热| 国产精品久久久久蜜芽| 亚洲国产婷婷香蕉久久久久久| 久久久亚洲精品蜜桃臀| 久久精品成人免费国产片小草| 久久精品国产WWW456C0M| 久久黄色视频| 亚洲国产精品嫩草影院久久| 伊人久久大香线蕉AV一区二区| 亚洲一区精品伊人久久伊人| 一本久久a久久精品综合香蕉| 欧美无乱码久久久免费午夜一区二区三区中文字幕 | 26uuu久久五月天| 久久精品国产免费一区| 久久久精品免费国产四虎| 精品国产一区二区三区久久| 久久精品草草草| 精品综合久久久久久88小说 | 91精品国产高清久久久久久91| 精品久久一区二区| 国产精品成人久久久久久久| 精品久久久久中文字| 香蕉久久AⅤ一区二区三区| 国内精品伊人久久久影院| 精品久久久无码人妻中文字幕| 久久天堂AV综合合色蜜桃网| 国产一区二区三区久久精品| 久久99精品国产麻豆蜜芽| 亚洲国产成人精品91久久久 | 久久精品国产黑森林| 国产精品久久久久蜜芽| 国内精品久久久人妻中文字幕| 国内精品伊人久久久久| 久久亚洲欧洲国产综合| 天天躁日日躁狠狠久久| 久久精品免费一区二区三区| 午夜肉伦伦影院久久精品免费看国产一区二区三区 |