對于一個新手,是絕對不適合一上來就追求spring,web容器,數(shù)據(jù)庫這種級別的代碼。萬事開頭總是要從簡單的來。如果沒有太多閱讀開源代碼經(jīng)驗的話,請從一個代碼量在千行級別或更小的repository開始吧。在閱讀代碼中,也慢慢留意一些約定,如
代碼的文檔一般寫哪里了(README.md ? 或者 docs目錄?)
代碼的起名字和目錄組織大概遵循什么規(guī)范
代碼如何配置
代碼如何build
這些將幫你構(gòu)建一個初步的可以深入代碼的路徑,并為進一步深入理解代碼打基礎(chǔ)。
這一點不得不夸一下javascript的npm。npm有相當多的很小的好代碼。老牌web框架express的代碼數(shù)才4000多行。一些小工具比如隨機字符串產(chǎn)生器、分布式ID產(chǎn)生器只有數(shù)十行。非常適合入門學(xué)習(xí)。
有多少人是抱著一顆不切實際的預(yù)期去看代碼的?有人說,我Java想提升一下去看看Spring吧;有人說我Web沒有太理解,去看看Tomcat吧。結(jié)果可想而知。正像問問題時不應(yīng)該問過于寬泛的問題,看任何代碼都不應(yīng)該抱有看一遍全都看懂的期望——因為就連代碼作者自己都做不到。
品牌網(wǎng)站建設(shè),寫代碼時往往都會做一些抽象,把某個特定問題拆解。比如分層、比如抽象為一個class代表一個實際的概念等等。每個抽象都可能解決一個具體的問題??创a也是如此,一定要先聚焦,把看代碼的scope限制住,不要貪多。
比如當看Java Collections代碼,可能是希望學(xué)習(xí)其數(shù)據(jù)結(jié)構(gòu)的實現(xiàn)方式——到底鏈表、樹、跳表等是怎么實現(xiàn)的,內(nèi)存中一個個object是如何關(guān)聯(lián)起來的,如何被快速訪問的;又或者是特定算法的實現(xiàn)(比如Collections.sort用的是什么排序算法)。此時,其他的部分就不要太過于在意,直接忽略那些抽象隱藏起來的地方,以及不相關(guān)的細節(jié)。
對于更復(fù)雜的服務(wù)就更要聚焦。比如Jetty解決了相當多問題,比如:如何啟動、如何找到Java Runtim、如何加載配置文件、如何load核心class、如何打log如何處理IO、如何解析HTTP協(xié)議的數(shù)據(jù)、如何將數(shù)據(jù)轉(zhuǎn)換為Servlet標準的處理、如何管理集群…… 并且,這些代碼里還會夾雜著一些設(shè)計模式的層,比如XXXXFactory,XXXXAdaptor…… 如此復(fù)雜的代碼,即使是很有經(jīng)驗的人也不可能兼顧著在短時間內(nèi)全看懂。所以,每次看代碼之前,務(wù)必先確定一個要學(xué)習(xí)的目的。如果代碼量很龐大,就可以安排一個學(xué)習(xí)計劃,每次聚焦于一個目的。
對于像Java這樣的面向?qū)ο笳Z言,優(yōu)秀的設(shè)計往往都是基于一組代表概念的類生成的對象的相互交互。學(xué)習(xí)代碼時,優(yōu)先去看類名,組織起高層的全局感非常重要。比如,如果希望學(xué)習(xí)一個“駕駛模擬”系統(tǒng)的代碼中有關(guān)“如何駕駛”的部分,一定會找到代表操作人、油門和方向盤概念的類。然后去觀察他們是如何互動的。此時絕對不該扯上變速箱、發(fā)動機和傳動軸。
作為像C這樣的語言,其源碼大致是面向過程的,即分多個步驟做一件事,每個步驟再細分為更多子步驟。例如,nginx分配一段內(nèi)存來存儲一個http請求頭就大概包括
利用一個工具函數(shù)分配指定大小的內(nèi)存
從socket中將數(shù)據(jù)讀出來,并填充到分配的內(nèi)存上
而第一步可以進一步細化為:從一個內(nèi)存池把一段內(nèi)存借出來,如果沒有可用內(nèi)存了就得找操作系統(tǒng)要,要到了內(nèi)存可能還需要填充為零……等等子步驟。這時預(yù)先畫畫流程圖對理解代碼會非常有幫助。
總之,如果你被龐大的源碼打敗,大概率不是因為你笨,而是因為你過于貪心急躁了。
三、請先看文檔
任何代碼,總得有個出現(xiàn)的動機和大致的工作原理。好的代碼一般會在文檔里(一般是README.md)里講得比較明白。比如Redis的源代碼的README.md就給出了非常概要性的信息,見https://github.com/antirez/redis。如果還需要對某個特定的主題的解釋,Redis官網(wǎng)也提供了大量的文字來說明,比如
解釋Redis的常用數(shù)據(jù)類型 —— https://redis.io/topics/data-types-intro
解釋如何實現(xiàn)一個key過期 —— https://redis.io/commands/expire
解釋如何做主從復(fù)制 —— https://redis.io/topics/replication
……
這些文檔能非常好的指導(dǎo)閱讀相關(guān)的源代碼。
更復(fù)雜的開源系統(tǒng)往往都有對應(yīng)的書籍來解釋其內(nèi)部工作原理。比如,《MySQL技術(shù)內(nèi)幕:InnoDB存儲引擎》是很好的指引如何理解InnoDB源代碼的書,大名幾乎每個做業(yè)務(wù)的同學(xué)都會接觸到;當年侯捷先生的《深入淺出MFC》非常細致的剖析了MFC內(nèi)部的C++是怎么把本來C++運行時做不到的事情通過一些歪招給搞定的;《C專家編程》(又稱魚書),用很多小例子來解釋比如一個復(fù)雜的函數(shù)指針的是怎么被parse的,變量是如何被保存和傳遞的。等等等等。
如果你閱讀的是著名系統(tǒng)的源代碼,請盡量先從文檔/書籍入手找到切入點,往往能事半功倍。對于可讀性,給人寫的東西總是好過給機器寫的東西啊。
四、關(guān)注資源的生命周期
有生產(chǎn)意義的系統(tǒng)一般總是會有一些核心的資源需要管理,而這些資源的生命周期的維護往往是這類系統(tǒng)代碼的核心。
比如
對于spring-core來講,其核心資源是“Bean”。一個Bean被創(chuàng)建、初始化、被使用、被解構(gòu),是整套代碼的核心;
對于spring-webmvc,其核心資源是“HTTP 請求”。一個http請求從被收到開始、其數(shù)據(jù)被注入到請求handler,其返回的數(shù)據(jù)結(jié)構(gòu)被設(shè)定,是整套代碼的核心;
對于一個池 (比如commons-pool,thread-pool),其核心資源是池中的Object。Object從創(chuàng)建,被借出,被使用,被歸還,到最后被銷毀,是整套代碼的核心
數(shù)據(jù)庫系統(tǒng)、隊列系統(tǒng)、web系統(tǒng)、一些業(yè)務(wù)系統(tǒng)(比如做活動、發(fā)紅包)、安全系統(tǒng)等等,都有這樣的資源的存在。把握住核心資源的生命周期就能掐到代碼的命門。
五、找一個好工具
很多年前我們做C開發(fā)時都喜歡用一款叫做"Source Insight"的軟件來學(xué)習(xí)代碼。他可以開很多窗口,在不同的函數(shù)間跳來跳去,還可以做書簽方便定位。
如今,基本上是個IDE都會有這些功能,就連沒有類型的js也能很方便的在VS Code中做各種符號跳轉(zhuǎn)和多串口切換。
代碼嘛,了解其執(zhí)行順序,而非其寫作順序更有利于學(xué)習(xí)。
六、建立調(diào)試環(huán)境
對于網(wǎng)站建設(shè)公司來講,如果對于某些系統(tǒng)需要特別細致的理解,就需要把代碼跑起來。通過打斷點,輸出log驗證等方式印證自己的想法。對于js,python這類會相當簡單,因為npm/pip等工具解決了很多依賴問題,而且無需編譯,直接啟動-修改-重啟-修改-……即可不斷的嘗試。jvm類的系統(tǒng)只要能滿足mvn install或者gradle build這樣的通用編譯約定,或者通過IDE直接加載,也能相對容易的把系統(tǒng)跑起來。
對于C/C++的系統(tǒng)就要麻煩許多,需要自己建立一個虛擬機,然后自行安裝必要的包。對于它們,遠程GDB之類的技術(shù)是非常必要的。對于前端代碼,使用jsfiddle配合chrome開發(fā)工具這樣的工具可讓你快速的構(gòu)建一段js+html+css代碼的片段,并且實時的看到效果。
值得提一句的是,有些系統(tǒng)可能涉及到比較復(fù)雜的多進程/線程并發(fā)執(zhí)行,對調(diào)試學(xué)習(xí)非常不利。此時需要優(yōu)先尋找將系統(tǒng)退化到單線程/進程的運行方式(畢竟代碼作者自己也得靠這個模式調(diào)試不是:)。一個典型的例子是nginx通常會有1個master進程+多個worker進程并發(fā)運行,但在開發(fā)時只要配置中設(shè)定:
daemon off; worker_processer 1;12
即可使其退化為單進程運行時模式。
就像跑步能跑多遠,跑多久,都是要靠自己。閱讀代碼的確能極大地提高個人能力。但是能走多遠要靠毅力堅持。而堅持的大敵就是過大的挫折感。上面提到的種種方法——從簡單的入手、聚焦、有計劃、找好工具,說白了就是盡量減少挫敗感,最大限度的提高“正反饋”。但是即便如此,不可否認的是,對于大多數(shù)人,看代碼是一項非??菰锏倪^程。這時你的恒心,你的毅力,你的“熬”的勁頭決定了你能走多遠。畢竟,想成為高級程序員并不是輕輕松松的事情。
橫下一條心來,挑戰(zhàn)自我吧。
最后附上部分我曾經(jīng)看過的高質(zhì)量開源代碼:
nginx
MFC
Redis
Lucene
Jetty
Kafka
Thrift
Java Executors
Java Collections
Java Concurrecy
express
koa
廣州天河區(qū)珠江新城富力盈力大廈北塔2706
020-38013166(網(wǎng)站咨詢專線)
400-001-5281 (售后服務(wù)熱線)
深圳市坂田十二橡樹莊園F1-7棟
Site/ http://www.szciya.com
E-mail/ itciya@vip.163.com
品牌服務(wù)專線:400-001-5281
長沙市天心區(qū)芙蓉中路三段398號新時空大廈5樓
聯(lián)系電話/ (+86 0731)88282200
品牌服務(wù)專線/ 400-966-8830
旗下運營網(wǎng)站:
Copyright ? 2016 廣州思洋文化傳播有限公司,保留所有權(quán)利。 粵ICP備09033321號