摘要:一些方法不應(yīng)該這樣不應(yīng)該漫無(wú)目的地隨手拿起一分源碼,試圖去通讀。應(yīng)該這樣精心挑選要閱讀的源碼項(xiàng)目。這最好是與你的編程語(yǔ)言你的工作內(nèi)容你的興趣所在相關(guān)的,這樣才能更切實(shí)地感受到閱讀源碼給你帶來(lái)的益處,更有動(dòng)力繼續(xù)。
怎么閱讀源碼
"沒(méi)有經(jīng)驗(yàn)的技術(shù)差底子薄的初級(jí)程序員,如何閱讀項(xiàng)目源碼? "
"有人閱讀過(guò) mybatis 的源碼嗎 ?就看一個(gè)初始化過(guò)程就看的已經(jīng)頭暈眼花了,小伙伴們支支招吧!"
"源碼應(yīng)該怎么閱讀,我曾經(jīng)嘗試閱讀一些源碼,例如alibaba的druid中sqlparser部分,spring-mvc,但是發(fā)現(xiàn)很吃力,都說(shuō)debug是最好的閱讀方式,我在debug時(shí)經(jīng)常有跟丟的現(xiàn)象……就是走著走著感覺(jué)好像進(jìn)入了一些我當(dāng)前不太關(guān)注細(xì)枝末節(jié)。 "
。。。。。。
估計(jì)很多人都有這樣的疑惑。
我非常能理解小伙伴們的痛苦,因?yàn)槲乙彩沁@么痛苦著走過(guò)來(lái)的。
閱讀優(yōu)秀源碼的好處想必大家都知道,學(xué)習(xí)別人優(yōu)秀的設(shè)計(jì),合理的抽象,簡(jiǎn)潔的代碼...... 總之是好處多多。
但是真的把龐大的代碼放到你的面前,就如同一個(gè)巨大的迷宮,要在其中東轉(zhuǎn)西轉(zhuǎn)尋出一條路來(lái),把迷宮的整個(gè)結(jié)構(gòu)搞清楚,理解核心思想,真心不容易。
在閱讀由面向?qū)ο蟮恼Z(yǔ)言如Java寫(xiě)的代碼時(shí),會(huì)發(fā)現(xiàn)接口和具體的實(shí)現(xiàn)經(jīng)常對(duì)應(yīng)不起來(lái),不太清楚一個(gè)功能到底是怎么在哪個(gè)實(shí)現(xiàn)類中才能找到。 不像C語(yǔ)言,就是函數(shù)調(diào)用函數(shù),相對(duì)還好點(diǎn)。
如果是動(dòng)態(tài)語(yǔ)言如Ruby,Python, 一個(gè)變量的類型甚至都不容易知道,閱讀的難度大大增加。
還有一個(gè)重要的原因,現(xiàn)在我們看到的源碼基本上都經(jīng)過(guò)若干年發(fā)展、經(jīng)過(guò)很多人不斷地完善的,枝枝蔓蔓非常多,魔鬼都在細(xì)節(jié)中。 閱讀的時(shí)候很容易陷進(jìn)去, 看了幾十層函數(shù)調(diào)用以后,就徹底懵了,就放棄了: 甭管你把源碼吹得天花亂墜, 老子再也不看了。
經(jīng)過(guò)很多痛苦的掙扎以后,我也算有一些成功的經(jīng)歷,今天用治學(xué)的三個(gè)境界來(lái)類比, 給大家分享一下:
昨夜西風(fēng)凋碧樹(shù),獨(dú)上高樓,望盡天涯路
想把源碼搞懂,吃透,首先得登高望遠(yuǎn),瞰察路徑,明確目標(biāo)與方向,了解源碼的概貌。
所以有些準(zhǔn)備工作必須得做。
閱讀源碼之前,需要有一定的技術(shù)儲(chǔ)備。
比如設(shè)計(jì)模式,在很多Java源碼中幾乎就是標(biāo)配,尤其是這幾個(gè):模板方法,單例,觀察者,工廠方法,代理,策略,裝飾者。
再比如閱讀Spring源碼,肯定得先了解IoC是怎么回事,AOP的實(shí)現(xiàn)方式,CGLib,Java動(dòng)態(tài)代理等,自己動(dòng)手,寫(xiě)點(diǎn)相關(guān)的代碼,把這些知識(shí)點(diǎn)掌握了。
必須得會(huì)使用這個(gè)框架/類庫(kù), 最好是精通各種各樣的用法。
上面剛提過(guò),魔鬼都在細(xì)節(jié)中,如果有些用法根本不知道,可能你能看明白代碼是什么意思,但是不知道它為什么這些寫(xiě)。
先去找書(shū),找資料,了解這個(gè)軟件的整體設(shè)計(jì)。
都有哪些模塊? 模塊之間是怎么關(guān)聯(lián)的?怎么關(guān)聯(lián)的?
可能一下子理解不了,但是要建立一個(gè)整體的概念,就像一個(gè)地圖,防止你迷航。
在讀源碼的時(shí)候可以時(shí)不時(shí)看看自己在什么地方。
搭建系統(tǒng),把源代碼跑起來(lái)!
相信我,Debug是非常非常重要的手段, 你想通過(guò)只看而不運(yùn)行就把系統(tǒng)搞清楚,那是根本不可能的!
衣帶漸寬終不悔,為伊消得人憔悴。
根據(jù)你對(duì)系統(tǒng)的理解,設(shè)計(jì)幾個(gè)主要的測(cè)試案例,定義好輸入,輸出。
運(yùn)行系統(tǒng),慢慢地debug ,一步步地走,這是個(gè)死功夫,沒(méi)有辦法繞過(guò)。
Debug一遍肯定是不行的,需要Debug很多遍。
第一遍盡可能拋棄細(xì)節(jié),抓住主要流程, 比如有些看起來(lái)不重要的方法就不進(jìn)去看了。
第二遍、第三遍....再去看那些細(xì)節(jié)。
一個(gè)非常重要的工作就是記筆記(又是寫(xiě)作?。?huà)出系統(tǒng)的類圖(不要依靠IDE給你生成的), 記錄下主要的函數(shù)調(diào)用, 方便后續(xù)查看。
文檔工作極為重要,因?yàn)榇a太復(fù)雜,人的大腦容量也有限,記不住所有的細(xì)節(jié)。 文檔可以幫助你記住關(guān)鍵點(diǎn), 到時(shí)候可以回想起來(lái),迅速地接著往下看。
要不然,你今天看的,可能到明天就忘個(gè)差不多了。
給大家看看我做的一些筆記, 格式不重要,很隨意,方便自己看懂就行。
主要的測(cè)試案例搞明白了,豐富測(cè)試案例,考慮一些分支流程。
繼續(xù)Debug......
總之,靜態(tài)地看代碼 + 動(dòng)態(tài)地debug (從業(yè)務(wù)的角度), 就會(huì)慢慢揭開(kāi)這個(gè)黑暗森林的面紗。
這一步會(huì)非常非常地花費(fèi)時(shí)間,但是你做完了,對(duì)系統(tǒng)的理解絕對(duì)有質(zhì)的飛躍。
眾里尋他千百度,驀然回首,那人卻在燈火闌珊處。
沒(méi)有千百度的上下求索,不會(huì)有瞬間的頓悟和理解,衷心祝愿閱讀源碼的朋友們都能達(dá)到這一境界。
最后一點(diǎn),也是最關(guān)鍵的一點(diǎn): 要能堅(jiān)持下去。
我不是一個(gè)聰明人, 但是笨人自有笨辦法:什么事都架不住不斷的重復(fù),一遍看不明白,再來(lái)第二遍, 兩遍搞不明白,再來(lái)第三遍......
可能有人要問(wèn): 你怎么能這么堅(jiān)持地刨根問(wèn)底呢?
答案就是好奇心: 這玩意兒到底是怎么實(shí)現(xiàn)的?!
閱讀源碼的意義與方法思索了這兩個(gè)問(wèn)題良久,也去知乎找了一些相關(guān)話題的問(wèn)答,但并沒(méi)有標(biāo)準(zhǔn)答案。所以,我這里也只是記錄一些我對(duì)此的看法,也許會(huì)隨著 RTFSC 閱歷的豐富而發(fā)生變化,我會(huì)記錄更新于我的博客里面
意義
在我看來(lái),閱讀源碼的意義在于學(xué)習(xí)優(yōu)秀的「套路」。
這里的「套路」所指范圍很廣,大到架構(gòu)設(shè)計(jì),小到可取的命名風(fēng)格,還有設(shè)計(jì)模式、實(shí)現(xiàn)某類功能使用到的數(shù)據(jù)結(jié)構(gòu)和算法等等。所謂高手,其實(shí)就是能比大部分人更早更快地掌握套路并熟練運(yùn)用之人。
埋頭在自己的天地里耕蕓固然也能逐漸進(jìn)步和成長(zhǎng),但總會(huì)有時(shí)候會(huì)遇到一些場(chǎng)景,你苦思良久也無(wú)法做出良好的設(shè)計(jì),總會(huì)有一些時(shí)候,糾結(jié)如何為一個(gè)變量命名讓你停下飛速敲擊的手指。這些令你為難的場(chǎng)景,先賢們也許早就遇到過(guò),并且給出了優(yōu)雅的解決方案??磧?yōu)秀的源碼的時(shí)候,將這樣的場(chǎng)景與對(duì)應(yīng)的方案收入囊中,或者僅僅在腦中留下一個(gè)印象也好,以便在需要的時(shí)候,你的武器庫(kù)里總能掏出一把稱手的家伙來(lái)。
源碼閱讀三要素
源碼分析是一種臨界知識(shí),掌握了這種臨界知識(shí),能不變應(yīng)萬(wàn)變,源碼分析對(duì)于很多人來(lái)說(shuō)很枯燥,生澀難懂。
源碼閱讀,我覺(jué)得最核心有三點(diǎn):技術(shù)基礎(chǔ)+強(qiáng)烈的求知欲+耐心。
我認(rèn)為是閱讀源碼的最核心驅(qū)動(dòng)力。我見(jiàn)到絕大多數(shù)程序員,對(duì)學(xué)習(xí)的態(tài)度,基本上就是這幾個(gè)層次(很偏激哦):
只關(guān)注項(xiàng)目本身,不懂就baidu一下。
除了做好項(xiàng)目,還會(huì)閱讀和項(xiàng)目有關(guān)的技術(shù)書(shū)籍,看wikipedia。
除了閱讀和項(xiàng)目相關(guān)的書(shū)外,還會(huì)閱讀IT行業(yè)的書(shū),比如學(xué)Java時(shí),還會(huì)去了解函數(shù)語(yǔ)言,如LISP。
找一些開(kāi)源項(xiàng)目看看,大量試用第三方框架,還會(huì)寫(xiě)寫(xiě)demo。
閱讀基礎(chǔ)框架、J2EE規(guī)范、Debug服務(wù)器內(nèi)核。
大多數(shù)程序都是第1種,到第5種不光需要濃厚的興趣,還需要勇氣:我能讀懂嗎?其實(shí),你能夠讀懂的。
耐心,真的很重要。因?yàn)槟銟O少看到閱讀源碼的指導(dǎo)性文章或書(shū)籍,也沒(méi)有人要求或建議你讀。你讀的過(guò)程中經(jīng)常會(huì)卡住,而一卡主可能就陷進(jìn)了迷宮。這時(shí),你需要做的,可能是暫時(shí)中斷一下,再?gòu)耐鈬纯此喝鏏PI結(jié)構(gòu)、框架的設(shè)計(jì)圖。
源碼知識(shí)點(diǎn)是程序員都繞不開(kāi)的話題,說(shuō)到這里,也給大家推薦一個(gè)交流平臺(tái):架構(gòu)交流群650385180,里面會(huì)分享一些資深架構(gòu)師錄制的視頻錄像:有Spring,MyBatis,Netty源碼分析,高并發(fā)、高性能、分布式、微服務(wù)架構(gòu)的原理,JVM性能優(yōu)化這些成為架構(gòu)師必備的知識(shí)體系。還能領(lǐng)取免費(fèi)的學(xué)習(xí)資源,以下的知識(shí)體系圖也是在群里獲取。相信對(duì)于已經(jīng)工作和遇到技術(shù)瓶頸的碼友,在這個(gè)群里一定有你需要的內(nèi)容。
一些方法
不應(yīng)該這樣
不應(yīng)該漫無(wú)目的地隨手拿起一分源碼,試圖去通讀。這一方面會(huì)過(guò)目即忘無(wú)所收獲,另一方面會(huì)枯燥得讓你迅速?gòu)闹值椒艞?。學(xué)習(xí)的方式有很多種,閱讀源碼并不一定是最適合你當(dāng)前的情況的。
應(yīng)該這樣
精心挑選要閱讀的源碼項(xiàng)目。
這最好是與你的編程語(yǔ)言、你的工作內(nèi)容、你的興趣所在相關(guān)的,這樣才能更切實(shí)地感受到閱讀源碼給你帶來(lái)的益處,更有動(dòng)力繼續(xù)。
如果你想學(xué)習(xí)的知識(shí)點(diǎn)有官方文檔,先看文檔再看源碼。
直接從源碼著手,搞清楚原理固然是好,但是源碼有可能是難啃的,先熟悉官方提供給所有人看的文檔,能較為平滑地對(duì)這方面的知識(shí)先有個(gè)大概的了解,然后再結(jié)合源碼去深入。
提出具體的問(wèn)題,然后帶著問(wèn)題到源碼中找答案。
比如在使用 Toast 的過(guò)程中,你可能會(huì)想到一些問(wèn)題:Toast.makeText(...).show() 時(shí)發(fā)生了什么?Toast 能不能在非 UI 線程調(diào)用?能不能自定義 Toast 布局?諸如此類。在源碼中探尋完你想要的答案,你的目的也就達(dá)到了。
從一些共性層面入手。
大部分的程序里都會(huì)使用到的東西,比如線程模型、UI 組織結(jié)構(gòu)、任務(wù)調(diào)度方式等等。針對(duì)某一個(gè)方面去了解,比漫無(wú)目的要有效率得多。
最好能夠編譯運(yùn)行起來(lái)。
如果一份代碼你只能看不能跑,那可能讀到一些地方你只能猜這個(gè)地方的數(shù)據(jù)值和跳轉(zhuǎn)結(jié)構(gòu)是怎么樣的,而很有可能你猜的是錯(cuò)的。但如果你能編譯運(yùn)行,那在需要的時(shí)候你可以修改,加日志等等來(lái)更好地觀察和驗(yàn)證你的想法,得到正常的理解。
做一些筆記。
一方面是將你的學(xué)習(xí)成果保留下來(lái),方便隨時(shí)查閱,畢竟只憑腦子記憶是不靠譜的;另一方面在學(xué)習(xí)的過(guò)程中,也能幫助理解。
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://m.hztianpu.com/yun/71254.html
摘要:構(gòu)造函數(shù)參數(shù)太多錯(cuò)誤的對(duì)象狀態(tài)使用模式在我們的示例中,改造下召喚師類齊天大圣孫悟空上單基石天賦戰(zhàn)爭(zhēng)雷霆瘟疫之源圖奇下路基石天賦戰(zhàn)陣熱誠(chéng)皎月女神戴安娜中單建造者模式讓我們寫(xiě)的代碼更具可讀性,可理解為建立復(fù)雜的物體。 建造者模式(Builder Pattern)屬于創(chuàng)建型模式的一種,將多個(gè)簡(jiǎn)單對(duì)象構(gòu)建成一個(gè)復(fù)雜的對(duì)象,構(gòu)建過(guò)程抽象化,不同實(shí)現(xiàn)方法可以構(gòu)造出不同表現(xiàn)(屬性)的對(duì)象,還提供了一...
摘要:?jiǎn)螜C(jī)游戲重視沉浸感和體驗(yàn)感。這是我做判斷時(shí)的一條重要準(zhǔn)則。在我的心目中,我是廣外的走讀生。所以我對(duì)廣外總是有一種特別的感謝之情。而這段時(shí)間是最純粹穩(wěn)定的。這種崗位確是挺對(duì)口的。還是相當(dāng)感謝同學(xué)們的。本來(lái)題目是沒(méi)有年齡的。只是在網(wǎng)上??吹揭呀?jīng)25歲是否還適合轉(zhuǎn)行當(dāng)程序員之類的問(wèn)題,就覺(jué)得有必要暴露下我的年齡。 在過(guò)去的2018年,我從新媒體藝術(shù)的小圈子里面跳出來(lái),自學(xué)編程,轉(zhuǎn)行前端。現(xiàn)已經(jīng)入職...
摘要:最常見(jiàn)的有簡(jiǎn)稱和簡(jiǎn)稱。計(jì)算的高度時(shí),浮動(dòng)元素也參與計(jì)算。遇到這種情形,我們?nèi)绾翁幚硖幚矸椒ㄆ鋵?shí)有很多,在元素中添加或者使其父元素形成一個(gè)也可以在元素中添加或是這些都可以有效解決父子元素重疊問(wèn)題。解決這個(gè)問(wèn)題,只需要把把父元素變成一個(gè)就行了。 一、什么是BFC Formatting context 是 W3C CSS2.1 規(guī)范中的一個(gè)概念。它是頁(yè)面中的一塊渲染區(qū)域,并且有一套渲染規(guī)則,...
摘要:最常見(jiàn)的有簡(jiǎn)稱和簡(jiǎn)稱。計(jì)算的高度時(shí),浮動(dòng)元素也參與計(jì)算。遇到這種情形,我們?nèi)绾翁幚硖幚矸椒ㄆ鋵?shí)有很多,在元素中添加或者使其父元素形成一個(gè)也可以在元素中添加或是這些都可以有效解決父子元素重疊問(wèn)題。解決這個(gè)問(wèn)題,只需要把把父元素變成一個(gè)就行了。 一、什么是BFC Formatting context 是 W3C CSS2.1 規(guī)范中的一個(gè)概念。它是頁(yè)面中的一塊渲染區(qū)域,并且有一套渲染規(guī)則,...
摘要:最常見(jiàn)的有簡(jiǎn)稱和簡(jiǎn)稱。計(jì)算的高度時(shí),浮動(dòng)元素也參與計(jì)算。遇到這種情形,我們?nèi)绾翁幚硖幚矸椒ㄆ鋵?shí)有很多,在元素中添加或者使其父元素形成一個(gè)也可以在元素中添加或是這些都可以有效解決父子元素重疊問(wèn)題。解決這個(gè)問(wèn)題,只需要把把父元素變成一個(gè)就行了。 一、什么是BFC Formatting context 是 W3C CSS2.1 規(guī)范中的一個(gè)概念。它是頁(yè)面中的一塊渲染區(qū)域,并且有一套渲染規(guī)則,...
閱讀 1849·2021-09-22 15:25
閱讀 1363·2019-08-29 12:34
閱讀 1993·2019-08-26 13:57
閱讀 3266·2019-08-26 10:48
閱讀 1499·2019-08-26 10:45
閱讀 863·2019-08-23 18:23
閱讀 796·2019-08-23 18:01
閱讀 2009·2019-08-23 16:07