文章出處:http://blogread.cn/it/article/4349?f=wb#originalphp
1. 前言java
不少人問我如何看源代碼?是否是我在看源代碼這方面特別有天賦?mysql
其實不是的,我也只是個普通人,跟大夥沒啥分別,sql
只不過我沒有別的特別愛好,一有空時,不是寫本身的代碼就是看別人的代碼,服務器
我在看源代碼時比較有耐心,純粹就是興趣驅動,或者說是一種好奇心。數據結構
固然,我不會隨隨便便拿起一個開源項目就看,而是通過必定了解後才決定看它的源代碼的,架構
一旦決定要看了,我至少要把這個開源項目80%以上的代碼看完,並非那種膚淺的看,eclipse
而是仔細研究每一行代碼。佈局
2. 我看過這些開源項目post
按時間前後順序:
2007:
OpenJDK Javac1.7
2008:
Erlang編譯器 (看得最少的一個,只看了一半源代碼)
2009:
Tomcat6
Junit4
Ibatis2.3
OSCache2.4
Ehcache1.6
Mongodb-mongo-java-driver1.2
Velocity1.6
2010:
MySQL JDBC Driver (mysql-connector-java-5.1.13)
PostgreSQL JDBC Driver (postgresql-jdbc-8.4-701)
Netty3.2
Tomcat7
2011:
Jetty8
目前主要關注這4個:
OpenJDK Javac1.7
Netty4.0
Tomcat7
Jetty8
我如今每隔1到7天就會看這4個開源項目的源代碼庫中有沒有更新,
我裝了TortoiseHg, TortoiseGit, TortoiseSVN,
由於看Javac1.7的源代碼更新用TortoiseHg比較方便,
而看Netty4.0要用TortoiseGit,最後二者用TortoiseSVN。
3. 我對看源代碼的人進行了分類
分5種人:
1) 解決問題型
這種類型的人一般是在工做學習中碰到了一個很費解或很棘手的問題,
文檔也看了,google也找了,同事、同窗也問過了,
可是問題仍是沒法解決,因而不得不把源代碼下下來,而後一邊看一邊debug,直到問題解決。
2) 三分鐘熱度型
多是看到別人也在看或者在論壇上看到某些人說XXX設計得很好,性能也不錯,或者看到某些人在論壇上發了些分析源代碼的文章,
再加上本身一開始也興趣滿滿,而後也跟風了,看了10來個類的代碼,啊,發現太痛苦,方法之間調來調去的,太繞了,頭快炸了,
給本身找個理由,這代碼寫得太垃圾了,媽的,不看了。
3) 只知其一;不知其二型
網上常常看到有人在寫分析源代碼的文章,一上來就是一陀陀的源代碼,而後告訴你這作了什麼,那作了什麼,
就加了點中文註釋,有時這中文註釋還不如源代碼中的英文註釋好理解,而後過了一段時間,發現文章不更新了,也沒有後續了。
4) 真才實學型
像原做者同樣思考,能輕鬆說出此開源項目的核心架構,精確理解80%以上的源代碼,能找出bug並能提交相應patch,
5) 創新型
對此開源項目的優缺點了然於心,可以提取其精華爲我所用,想出更好的方案解決現有問題,超越原做者。
4. 我看源代碼的經驗
僅供參考,不要隨意模仿,每一個人都應該找到適合本身的方式,
惟一重要的是如下3點:
1) 時間
最好能有一大段時間集中精力去看,好比你要看Tomcat7,要有3個月的時間天天花3到8小時去不停的看,
時間拖拉得越久,會看了前面忘了後面。
2) 興趣
看代碼不要有任何功利性,你要對它有興趣,充滿好奇心,去理解它作了什麼,怎麼作的。
3) 耐心
這一點提及來容易,真正要作到是極其困難的,好比當你某些類連看了三次時還看不懂,不要先想別人寫的代碼是否垃圾,
先想一想你在這方面的背景知識是否足夠,好比在看Tomcat實現http協議相關的代碼時,一邊看代碼一邊看http協議是最有效的方式,
再好比你想看編譯器相關的代碼,最起碼在看以前,你要對<<編譯原理>>這門課中的內容有基本的瞭解。
若是背景知識有了還看不懂怎麼辦,看不懂的代碼先放下,有些if分支只有你把整個項目都大體瞭解了一下後才能理解的,
要反覆的看,看三次僅僅是個入門級別。
先簡單說一下個人經歷:
小學到初中我還算是個好學生,在班裏常常拿第一,
可是從小學6年級到初三這4年比較特殊,遇到了一個很垃圾很垃圾很垃圾的數學老師,
因此這4年個人數學基本上就是自學的了,個人自學能力從小到如今都是很是的強。
固然,這不能歸功於這位垃圾老師,我自小就很叛逆,不喜歡這禽獸的教學方式,沒有此垃圾,也許個人生活會是另外一番景色。
我不像正常人那樣上完初中上高中,而後再上大學,
而是上完初中後就直接到一所師範大學上中專+自考大專,2001年就畢業了。
中專是學會計統計類的,自考大專是計算機應用,大專注共才12門課,沒有英語,數學方面只有高數,並且仍是第一冊,
核心專業課方面只有pascal、c、8086彙編語言、FoxPro、模擬電路、數據結構、操做系統、軟件工程、計算機接口與技術。
只要不是硬件類的專業課程我就學得很是好,硬件類課程就只是聽老師講,當時連硬盤長什麼樣都不知道。
我2001年畢業時才19歲,而後就出來找工做了,說這些只是想說我從學校獲得的教育並很少,
如今回想起來從學校學的C語言、彙編語言、數據結構、操做系統爲我之後的自學提供了一些幫助。
直到2006年,我辭職了,以前我己經工做了4年,都只是作應用軟件項目,
因此數學基本上沒用過,英語也用得少之又少,英語其實比如今的高中生水平還差,
因此要看英文的技術文章也是看不懂的。
2006年我原本是要複習考研究生的,我從3月份開始連背了三個月的英語,天天花4到8小時背新概念英語的課文,
1、二冊所有背完,第三冊背了前42課,第四冊背了前10課,我覺得這樣的水平足夠應付考研英語了,結果拿試卷一作,
閱讀理解至少有2/5的單詞認不得,不得不去背考研英語的單詞。
數學基本上忘光了,到網上下初中和高中的新課標課本下來看,
高數、線性代數、概論全都自學,還買了相關的數學書來看(像幾何、離散數學等等)。
每天作那些垃圾數學題,還要背馬哲、毛概,專業課卻是小兒科。
一直到10月份,各校出來招生簡章了,想報10大高校,結果別人不鳥你專科生,你專科生沒有報名資格,
好吧,換二線的能夠了吧,結果仍是差很少,不是要本科,就是要發表啥論文才能報,
最後,很不情願的報了個很平庸的所謂211大學。
此後愈加以爲每天作題背單詞背書實在是件極其無聊的事,再加上報考這件事,嚴重打擊積極性,一直想放棄考研可是又一直堅持着,
直到11月23日,那天去書店看書,翻到一本講編譯器實現的書,
也就是所謂的"虎書",當時並不知道編譯器是什麼,由於我在學校時沒學過編譯原理,在書店連看了一小時,以爲頗有趣,
就買了回來,接着就把考研的書全丟到一個角落裏了。
接下來你應該懂的,我瘋狂的買書,"龍書","鯨書"啥的我都買了,只要是有關編譯器的,無論是國內仍是國外我都買,
由於我並非一看就全懂的,也是由於"虎書"剛開始一兩章還好理解,後面的我當時就看不懂了,
我有個習慣,就是實在看不懂的書,我就會換一本,確認一下是我本身的緣由仍是書自己的問題,
如今我只會說"虎書"翻譯得並很差,"龍書"更好理解,固然一開始就看"龍書"也並非那麼好理解,
因此我當時甚至連形式語言和自動機相關的書我都買來看了。
我連看了3個多月,當時以爲看書不過癮,就想找個實際的編譯器來玩,
我下了GCC和LCC,當時恰好sun公司又把javac開源了。
由於工做中只用到php和java,c語言已經4年沒用過了,加上javac比前二者要小不少,
因此從2007年二月份開始第一次看javac的源代碼,也是第一次看別人的源代碼。
javac的源代碼很少,8萬行都不到,花了我3個月的時間,平均天天至少花7小時看代碼。
由於我當時只會java1.4,java1.5以後出來的不少東西都不懂,因此也是一邊看javac的源代碼一邊學新語法。
2007年5月份時我還在JavaEye上發了第一篇有關javac的文章,得了個精華,引發了一點小轟動,
這裏有證據: http://www.iteye.com/topic/84833
內容貌似當年被我刪除了,想不起來是什麼緣由了,zhh2007就是我本人之前的id。
當時看代碼的方法是很是原始的,可是直到如今我還在用這種方法,只不過如今有時會用eclipse來看,
我是這麼作的:
看原代碼用 EditPlus,
找到第一個入口類: com\\sun\\tools\\javac\\Main
本身再寫一個Debug類,按執行流程看到一個方法時,就加入相似下面的代碼塊:
public static int compile(String[] args) { try {//我加上的 DEBUG.P(Main.class,"compile(1)"); DEBUG.PA("args", args); com.sun.tools.javac.main.Main compiler = new com.sun.tools.javac.main.Main("javac"); return compiler.compile(args); }finally{//我加上的 DEBUG.P(0,Main.class,"compile(1)"); } }
而後必定要重編譯源代碼,再運行,保證本身加的代碼被執行到了,我會把輸出的debug結果重定向到一個文件中,
而後一邊看源代碼一邊看輸出結果,一些變量或表達式本身想看結果也會加DEBUG.P(...),
碰到一些代碼行數不少的類,我甚至會把每一個方法copy出來放到一個新的java文件中,
而後打開多個EditPlus,每一個EditPlus看一個方法,並且是按照方法的調用順序打開EditPlus看的。
可能看到這不少人會以爲這種方式好土,我也不能說好很差,從今年開始,由於個人電腦裝了Eclipse了,
因此Jetty8的源代碼我是用Eclipse看的,也再也不打DEBUG輸出,也再也不copy方法,而是直接用eclipse的debug跟蹤功能,
可是我如今提出質疑了,Jetty8的代碼量只是Tomcat6的1/3,我用Eclipse這種方式來研究源代碼並不能節省個人總時間,
我用最原始的方式研究Tomcat6也只花了3個月,如今研究Jetty8已經用了我兩個月的時間,並且看Tomcat6和Jetty8是兩個相似的東西,
按理說先看Tomcat6後看Jetty8應該花的時間更少纔對。
我總結了一下,爲何最初的方式好,那是由於我那樣不斷折騰源代碼的過程當中已經間接讓我記住了代碼的佈局,
我在敲那些重複的DEBUG.P代碼時我把局部變量、表達式、字段都輸出了一次,這有助於個人記憶。
而Eclipse的debug功能只是在不停的按F5-F6-F7-F8,打斷點,方法調用太深時很難理清先後關係,
有時看了一星期,連哪一個類在哪一個目錄都不知道,由於debug時,跟到相關的類eclipse會自動打開那個類,不用你從目錄中找。
Eclipse的代碼摺疊粒度又不能摺疊到塊級別,不能摺疊if、while,一旦方法的行數不少,看起來會很累,分不清這個方法的層次結構,
而EditPlus在看方法時就看得很舒服,由於他能摺疊if、while,看完了一個while我能夠把他摺疊起來,
有多個if-else時只要摺疊一下就不會超過一屏。
你能打開20個EditPlus,可是你不能同時打開10個Eclipse,除非你電腦的內存牛X到不行。
有一點很重要,無論是哪種方式,必定要把環境搭建好,你自已要可以編譯源代碼,而且多寫些例子去驗證源代碼中的執行流程,
我通常不會去看源有代碼中的例子或測試用例的,只有想不出時纔去看(特別是看編譯器時,一些用例你很難想到)。
我爲何要看這麼多源代碼?
除了我的興趣以外,如今想起來其實還有個很可笑的緣由:
2007下半年和2008一全年,這段時間不少人說Java快死了,Ruby/Rails、Erlang很火,
我常常上JavaEye,免不了也受影響,因此在2008年時還學習了Ruby/Rails、Erlang,連Erlang的編譯器都玩了一下,
以後發現並非那樣滴,只不過是一些大佬在鼓吹而已,再加上2008年家裏出了點事,因此過得很鬱悶,
一有閒情就跟JavaEye的大佬們"打架",想來也是種樂趣,算是種排解壓力的方式。
固然,與此同時,也會從技術的角度思考Java出了什麼問題,因此從2009年開始就專心研究技術了,還把douyu的原型鼓搗出來了。
2009年研究的那些開源項目其實都是很順其天然的事,我要作一個http服務器,Tomcat已經作好了,我想知道他怎麼作的,
我就去看,看這些項目就是爲了想知道他們作了什麼,怎麼作的,哪裏作得很差,我能不能比他們作得更好。
如今,看代碼已是個人一種習慣了,從畢業那年到2008年我買了幾萬塊錢的書,以致於我來杭州後都沒有把桂林的房子退了,
由於書多,桂林那房子除了回去能住個幾天外,如今是租給書住的了。
從2009年到如今,兩年多時間我沒有再買書,都是看源代碼學新東西,
若是是一個全新的領域,最多也就是在網上找點入門資料,而後再看源代碼,
包括下半年我準備研究HotSpot,已是C/C++的領域了,我沒有任何學習壓力,只是一個時間問題。
一我的的自我學習能力很是的重要,Java相關的和Java以外的全部東西我都是自學的,
我沒有特別問過什麼人,也沒參加過培訓,實在不懂的地方就查資料買書看。
若是看代碼看不懂,這幾點必定要明白:
1) 相關背景知識是否具有
2) 要有耐心,多看幾遍
3) 不要期望別人告訴你答案,別人沒跟你說也不要說別人高高在上不理你,由於這不是別人的義務
4) 通過對比以後再說別人的代碼爛