【方法】閱讀源碼


以下內容來自網絡。

經驗總結

先別看代碼,先看書或者國外牛人博客,嘗試從設計者的角度審視代碼,也就是從全局到模塊再到主要類的方式去梳理。如果一上來就扎入代碼,會很快迷失在茫茫代碼中。

不要直接看代碼。先看文檔,特別是關於整個東西的整體架構、整體設計的部分,瞭解它的結構和運作方式。然後看API文檔,瞭解它的主要接口都在幹什麼。最後再看具體實現

先看代碼的整體結構,實現類,接口類,模型類,工具類區別開來。花10分鐘時間把每個文件大概看下。之後跟着程序跑一次,從入口走,進入庫的核心實現類後觀察他實例化了哪些類,這些類分別都做了些什麼…最後一層層慢慢地把源碼拆開閱讀,很快就能理解。一定要有耐心,有的源碼比較難懂,往往看了幾遍後還沒有頭緒,相信多讀繼續,每次肯定有新收穫。

讀代碼和寫代碼一樣,你得先明確目標。漫無目的的讀代碼是不會有結果的,就如你自己都不知道寫什麼功能的情況下,能寫什麼代碼?既然明確你想了解的具體功能,接下去就簡單了,你只要找到這個功能的切入點,按代碼順序讀下來就可以了,讀代碼的速度取決於你對整體代碼的熟悉程度,剛上手肯定會慢一點整個過程中最關鍵的是找切入點,我看了很多新手程序員根本找不到他想看的功能該如何看起,那就需要一些技巧了,找一些不會變的關鍵api來作爲索引的關鍵字,比如網絡相關的肯定有recv,文件相關的也就是fread這樣的一系列函數。

讀懂開源項目首先你一定是這個開源項目的重度用戶,你熟悉這個項目的個性和脾氣。比如說你用一個開源框架,你知道這個框架喜歡你怎麼配置,什麼時候會出問題。然後某次你調試代碼的時候突然發現一些不合情理的異常,於是你一步一步跟蹤終於找到是在調用框架方法A的時候出現的問題。這是你自然而然的挖掘到這個項目的源代碼去,終於發現原來這個項目有n層調用,每一層都檢查些什麼、又做些什麼,等等。這種情況經歷多了,你對這個項目就越來越熟悉,甚至如果你發現了缺陷還可以貢獻一下。最後再說一遍,最看不順眼整天一上來就牛逼哄哄讓人看個Linux內核之類的,tmd絕對沒安好心。另外,關於代碼註釋,不好意思,我還沒見過任何一個開源項目有完整註釋的,5%都沒有。

看得慢,看不懂,要嘛是看少了,要嘛是水平不夠。沒捷徑,多看,努力提升理論水平。熟讀唐詩三百首,多看豬跑。對於沒多少經驗的新手,建議從兩個角度讀,全局或者局部。瞭解全局的時候,關注執行流程、層次、調用之類的,對細節不求甚解,看不懂的,底層的,跳過就是。讀細節的時候,就只讀系統內自己關注的某個點,甚至某個具體的方法或者函數,一行一行慢慢啃。

題主,我個人感覺讀開源分兩種情況:1. 工作中需要解決一類問題2. 爲了學習如果爲了解決一類問題,這個時候你的目的是很明確的,直接在源碼中找尋相關的部分讀就好。我當時爲了解決連接不提供JMXURL的MBeanServer問題時,去看OpenJDK的源碼,其源碼東西很多,但這一塊因爲目的明確,可以直接到其Attach機制實現的部分去了解,順帶着看JConsole的實現,就解決了問題。而如果是爲了學習,就需要慢慢來讀,開源項目一般都不小,不能急着想一氣讀完。那樣和讀課文一樣看過之後,也是吸收不到東西的。而藉助其文檔,瞭解整個項目的大概,架構,組件等一系列內容,再分別去看,效果可能會好一些。甚至讀的過程中,某一些點感覺很不錯,自己馬上上手mock一個,興趣可能會大增吧。 比如你在讀Tomcat源碼,則先了解其各個容器,組件劃分等。之後各個組件間的關聯,可以跑起來跟一下就會有個大概印象。另外,也可以從開源項目的testcase入手,都是按功能點寫的。至於題主提到的類有多個繼承這一類的,可以在看的時候一邊看一邊畫個類圖,也方便後續的使用。如果給別人講,甚至可以直接拿類圖開始說。

根據我的經驗,把握粒度很重要,每行每行讀是不現實的,這樣容易造成只見樹木不見森林,但是又不能讀的太粗糙,否則錯過很多精華部分,以c代碼爲例,我一般是先以文件爲單位,看看每個文件大致是幹嘛的,然後再以函數爲單位,這時不關心函數的具體實現細節,而是將注意力放在函數接口上,大致理解下函數的意圖,控制流的流動等,然後覺得哪個函數比較重要,在看看其實現。。。如果一上來就一行一行的啃就圖樣圖森破了,上述過程完成之後,如果還有餘力,最好親手實現一下,正所謂知者行之始,行者知之成,知行合一,如果能自己寫一個,就說明真的掌握了。。。

應該先打開它的trace或debug日誌,跑起來,然後跟蹤日誌,可以最快的熟悉代碼

自動生成代碼圖的工具

單步調試,可以看到程序流程

先去掌握了設計模式,再去看優秀的開源代碼

1、導入代碼至開發環境,運行起來
2、樣例代碼做爲入口,逐步斷點調試
3、把工程、包名、類在word中按層次整理,分析寫出用途和主要技術點
4、畫程序流程圖或者時序圖
5、嘗試代碼擴展、以及打包構建

讀代碼切勿一開始就鑽進一些細節。就像工作中接觸一個新項目,新人也是從解bug 開始。帶着目標問題去讀,效果更好。要掌握一個整體架構,不妨自己動手畫出一張完整的類圖,對於理解代碼架構非常有幫助。一些主要的業務邏輯,繼續畫些流程圖順序圖,就一目瞭然了。最後纔是語法方面的問題。我認爲好的代碼一定也是閱讀起來超爽的…

先搞清楚代碼的業務流程,什麼設計模式都是看懂代碼以後的事了

直接開始調試,先大致搞清楚程序跑得流程;然後不好調試的部分,比如網絡,添加log,通過讀日誌分析程序行爲。
最後,挑感興趣的部分,直接讀代碼。

開源項目的代碼結構文件佈局應該都不錯,在瞭解項目的主題功能後,我都是先看文件夾結構,猜測每個文件夾下的文件可能是幹嘛的,文件名字應該都挺達意。我只說vs,它好像可以畫出所有類的引用關係圖,然後挑選繼承關係在最上層的開始閱讀。如果項目功能模塊分的比較開,那更好了,一個模塊一個模塊的讀。閱讀中最怕數據model了,變量都是啥意思,怎麼用,能幹嘛,真是煩死了。

閱讀源代碼的第一個工具,就是你手中的code base。把它編譯出來,運行它,加log,試着修改一些數據和代碼,看看有什麼變化。第二個重要的工具就是debugger,而debugger最重要的功能是獲取call stack。在你感興趣的use case裏pause一下,在你不知道有什麼用的函數里加個斷點,顯示出來的call stack都能讓你對系統有更清晰的認識。一個軟件系統就是一個小宇宙。別期待有什麼高明的文檔。要把自己當成探求自然真理的物理學家。
必須找好切入點。你要解決什麼問題。是要fix bug;還是要把這個系統和其它模塊集成;還是要增加新功能。物理學家沒有上來就研究整個宇宙的,必須選好分支。
如果你有一個猜想,但是又和你的目標關聯不太大,那就堅持這個猜想,直到出現明顯反例。物理學有很多這樣的例子,和數學不同,爲了旁支猜想投入過多研究是不明智的。
如果有明顯證據證明你的某個旁支猜想大錯特錯,你就要放棄主要目標,暫時把解決旁支猜想作爲主要目標。比如,你本來以爲某個結構是LRU的cache,結果發現怎麼做都不對,那就先放棄原來的目標,專門研究這個結構的用途。
對於旁支猜想的不斷切換,要做好自己的task stack保留。在旁支猜想解決之後,要根據結論儘快回到上次中斷的任務。

第一,找准入口出口,不要直接跳進去看,任何代碼都有觸發點,無論是http request,還是服務器自動啓動,還是main函數,還是其他的,先從入口開始。第二,手邊一支筆一張紙,除非你是Jeff,否則你不會記得那麼多跳轉的。一個跳轉就寫下來函數/方法名和參數,讀完一遍,就有了一個sequence diagram雛形第三,私有方法掠過,只要記住輸入輸出即可,無需看具體實現

1.先搞清程序的流程和整體框架。模糊的地方可以嘗試進行修改看效果,有debug工具的話最好。2.定位。找到需要了解的具體功能實現模塊。工具方法也可如上。3.分析。對需要的具體的代碼進行詳細分析。搞清變量的意義和關聯關係,搞清實現的邏輯和算法。好的代碼,此處最需要註釋。

一般閱讀非自己寫的代碼都是關注某一部分代碼塊,比如某一條流程線。如果這份代碼讓你看的眼花繚亂,條件允許的話最有效地方法就是進行debug調試。一步一步的跟進調試會讓你很流暢的根據代碼的執行步驟瞭解代碼的邏輯。如果無法debug調試的話,我會從最淺層的代碼層入手,理清思路,先不去關注深層的邏輯或者函數,需要使用到得時候在去仔細查看。

如果是C++的話,VS可以生成UML的類關係圖,由UML圖去看關係比較清楚,即使不用VS,也有很多軟件可以從代碼生成UML圖,看面向對象的代碼,搞清楚有多少類,每個類的接口是什麼,繼承關係,依賴關係,VS的類圖可以通過雙擊直接跳轉到目標代碼,分析起來也會很方便。看項目的源代碼主要的難點是整理清楚整體的邏輯關係,具體實現可以先不去看,配合UML用筆把把整體依賴關係在之上畫寫清楚,哪些類是做什麼的也要寫一寫,如果只看不記,就像走馬觀花,今天可能有點感覺了,明天就會忘記,因爲很多代碼依賴關係錯綜複雜,筆記配合UML是最好的入門方法了。多問自己幾個爲什麼,它爲什麼要這麼封裝,爲什麼要分離,爲什麼要用模板?然後閱讀的過程中去一一解開這些問題,代碼就漸漸懂了。當然,有些時候實現可以有多種方式,也不用太轉牛角尖,非要思維和作者達成一致,只要合理即可。

單元測試
在這個頁面上搜索了一下,發現提到單元測試的人很少,所以我覺得很有必要強調一下。
思路
我覺得得從開發者的角度去閱讀程序源代碼,從一開始就不要抱着學習的心態。去改進它。

作者:豆包
鏈接:https://www.zhihu.com/question/19625320/answer/105942481
來源:知乎
著作權歸作者所有。商業轉載請聯繫作者獲得授權,非商業轉載請註明出處。

  1. 首先你得找本入門資料,最好是中文的,這樣可以瞭解基本術語,知道變量的意思是啥,這樣閱讀代碼裏註釋時方便快速理解。 2. 有一個好的調試工具,Libgdx 可以導入Eclipse或者Android Studio,因此我一直用Eclipse看代碼,方便快速定位方法和變量。3. 每個源代碼裏基本都有demo 和 WIKI,將demo運行起來,結合WIKI 不斷的修改裏面的方法和變量,這樣就清楚的知道每個API的作用。這絕對是幫你快速入門、瞭解API作用的不二法門。4. 瞭解API之後自己寫簡單的demo,加速自己對框架的理解和記憶。 5.現在我們要深入源碼,根據步驟 3 進入每一個源文件,先閱讀註釋,然後看每個API實現方法。(其實要不自己寫框架,只需要理解API具體做什麼就可以了) 瞭解框架所用的數據結構,最好再去看具體的實現步驟,這個真是太難了^^ 6. 根據步驟自己寫一個教程/筆記,這個過程是一個查漏補缺的過程,也方便你加深記憶。目前我正在寫一個關於Libgdx的教程: Libgdx教程目錄 7. 最後一點,但是也是很重要的一點,必須具備一些額外相關知識:要掌握Libgdx的源碼最好知道 設計模式 的相關知識,瞭解OpenGL的知識更好了,我就因爲不懂,導致走了很多彎路。

程序=數據結構+算法
首先搞清楚程序中的數據結構有哪些,數據的組織形式是怎樣的
然後搞清楚程序使用了哪些運算,以及哪些數學模型和算法

如果你方便調試的話,最好就是在調試過程中進行閱讀。在你想要重點閱讀的地方加上斷點,然後進行調試。在調試過程中可以清晰看到調用過程以及變量的變化。不過你最好應該先對整個程序有一個大體瞭解,不然看到調用棧(call stack)裏一堆不熟悉的方法或者函數,也夠頭大的。 如果不方便調試,比如linux內核,你可以使用一些源代碼閱讀工具。比較有名的是source insight,或者Understand for c++,它們共同的特點是通過爲函數啊變量啊建立符號存檔來快速定位瀏覽,並且支持顯示某一個函數的調用過程。總之source insight真的是一個很強大的軟件,你可以試用一下。 不過不管哪種方式,先看一下程序的總體說明,源碼的組織結構等都是很有用的事情。

首先聲明,我看到源代碼都是面嚮對象語言的。下面是我讀源代碼的方式:1 從這個軟件最核心的API開始,先使用UML裏的類圖建立靜態結構,分析出類與類之間的關係(繼承,組合,實現,依賴,關聯等等)2 使用UML裏的活動圖,配合IDE工具分析核心業務流程,理解軟件是如何工作的。3 從設計模式角度思考這個軟件爲什麼要這麼設計4 自己寫unit test來調試源代碼(這一步其實可以和1,2,3並行執行)

最好有當次閱讀目標。爲了解決/理解一個什麼問題而看源代碼(也可以在記事本上寫下問題列表)。一次一個問題,目標明確,不容易暈菜。當次閱讀所遇到代碼的數據結構(接口/數據類),有時間的話可以理清楚。一張大紙,一支多色筆,草圖。理解源代碼就像是理解一幫子有性格的人,代碼沒有完美的,不要老想着爲了理解而去修改既有代碼,理解是理解,重構是重構,兩碼事兒。
遇到“大”、“長”、“亂”的方法,不要煩躁,可以嘗試先找這個方法的輸入輸出,然後從輸出往前,尋找重點代碼,一步步分析。

下載源代碼,建工程編譯,讀系統的概要涉及,大體瞭解各模塊的功能。
從單元測試入手, 可以幫助你更快掌握代碼。

閱讀源碼 對於可直接編譯調試的代碼 更改 添加log 編譯 運行看效果 是最佳途徑對於代碼框架 前人的文檔也是不錯的參考 若沒有 那麼各個IDE的call tree生成功能也是很方便的.對於邏輯冗雜的代碼 代碼摺疊功能也是分析利器中文註釋也是方便記憶回溯整合的利器 便於統籌理解 可惜的是公司大部分要求英文註釋

先找到軟件功能需求,也就是這個軟件包是幹什麼的,然後找到合適的IDE,編譯查看效果。最後就是從主函數開始一點一點往下看了唄,遇到封裝的函數語句就看進去怎麼實現的。

工具

  1. Source Insight
  2. Understand

參考資料:
https://www.zhihu.com/question/37240878
https://www.cnblogs.com/ToDoToTry/archive/2009/06/21/1507760.html
https://www.codedump.info/post/20190324-how-to-read-code/

部署
https://www.jianshu.com/p/de61298316b2

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章