不管對於那個段位的 Developer 來說,讀原始碼都是一件好處頗多的事情,特別於初學者而言,這能迅速的吸納優秀框架精華程式碼營養,迅速成長。不巧的是,晦澀難懂的原始碼,很容易讓人心生怯意。今天分享就來談一談讀原始碼的方法,希望能幫到一些有心讀原始碼的朋友
一、瞭解框架解決了什麼問題
這不光對讀原始碼有幫助,對整個學習都很有幫助。思考一個問題:你學習 VueReact 的原因,除了它們如日中天,再不學習都不好意思找工作了,還摻雜了一些它們的某些優秀特效能給我帶來某某好處的思考麼?
新潮的框架,開發者需要而且也應該去了解,用人單位需要當然是本能的驅動力,什麼火學什麼也無可厚非,但是在悶聲學習之前,需要加上一層思考,相比之前的技術體系,這個框架到底解決了什麼問題,優勢在哪,懷著目的去學習才不至於迷茫,例如 VueReact 最大的優點是什麼呢?元件化吧,帶著框架是如何解決這個問題的疑問去學習,定能事半功倍
對於讀原始碼來說,這一步就更關鍵了,如果都不瞭解程式碼是要幹什麼的,怎麼會清楚它為什麼這麼寫呢?再細分一下,在仔細閱讀某個模組的檔案的時候,也應當對模組的功能有個整體的把握
二、瞭解框架的設計思想
這一步尤為關鍵,我們看不懂原始碼(或者看起來舉步維艱),並不是因為不懂某一句語法,而是不明白作者的思路。舉一個簡單的例子:
//這個方法可以獲得point2頂角的弧度值
function getAngle(point1, point2, point3) {
var bb = (point2.y - point1.y)*(point2.y - point1.y) + (point2.x - point1.x)*(point2.x - point1.x);
var aa = (point3.y - point1.y)*(point3.y - point1.y) + (point3.x - point1.x)*(point3.x - point1.x);
var cc = (point3.y - point2.y)*(point3.y - point2.y) + (point3.x - point2.x)*(point3.x - point2.x);
var cosa = (bb + cc - aa)/(2*Math.sqrt(bb)*Math.sqrt(cc));
return Math.acos(cosa);
}複製程式碼
getAngle
方法接收三個座標引數,可以計算出 point2 頂角的弧度值,如果不告訴你這使用了運用三角形的餘弦定理,恐怕你看半天也看不出來這是怎麼算出來的
那麼我們可以通過什麼渠道去了解框架的設計思想:
- 到框架的官網看文件,開源的框架,甭管詳不詳細,這肯定是第一手權威資料
- 到網上搜別人的分析總結(原始碼分析也不會少),大多數情況下,都會有大神已經研究過了,站在巨人的肩膀上,能省不少事
另外,設計思想是整個框架層面的,對於每一個實現細節,又會使用不少設計模式,例如函數語言程式設計(Js 中最為常用)、單例模式、代理模式、工廠模式等等,這就需要平時的積累了。有一定程式碼量的積累之後,建議閱讀一些設計模式類的書籍,對自己的程式碼設計,以及閱讀別人的原始碼,都很有益處。
三、搭建除錯環境,摸清執行主脈絡
第一節我們提到,細分到每個模組,要對模組功能有個整體的把握,如何去做到這個“把握”?除了官方文件和網上查閱的資料,最好的辦法就是寫一個簡單的 Demo,搭建好測試環境,增加一些除錯資訊,自然能理清除框架的生命週期中,每一步需要呼叫那個模組(對於目錄結構很清晰的優秀框架,有時候也可以憑直覺猜測,列印日誌確認)
四、分清主次
框架原始碼就是一顆枝繁葉茂的參天大樹,而你要做的事情是從根部網上爬。樹要這麼多分支,時間又是這麼昂貴,閱讀的策略很重要。我們的閱讀路徑,要以主要流程為主(也就是樹的主驅趕,這樣才能儘可能快的到達頂點),對於一些細枝末節,再這之後再來慢慢啃(或者有必要的時候)
例如,要去閱讀 Vue 的原始碼,有個目錄是解析模板,生成語法樹 AST 從而最終生成 Render Function 的, 其實這一步最關鍵的是這個 Render Function 的生成結果,對於如何去解析模板、生成語法樹,可以先放一放,回頭需要的時候再回頭看。否則你很容易卡死在某個點上出不來,從而產生放棄的念頭
五、堅持不放棄
技術策略得當,遇到棘手過不去的問題也很正常,這個時候考驗的就是毅力了,繼續除錯、搜尋資料、或者找個大神來問一問都行,只要不放棄就好~~