標籤: 源碼學習方法git
這個小標題好像有點扯淡,不過我感受仍是有必要聊一聊。
最近搞 Blazor,手邊常備 AspNetCore 源碼,遇到問題了就翻源碼。
而後有一樣關注 Blazor 的同窗會一塊兒討論一些問題,我知道的問題會直接分享,我不知道的問題,我就,甩一句,「看源碼」
而後有的同窗炸了,說,「不是每一個人均可以像你同樣看源碼,源碼不是每一個人都能看的,不是每一個人都想看源碼」
固然原話不是這樣,後兩句是我添油加醋的,不過這兩句想必是大部分同窗的心聲,內心懼怕看源碼,以爲看源碼都是大神纔會看的。github
st=>start: 遇到問題 search=>operation: 百度谷歌 isOk=>condition: 能解決嗎? donotusecode=>end: 好了你能夠不用繼續看了 usecode=>end: 分析源碼解決 st->search->isOk isOk(yes)->donotusecode isOk(no)->usecode
st=>start: 據說看源碼能學到不少東西,能經過面試,能XXXXX usecode=>end: 看源碼 st->usecode
感受第二個流程圖像是在扯犢子,其實第二個圖也並不是徹底錯誤,只是在強調你不能爲了看而看,你要帶着問題去看,但若是這樣的話,那其實又變成了第一張流程圖了面試
不少同窗在知足第一個流程圖的條件以後,可能看源碼仍然感受累,沒有頭緒,這是沒掌握看源碼的技巧,可能存在如下幾種狀況網絡
- 拿着 github 在線看源碼,這和拿記事本看源碼沒好到哪去
- 真的就拿着記事本看源碼,或者拿着 VSCode 看源碼(我不是黑它)
- 不擅於使用 VS 的相關功能
不用編譯直接打開 VS 一把梭,不是很好嗎?
很差,確實是能夠打開的,可是這個時候每每由於沒有編譯過致使 VS 的不少功能不可用,例如轉到定義、查找引用。
對我而言,編譯源碼是個艱難的過程,看源碼反而簡單。特別是 AspNetCore 的源碼,編譯起來要了半條命。
關於怎麼編譯,每一個開源項目都不同,有的項目簡單,打開 VS 直接就能編譯,可是像 AspNetCore 這種,必須嚴格按照官方給的編譯步驟文檔,還得保證網絡暢通,編譯過程當中很容易被勸退。單元測試
有不少同窗看源碼的過程讓我比較着急,咋看的呢?
CTRL+F,輸入搜索詞,全解決方案搜索,不論是怎樣的狀況全是這樣搞,解決方案比較大的話一搜一大堆出來。
也許只是我周圍的同窗是這樣的吧。
我看源碼的過程當中常使用這些方法學習
- 轉到定義,F12
- 轉到實現,CTRL + F12
- 查找引用
- 調用堆棧
- 解決方案管理器搜索
這五大板斧中,除了調用堆棧,其餘的幾乎都是靜態分析代碼的必備方法,調用堆棧通常屬於動態分析代碼的辦法。
這五大板斧用好了,只要源碼的變量命名不要太坑爹,基本上是不須要看註釋的,我看開源項目的源碼歷來不看註釋,開源項目的源碼的命名通常都是比較好的。測試
下面我將舉例來分享我看源碼的過程,把上面這幾個方法用上code
這是我在編寫 BlazAdmin 時遇到的問題,我須要根據當前路由獲得這個路由對應的那個組件,而後作一些操做,我甚至不知道如何搜索,由於關鍵詞很差搞,隨便搜了幾個也沒找到答案。component
下面開始分享我針對這個問題的解決思路,下載編譯 AspNetCore 源碼的步驟我就不寫了blog
萬事開頭難,剛開始看源碼更難,無頭蒼蠅的感受。
咱們的需求是,怎麼根據路由獲取對應的組件,這裏面有兩個關鍵詞,一個是路由,一個是組件
咱們換位思考一下,假如由咱們來開發這個功能,咱們會寫哪兩個類?
答案應當很明顯,Router
和 Component
,固然也許不是這麼命名的,都有可能。但好像知道這兩個名字了仍是沒啥用?根本問題在於 AspNetCore 解決方案太多,咱們壓根不知道應該打開哪一個解決方案,也就無從搜索這兩個類名。
個人辦法是,也許這兩個類咱們是能夠直接使用的,那麼若是能夠直接用的話,咱們應該能夠在代碼的任意地方調用這兩個類,那麼咱們就試試。
在咱們本身項目的 Program.cs
文件中,隨便找個地方,咱們首先嚐試 Router
關鍵字。
好像有戲,咱們已經看到命名空間了,那麼根據這個命名空間,咱們嘗試找到對應的解決方案,這個命名空間的關鍵詞是什麼呢?Microsoft?AspNetCore?這兩個關鍵詞太大衆化了,那麼只剩下兩個,Components 和 Routing,咱們一個一個來
沒啥好說的,既然找到了,管它是否是,先打開看看再說。
咱們直接在解決方案管理器中搜索這 Router 這個類。
咱們的入口點已經顯而易見了
這個類中有這麼些方法
根據方法猜功能,沒錯,看源碼全靠猜,猜錯了換條路繼續
OnAfterRenderAsync 這個應該不是
OnLocationChanged 這裏面都有些啥?
這裏面調用了 Refresh 方法,F12 跟進去
開始發暈了,咋這麼多呢,並且還不明顯,咱們一行行看,一行行猜
看第五第六行,這兩行有點意思,跟當前路由有關,也許是咱們想要的
F12 進 RouteContext,看看裏面有啥
好吧啥也沒有,咱們繼續看第六行,F12 進 Route 方法
愈來愈像了,Match 方法裏面又是什麼呢?F12 進去
這個方法中看起來也不像那麼回事,不過仍是有點有用信息,最後一句代碼將 Handler 賦值了一下,但問題是 Handler 是啥?看這命名有點像當前路由的處理器,那麼這個處理器可能就是咱們要找的 Component,從構造方法中能夠看出這個 Handler 是由構造方法傳過來的,構造方法能夠看到還有一個引用,意味着有地方在顯示調用,那麼咱們經過查找引用跳過去看看
看來這就是咱們要找的了,愈來愈近了,這裏應該是在分析路由模板,那麼路由模板應該是調用這個方法的地方傳過來的,再次查找引用跳過去
兩個地方在調,咋辦?明顯能夠看出第一個地方是單元測試調的,因此其實只有第二個地方在調
Template 就是路由的模板,而這個模板是由 RouteAttribute 特性來獲得的,而這個特性是標記在每個組件的 Type 上的,也就是說,只要獲取全部組件的 Type,就能夠拿到全部組件對應的路由,這樣一來,個人問題解決了
- 大膽猜想,當心求證
- 換位思考,若是是我,我會怎麼命名,這個經常使用於尋找分析入口點
- 英語別太差,不過通常來講你堅持看源碼英語會提高的
- 不要 CTRL + F,不要 CTRL + F,不要 CTRL + F,多用 F12,查找引用
- 在某些特殊狀況下,例如別人都是經過反射調用的,那麼就只能 CTRL + F 了
能夠看到,解決這個問題的過程幾乎全是靠猜,猜錯了就回過頭去猜下一個,猜對了那就對了。因此若是說某個開源項目的命名太糟糕,那就確實很差找了。當你看源碼看多了以後,你就不須要猜了,由於你已經知道命名是啥了。
在這個示例中,咱們沒有使用轉到實現,由於其實這個示例所涉及到的代碼仍是簡單的,沒有涉及到太多的多態,所以不須要轉到實現。若是涉及到多態,那麼過程會複雜不少,由於要看的路徑太多,但總歸是能看完的,相比用谷歌去搜索半天壓根就沒有頭緒,花點時間猜源碼仍是值的。