"沒有經(jīng)驗(yàn)的技術(shù)差底子薄的初級(jí)程序員,如何閱讀項(xiàng)目源碼? "
"有人閱讀過 mybatis 的源碼嗎 锯厢?就看一個(gè)初始化過程就看的已經(jīng)頭暈眼花了,小伙伴們支支招吧脯倒!"
"源碼應(yīng)該怎么閱讀实辑,我曾經(jīng)嘗試閱讀一些源碼,例如alibaba的druid中sqlparser部分藻丢,spring-mvc剪撬,但是發(fā)現(xiàn)很吃力,都說debug是最好的閱讀方式悠反,我在debug時(shí)經(jīng)常有跟丟的現(xiàn)象……就是走著走著感覺好像進(jìn)入了一些我當(dāng)前不太關(guān)注細(xì)枝末節(jié)残黑。 "
馍佑。。萍摊。挤茄。。冰木。
估計(jì)很多人都有這樣的疑惑穷劈。
我非常能理解小伙伴們的痛苦,因?yàn)槲乙彩沁@么痛苦著走過來的踊沸。
閱讀優(yōu)秀源碼的好處想必大家都知道歇终,學(xué)習(xí)別人優(yōu)秀的設(shè)計(jì),合理的抽象逼龟,簡潔的代碼...... 總之是好處多多评凝。
但是真的把龐大的代碼放到你的面前,就如同一個(gè)巨大的迷宮腺律,要在其中東轉(zhuǎn)西轉(zhuǎn)尋出一條路來奕短,把迷宮的整個(gè)結(jié)構(gòu)搞清楚,理解核心思想匀钧,真心不容易翎碑。
在閱讀由面向?qū)ο蟮恼Z言如Java寫的代碼時(shí),會(huì)發(fā)現(xiàn)接口和具體的實(shí)現(xiàn)經(jīng)常對(duì)應(yīng)不起來之斯,不太清楚一個(gè)功能到底是怎么在哪個(gè)實(shí)現(xiàn)類中才能找到日杈。 不像C語言,就是函數(shù)調(diào)用函數(shù)佑刷,相對(duì)還好點(diǎn)莉擒。
如果是動(dòng)態(tài)語言如Ruby,Python, 一個(gè)變量的類型甚至都不容易知道瘫絮,閱讀的難度大大增加涨冀。
還有一個(gè)重要的原因,現(xiàn)在我們看到的源碼基本上都經(jīng)過若干年發(fā)展麦萤、經(jīng)過很多人不斷地完善的蝇裤,枝枝蔓蔓非常多,魔鬼都在細(xì)節(jié)中频鉴。 閱讀的時(shí)候很容易陷進(jìn)去, 看了幾十層函數(shù)調(diào)用以后恋拍,就徹底懵了垛孔,就放棄了: 甭管你把源碼吹得天花亂墜, 老子再也不看了施敢。
經(jīng)過很多痛苦的掙扎以后周荐,我也算有一些成功的經(jīng)歷狭莱,今天用治學(xué)的三個(gè)境界來類比, 給大家分享一下:
昨夜西風(fēng)凋碧樹概作,獨(dú)上高樓腋妙,望盡天涯路
想把源碼搞懂,吃透讯榕,首先得登高望遠(yuǎn)骤素,瞰察路徑,明確目標(biāo)與方向愚屁,了解源碼的概貌济竹。
所以有些準(zhǔn)備工作必須得做。
1. 閱讀源碼之前霎槐,需要有一定的技術(shù)儲(chǔ)備送浊。
比如設(shè)計(jì)模式,在很多Java源碼中幾乎就是標(biāo)配丘跌,尤其是這幾個(gè):模板方法袭景,單例,觀察者闭树,工廠方法耸棒,代理,策略蔼啦,裝飾者榆纽。
再比如閱讀Spring源碼,肯定得先了解IoC是怎么回事捏肢,AOP的實(shí)現(xiàn)方式奈籽,CGLib,Java動(dòng)態(tài)代理等鸵赫,自己動(dòng)手衣屏,寫點(diǎn)相關(guān)的代碼,把這些知識(shí)點(diǎn)掌握了辩棒。
2. 必須得會(huì)使用這個(gè)框架/類庫狼忱, 最好是精通各種各樣的用法。
上面剛提過一睁,魔鬼都在細(xì)節(jié)中钻弄,如果有些用法根本不知道,可能你能看明白代碼是什么意思者吁,但是不知道它為什么這些寫窘俺。
3. 先去找書,找資料复凳,了解這個(gè)軟件的整體設(shè)計(jì)瘤泪。
都有哪些模塊灶泵? 模塊之間是怎么關(guān)聯(lián)的?怎么關(guān)聯(lián)的对途?
可能一下子理解不了赦邻,但是要建立一個(gè)整體的概念,就像一個(gè)地圖实檀,防止你迷航惶洲。
在讀源碼的時(shí)候可以時(shí)不時(shí)看看自己在什么地方。
4. 搭建系統(tǒng)劲妙,把源代碼跑起來湃鹊!
相信我,Debug是非常非常重要的手段镣奋, 你想通過只看而不運(yùn)行就把系統(tǒng)搞清楚币呵,那是根本不可能的!
衣帶漸寬終不悔侨颈,為伊消得人憔悴余赢。
5. 根據(jù)你對(duì)系統(tǒng)的理解,設(shè)計(jì)幾個(gè)主要的測試案例哈垢,定義好輸入妻柒,輸出。
運(yùn)行系統(tǒng)耘分,慢慢地debug 举塔,一步步地走,這是個(gè)死功夫求泰,沒有辦法繞過央渣。
Debug一遍肯定是不行的,需要Debug很多遍渴频。
第一遍盡可能拋棄細(xì)節(jié)芽丹,抓住主要流程, 比如有些看起來不重要的方法就不進(jìn)去看了卜朗。
第二遍拔第、第三遍....再去看那些細(xì)節(jié)。
一個(gè)非常重要的工作就是記筆記(又是寫作3《ぁ)蚊俺,畫出系統(tǒng)的類圖(不要依靠IDE給你生成的), 記錄下主要的函數(shù)調(diào)用逛万, 方便后續(xù)查看泳猬。
文檔工作極為重要,因?yàn)榇a太復(fù)雜,人的大腦容量也有限暂殖,記不住所有的細(xì)節(jié)。 文檔可以幫助你記住關(guān)鍵點(diǎn)当纱, 到時(shí)候可以回想起來呛每,迅速地接著往下看。
要不然坡氯,你今天看的晨横,可能到明天就忘個(gè)差不多了。
給大家看看我做的一些筆記箫柳, 格式不重要手形,很隨意,方便自己看懂就行悯恍。
- 主要的測試案例搞明白了库糠,豐富測試案例,考慮一些分支流程涮毫。**
繼續(xù)Debug......
總之瞬欧,靜態(tài)地看代碼 + 動(dòng)態(tài)地debug (從業(yè)務(wù)的角度), 就會(huì)慢慢揭開這個(gè)黑暗森林的面紗罢防。
這一步會(huì)非常非常地花費(fèi)時(shí)間艘虎,但是你做完了,對(duì)系統(tǒng)的理解絕對(duì)有質(zhì)的飛躍咒吐。
眾里尋他千百度野建,驀然回首,那人卻在燈火闌珊處恬叹。
沒有千百度的上下求索候生,不會(huì)有瞬間的頓悟和理解,衷心祝愿閱讀源碼的朋友們都能達(dá)到這一境界妄呕。
最后一點(diǎn)陶舞,也是最關(guān)鍵的一點(diǎn): 要能堅(jiān)持下去。
我不是一個(gè)聰明人绪励, 但是笨人自有笨辦法:什么事都架不住不斷的重復(fù)肿孵,一遍看不明白,再來第二遍疏魏, 兩遍搞不明白停做,再來第三遍......
可能有人要問: 你怎么能這么堅(jiān)持地刨根問底呢?
答案就是好奇心: 這玩意兒到底是怎么實(shí)現(xiàn)的大莫?蛉腌!