如何查看大型工程的源代碼?

我現在拿到了一個開源項目的源代碼,大概有幾十萬行的C。短期來說,我需要對這些代碼有一個初步的了解,以和另一個同等兩級的閉源項目進行對比,然後做出選擇。長期來說,我需要以這份代碼為基礎,重構其中的一部分部件。所以我需要查看源代碼,來對這個項目有一些了解。

作為一個新手,請問如何上手查看這樣的大規模代碼?有什麼工具或者教程可推薦沒?


這裡有一篇非常好的源碼閱讀教程,分享給題主。

程序員在工作過程中,會遇到很多需要閱讀源碼的場景,比如技術預研、選擇技術框架、接手以前的項目、review他人的代碼、維護老產品等等。可以說,閱讀源代碼是程序員的基本功,這項基本功是否紮實,會在很大程度上影響一個程序員在技術上的成長速度。

2014年寫《Qt on Android核心編程》和《Qt Quick核心編程》時,很多內容都是通過分析Qt源碼搞明白的。這陣子研究CEF和PPAPI,也主要靠研究源代碼來搞明白用法。最近工作上要修改已有項目的一個子系統,也是得硬著頭皮先讀懂代碼。

總之在開發工作這十來年中,讀過太多源碼了,從源代碼中學習到太多東西了,如果不閱讀源代碼,真不知道自己能否成長起來。

寫代碼是從模仿開始的,提高也是從觀摩別人的優秀設計和代碼開始的。所以閱讀源碼至關重要,接下來咱從下列方面聊聊閱讀源碼的事兒。

  • 目的
  • 工具
  • 知識準備
  • 運行與開發環境
  • 筆記
  • 實用技巧
  • 心理調試(散步在各個環節)

目的

當我們閱讀面前的源碼時,無非有以下幾種目的:

  • 純粹學習
  • 添加新功能
  • 重構舊代碼
  • 修復他人的Bug

不同的目的會有不同的心情,會影響到工作的進展,像修復他人的Bug這種事情,類似於沒被掰彎的男猿捏著鼻子給另外一個男人擦屁股,是很噁心的,很容易讓人拒絕的。所以因這種目標而閱讀源碼,往往是欲拒還迎、欲說還休,效率較低。然而修復實際工作中幫別人修復Bug這種情形,十有八九你要遇到,無可逃避。所以,心理調試很重要。

為了學習去讀源碼,這是最愉快的最放鬆的。不過提醒一點,設定可檢驗的目標才會有收穫,否則就會像走到大街上看見一美女擦肩而過那樣,驚艷一下下,過後嘛關係嘛收穫也沒了。

其他的目的,重構舊代碼、添加新功能,比幫別人擦溝子(陝西話,屁股)略強,因為他帶有創造性,創造性的活動能給人帶來強烈的愉悅,所以雖然這兩種目的也有很多讓人不爽的部分,不過想到我可以讓一棵老樹煥發青春,不爽也就慢慢弱下去了。

工具

工欲善其事必先利其器,這是亘古不變的道理。要很好的完成閱讀源碼的任務,我們大概需要下列這些工具:

  • SourceInsight,最好的源碼瀏覽工具,它能維護符號庫,動態顯示上下文,還能繪製調用關係圖,最好的,沒有之一
  • 紙質筆記本,隨時記錄心得和疑惑,隨時繪製各種圖(類圖、時序圖、框圖),比UML工具快,也比Visio快
  • 中性筆
  • 記事本、Notepad++、有道雲筆記、為知筆記等,記錄閱讀源碼過程中的關鍵點、心得體會、分析過程
  • Visio,用於繪製簡單的框圖,表述源碼的模塊劃分、層次結構等
  • StartUML,用於最後繪製類圖、時序圖等,方便交流
  • 掃描全能王(CamScanner),一款可以通過拍照達到掃描效果的App,可以用它掃描你在紙質筆記本上寫下的文字,繪製的框圖,分享給其他人,如果你懶得用軟體繪製圖標,那手繪之後掃描成電子檔就最適合你了

知識準備

前戲很重要,準備好了後面水到渠成快感不斷,否則就會頻頻受挫直感道阻且長。

  • 業務基礎,每一份有實際意義的源碼都離不開業務,必須先對業務有概念
  • 技術基礎,這個源碼用什麼語言,什麼框架,什麼第三方模塊,都需要先有所了解
  • 文檔,盡量找到業務、需求、概要、詳細等文檔,幫助會很大,然而,我們經常面臨的情況是,只有源碼,只有源碼,只有源碼,片言隻字的文檔也無,所以只好堅信——源碼是最好的文檔。這個心理門檻兒其實也容易過,你就想像著源碼只是神仙姐姐的畫像,看再多畫像也不抵當面一眼效果強大——要麼摧毀三觀要麼魂牽夢縈
  • 人,搞明白哪個程序員維護過這份代碼,方便後面不懂時請教,有時人家點一下頂你自己瞎琢磨一天

運行與開發環境

  • 配置好開發環境,目的是為了調試,對有些程序員來講,調試是弄明白軟體內部機理的最好方法,按著F5、F10、F11、F9,一切都搞定了
  • 配置好運行環境,為使用軟體、體驗軟體做準備,從用戶角度,從外面看看軟體到底是怎麼回事,便於揣摩內部邏輯

筆記

在閱讀源碼的過程中,做筆記是必須的。我有這樣的體會,因為代碼不是自己寫的,很難很快在腦子裡刻下印記,經常是看著這裡忘了那裡,早上覺得弄懂了數據流向,中午吃個飯就忘了。所以,筆記就顯得尤為重要。

  • 找到適合你的記錄方式,小本本、軟體皆可。用軟體(Notepad++、有道筆記、為知筆記等)來記錄有個壞處——必須切換屏幕,會在形式上中斷代碼閱讀過程。所以我經常在緊張得不能中斷時隨手用筆寫些斷句殘章在本子上,告一段落時梳理下用軟體再記錄。
  • 儘可能詳細的記錄,但不必看到什麼記錄什麼,要間隔性的記錄,比如弄明白了某個子模塊的邏輯、某個類的作用、某些函數的調用關係時再記錄,否則記錄這個動作本身會打斷思考
  • 每天工作結束,記錄進度(弄明白的部分),記錄疑問,記錄第二天要弄明白什麼東西,這樣你的工作狀態就入棧了,第二天來了很容易出棧,快速進入工作狀態
  • 記錄看到的優秀設計,提高審美,見賢思齊,自我成長

滄海遺珠

我在漫長的讀碼生涯里積攢了一些的經驗,算是碎碎念,供參考:

  • 理清某一業務如何映射在代碼執行流程上的,這點很關鍵。
  • 理清不同模塊間的業務關係,代碼調用關係,很關鍵
  • 調試是弄明白代碼調用流程的最快方式,之一
  • 找出關鍵代碼(代表實際對象的類、銜接不同模塊的類、代表業務關鍵節點的類)
  • 分析日誌可以幫助分析代碼執行流程和業務流程
  • 先用已有的可運行軟體,體驗業務,琢磨你點這裡一下點那裡一下代碼可能是怎麼做出反應的
  • 閱讀應該圍繞目的,把實現目標放在第一位,比如修改Bug,如果有期限,在最後日期前搞定是第一要務,然後有時間就繼續讀源碼或改進Bug修復方案,力求沒有副作用和後遺症,再有時間就修修別人留下的破窗戶(你也可以順帶鄙視下前任維護者)
  • 千萬次的問,還記得前面說要弄明白誰維護過你要讀的代碼吧,別不好意思,問吧,問吧,問吧
  • 對著設計文檔、介面文檔或測試用例看代碼
  • 心理調試,勿畏難,別放棄。我有時看代碼,看兩天也不知道看了個甚,一頭霧水兩眼發花是常有的事兒,有時真是覺得搞不定了,然而,這要麼是你基礎知識沒準備好,要麼是你找錯了入口,要知道,任何一份代碼,都有一條隱形的線串著,耐心點,總會找到。這樣不行就那樣,多換換角度,多換換方法,讀不行,就調試,調試不行,就運行,運行不行,就研究日誌,都不行,我靠,while(!i.isDead())i.analyzeCode(),跟Y死磕!總之,你不放棄自己,就沒人能放棄你!
  • 給自己設置小獎勵,弄明白某個邏輯或某個模塊的代碼後獎勵自己休息一下,5~10分鐘,走出辦公室轉轉,或者乾脆在網上瞎逛一下,瀏覽自己喜歡的網站
  • 讀不懂才要讀,想不明白才要想,這是進步和成長的開始。那些阻擋你的蹂躪你的而殺又不死你的,終將幫助你成長讓你變得更強大。

你想更深入了解學習Linux知識體系,你可以看一下我們花費了一個多月整理了上百小時的幾百個知識點體系內容:

【超全整理】《Linux雲計算從入門到精通》系列實戰筆記全放送


先看readme和以及其他文檔,快速了解結構。

幾十萬行的開源軟體很可能都已經有人寫了源碼分析的文章書籍。

再者,人家代碼都開源了,題主連軟體的名字都不肯說啊


謝邀

先編譯,然後用調試器


首先樓主放心,幾十萬行的項目不算大,幾個核心的點通了以後就會發現好多代碼沒必要讀。

注意兩個方法結合著用:

1)找到入口,順序的看;

2)順序地看沒法進行時(比如多進程並發之類的代碼),要會全局搜關鍵字

最好能跑起來,這樣你就可以列印出些信息(或者調試器查看),人腦容量就這麼大,單靠走碼會腎虛的。。。


不得不提Visual Studio的CodeMap功能了。


1.首先可以推薦一本書, code reading (Jolt大獎精選叢書:代碼閱讀(附光碟1張))

2.我自己的習慣。

搭一個相應的開發環境,編譯一下整個項目。

開始找程序入口main, index..........

大概猜測一下整個程序架構。

仔細查看每一個獨立部分。

償試修改或者說加入自己的一些代碼。

BYW:有時測試代碼會給你提供額外的驚喜。


試試source insight


1.看Makefile,有時候Makeifle寫得比較蛋疼,就加列印,就能看到工程結構。

2.看頭文件,頭文件有什麼數據結構和介面,如果對業務邏輯熟大概能理解其代碼設計。

3.加列印,看具體業務邏輯,以調用鏈分析。其實可以先gcc -pg,然後看gprof的輸出的。

4.看源碼,了解細節部分。


你的知識有限,所以從你感興趣的地方看比較好,最重要的是別放棄


看這樣子應該是開源項目的二次開發吧。正好我最近在做,說一下一些心得。

1 搭建編譯,運行,調試環境。可能需要安裝虛擬機,安裝相應的系統。就是要達到能編譯,能運行的效果。

2 搭建開發環境。推薦linux smb +windows sourceinsight,具體方法請自己搜索,這樣的話開發環境搞定了,閱讀代碼也方便了。vim難度有點大,暫時還是在win上soureinsight吧。

3 找程序入口,不進子進程和具體函數,看整體流程。備份代碼,然後開始按照自己想法在整體上修改。

4 掌握整體流程以後,進入需要的進程代碼,修改細節代碼。

備註:能運行起來,敢修改,知道怎麼調試,有基礎,有想像力,就搞定了。

提醒:不要在一個點死摳,更重要的是整體流程。除非是你要修改的地方,要不然死摳無益。


對於想在GitHub上一些很好的項目,無論你出於什麼目的,讀懂它是非常有好處的,你可以看到優秀的代碼是怎麼寫出的,你也可以深入理解一些理論知識,所以讀懂它是很必要的。

至於怎麼讀懂,最直接的辦法就是根據使用實例輸出結果,然後一步一步列印輸出中間值,這樣就事半功倍,你把所有的實例都輸出一遍,你對代碼也理解差不多了。注意,在代碼中用注釋的方法記錄一些中間變數的值是很重要的,因為下次在看的時候也許你會忘記。

對於工作中具體遇到的源代碼或者在GitHub上沒有足夠好的實例的代碼,那就盡量按照軟體理論中的輸入,處理,輸出過程閱讀,看整個代碼有什麼輸入,是怎麼樣處理的,最後得到什麼結果。個人認為只要你找到了輸入,你把輸入里清楚了,你閱讀源代碼的工作就完成了65%。讀了很多源代碼,輸入找到了以後想要讀懂就是時間問題了。


有的用doxygen的,能生成代碼索引和注釋。

從入口開始,對你需要關注的模塊和相關模塊進行閱讀。必要進行跟蹤深入了解流程


推薦閱讀:

既然編譯器是一個軟體,那它是如何編譯自己的?
覺得自己程序寫得很差不敢寫了怎麼辦?
未來想從事Linux 後台開發,需要學習linux內核嗎?像讀內核源碼。還是學好linux網路編程,C,演算法。學習內核的意義有哪些呢?
c語言未來的前景(比如就業)是怎麼樣的?
C語言怎麼寫窗口化程序?

TAG:程序員 | Linux | C編程語言 | 開源 | 圖形處理器GPU |