我用笨辦法啃下了一個開源項目的源碼!
前言
這篇文章,給大家簡單介紹一下很多同學(xué)都非常關(guān)心的一個問題:如何閱讀一個開源項目的源碼。
我相信很多同學(xué)都希望能夠去閱讀一些源碼來提升自己的技術(shù)水平,畢竟在面試的時候,很多大廠都經(jīng)常會扣到非常深入的底層源碼。
1、從最簡單的源碼開始:別幻想一步登天
其實開源項目有很多種,比如說有Spring這種框架類的,還有比如數(shù)據(jù)庫連接池、log4j等這種工具類的。
當(dāng)然還有特別重型的中間件類的,比如說RocketMQ、Kafka、Redis。更有甚者也有上百萬行代碼的大數(shù)據(jù)類的,比如Hadoop、Spark。
所以如果很多同學(xué)想要讀源碼的話,面臨的第一個問題:不知道從何下手。
那么是不是說只要隨便挑選一個開源技術(shù)的源碼,采用愚公移山的精神,直接硬著頭皮去讀,堅持就是勝利,鐵杵一定就能磨成針嗎?
不是的!其實很多同學(xué)始終都沒掌握到閱讀源碼的順序、技巧和方法,所以導(dǎo)致嘗試看過一些源碼,卻還是看不懂。
首先你要明白一個前提,比如說Kafka的作者,Hadoop的作者,他們本身都是有很多年經(jīng)驗,技術(shù)功底極為扎實,都是技術(shù)大牛的人,站在一個很高的角度去設(shè)計和開發(fā)出來了這些極為出色的分布式系統(tǒng)。
那么如果你的技術(shù)實力達不到他們的水平,你覺得你直接去讀他們寫出來的源碼,就能看懂嗎?
那估計是很難的,因為里面蘊含的各種底層技術(shù)細節(jié),分布式架構(gòu)設(shè)計思想,還有復(fù)雜的算法和機制,都不是你能理解的。
所以建議大家第一點,想看源碼,先挑一個最最簡單的,適合自己技術(shù)水平的去看。
給大家舉個例子,比如說你平時常用的一些源碼都有什么?顯而易見,每個人都會用Spring Web MVC、Spring、MyBatis、Spring Boot,等等。
其實這些開源框架的源碼也不能說就簡單了,他們同樣蘊含了開源作者深厚的技術(shù)功底在里面。
但是你要考慮一點,這些開源項目已經(jīng)相對來說是普通人可以優(yōu)先觸碰的了。因為他們不是分布式系統(tǒng),不涉及到復(fù)雜的架構(gòu),網(wǎng)絡(luò)通信,IO,等技術(shù)細節(jié)。
他們大多就是依賴一些底層的Java基礎(chǔ)技術(shù),比如說動態(tài)代理、Servlet、HTTP協(xié)議、JDBC等等。
而他們依賴的那些基礎(chǔ),大多數(shù)普通工程師都是掌握的,你完全可以優(yōu)先嘗試去閱讀一些這種開源框架類的源碼。
2、循序漸進:先搞定底層依賴的技術(shù)
好,現(xiàn)在假如說你經(jīng)過了幾個月的努力,把一些開源框架的源碼,比如上面說的SSM三大框架的源碼都看過了,現(xiàn)在你的技術(shù)實力有了進一步的提升。
這些提升,主要體現(xiàn)在對開源項目的設(shè)計思想,組件設(shè)計,組件交互,還有框架封裝,等等,都有了進一步的理解。
接下來,你就可以嘗試去讀一些更難一點的源碼。
給大家舉個例子,假設(shè)你這個時候去閱讀Kafka的源碼。沒問題。但是這里有一些是你需要注意的地方,Kafka的底層是重度依賴ZooKeeper的。
如果你不把ZooKeeper給掌握精通的話,會導(dǎo)致Kafka你也難以理解。
所以這個時候你得先把底層依賴的技術(shù)給搞定,那么你就得回過頭去先閱讀ZooKeeper的源碼,把ZK這個技術(shù)先給搞精通一些。
同理,如果你在研究ZK的時候,發(fā)現(xiàn)他底層有一些技術(shù)是你掌握不好的,比如你發(fā)現(xiàn)他大量運用了Java并發(fā)包下的東西。
因此如果你對Java并發(fā)包掌握的不夠好,那么建議你去把Java并發(fā)包下的源碼先仔細研究一下。
通過這種方式,你可以自行追蹤到自己還不熟悉的很多底層技術(shù),然后一個一個擊破,把這些底層依賴的技術(shù)的源碼你可以先研究透徹一些。
然后,你再一步一步往上層的技術(shù)去研究,這樣看那些復(fù)雜技術(shù)的源碼就會輕松很多了。
3、一定要以Hello World作為入口來閱讀
閱讀源碼有一個非常非常有用的技巧,那就是你別下載了源碼到本地IDE里然后直接胡亂的翻看,那是不行的。
一般建議就是基于一個開源技術(shù)寫一個最最基本的HelloWorld程序,就是一個入門級的程序,然后把他的核心功能給跑通。
舉個例子,假如說你要閱讀ZooKeeper的源碼,那么你先寫一個ZK的HelloWorld程序。
比如說先連接,然后創(chuàng)建一個znode,對znode注冊一個監(jiān)聽。接著觸發(fā)這個監(jiān)聽,接著再關(guān)閉連接,就這樣的一個簡單的程序。
然后就可以打斷點,跟蹤這個Hello World級別的源碼一步一步調(diào)試追蹤,他是如何發(fā)起和建立連接的,底層的代碼流程是什么樣的。
4、抓大放小,邊寫注釋邊畫圖
在看源碼的過程中,很多人會被核心流程中混雜的一些特殊業(yè)務(wù)邏輯的處理給搞懵。
給大家舉個例子,看下面的代碼,是一段隨手寫出來演示的:
checkUser();
fetchFromPeers();
countMetrics();
大家可以看到,上面就三行代碼,從方法名稱就可以看出來,先是做了一個權(quán)限檢查之類的操作,然后是核心業(yè)務(wù)邏輯去抓取數(shù)據(jù),最后是做了一些metric指標(biāo)統(tǒng)計。
那么很多同學(xué)看源碼的時候,就喜歡把每一行代碼都看懂,最后不停的點到很深層的地方去,把自己給繞暈了。最后淹死在源碼的海洋里。。。
其實這個是不對的,這就是沒有掌握源碼閱讀的一大典型原則:
抓大放小。
比如上面的三行代碼,你應(yīng)該直接跳過第一行和第三行,連看都別去看,直接進入第二行核心邏輯。
也就是說,你只需要抓最核心的代碼流程就可以了,那些無關(guān)緊要的代碼,千萬別有強迫癥點進去反復(fù)看,那樣絕對會讓你對源碼從入門到放棄。
所以,再次強調(diào)!強調(diào)!強調(diào)!重要的事情說三遍。閱讀源碼,你一定要有粗大的神經(jīng),反復(fù)告訴自己,剛開始先把握代碼的主流程即可。
很多細節(jié)看不懂直接跳過去,別有強迫癥讓自己看明白每個細節(jié)。
此外,大家一定要形成一個習(xí)慣,在看源碼的過程中盡量多自己對源碼寫一些注釋。
你應(yīng)該結(jié)合自己的理解,盡可能把自己對源碼閱讀過程中的思考都寫成注釋寫在源碼里。
這個習(xí)慣可以促使你一邊閱讀一邊思考,而且有自己注釋的源碼,是你寶貴的財富。
此外,還有一個非常重要的點,那就是一定要多畫圖。
你可以嘗試在閱讀的過程中,提取源碼運行的核心流程,一邊讀源碼,一邊自己畫在圖上,可以用那種畫圖軟件來作圖即可。
大家記住,人腦對圖片的敏感度,是遠高于對文字或者代碼的,這個是大腦機制決定的。
筆者公眾號寫的很多篇文章,里面對各種技術(shù)的講解,無一不是通過大量的畫圖。相比于冗長的文字描述,圖片會讓人容易理解接受的多。
通過畫圖,能幫助你抽象和總結(jié)出源碼的核心流程,以后如果你要回顧和復(fù)習(xí),直接看圖即可。
5、反復(fù)三遍:真正理解源碼
另外一個要注意的點,源碼這個東西,是多看幾遍理解的就會越深刻。
因為你看第一遍,按照上面說的抓大放小的思路,可能很多東西就直接略過去了,因為剛開始你看不懂一些非核心代碼在干什么。
但是第一遍看完以后,通過寫注釋,自己動手畫圖,對一個開源項目的核心流程、架構(gòu)以及原理都有了一定的理解了。
此時再去讀第二遍源碼,再過一遍,你會發(fā)現(xiàn)之前很多看不懂的細節(jié)都能看懂了。然后再看第三遍源碼,你會發(fā)現(xiàn)大多數(shù)的代碼自己都能看懂了。
所以說任何一個源碼,都是要至少反復(fù)看三遍的過程,不是看一遍就可以完成的。
6、借力打力:參考源碼分析書籍及博客
其實現(xiàn)在有很多對熱門開源項目進行源碼分析的書籍以及博客,你大致可以認為就是一些技術(shù)比較牛的兄弟自己看了源碼之后,寫出來的一些分析和感悟。
但是那畢竟是別人的東西,如果你上來就直接看源碼分析書籍或者博客,那么不一定可以看懂,因為文字的信息傳遞未必能很好的讓你理解有些復(fù)雜的東西。
所以比較建議的方式,就是先自己嘗試看幾遍,有了一定的理解之后,此時可以借助源碼分析書籍或者是博客,參考其他技術(shù)牛的同學(xué)對這個源碼理解,結(jié)合自己之前的一些思考,綜合起來進行分析,相信一定會大有裨益。
你會發(fā)現(xiàn)人家的一些理解可以很好的補充你沒想明白的一些問題,或者是忽略的一些細節(jié)。
不過,需要提醒的一點,網(wǎng)上不少博客,包括一些書籍,他們寫出的一些源碼分析,可能是錯誤的。
所以,盡信書不如無書,你需要帶著一定的糾錯眼光。在和你的理解相悖時,不一定就是你錯了。
7、最后寄語:用幾年時間鍛造自己的核心技術(shù)
其實上面那個過程說起來很簡單,做起來非常的困難。
因為在上面任何一個步驟,閱讀的過程中你都有大量的東西是不會的,而且會覺得很難,甚至經(jīng)常有想放棄的沖動。
畢竟人的大腦天生就是會對困難的事情產(chǎn)生抗拒感,這是本能,天生就是對舒服、放松的事情有向往。
但是只有那些能克服人的動物本能,惰性本能,迎難而上,堅韌不拔的同學(xué),才能真正攻克各種技術(shù)難題。
讓自己的大腦不停的開動,不停的思考上面那個過程,也許你要持續(xù)一年才能有個小的開悟,持續(xù)三年才能有一定的心得,持續(xù)五年甚至八年,才能說真的融匯貫通,打通任督二脈,成為技術(shù)大牛。
但是堅持這個事情同樣是很可怕的,一旦你堅持做到了,那么你將鍛造出來自己最硬核的技術(shù)實力,遠遠不是普通人,或者剛畢業(yè)的年輕同學(xué)可以追上你的。技術(shù)深度、技術(shù)功底,這是每一個工程師最最硬核的技術(shù)實力。
希望各位同學(xué)可以從現(xiàn)在開始,嘗試著用筆者分享的技巧閱讀源碼。跳出舒適區(qū),去擁抱更大的舒適區(qū)。
真正體驗一下讀透源碼之后,根據(jù)報錯日志,從源碼層面精確定位項目問題、精確制導(dǎo)線上bug,感受一下這種上帝視角解決問題的快感吧!