這樣讀源碼,不牛X也難
程序員在工作過程中,會(huì)遇到很多需要閱讀源碼的場(chǎng)景,比如技術(shù)預(yù)研、選擇技術(shù)框架、接手以前的項(xiàng)目、review他人的代碼、維護(hù)老產(chǎn)品等等??梢哉f,閱讀源代碼是程序員的基本功,這項(xiàng)基本功是否扎實(shí),會(huì)在很大程度上影響一個(gè)程序員在技術(shù)上的成長(zhǎng)速度。
2014年寫《Qt on Android核心編程》和《Qt Quick核心編程》時(shí),很多內(nèi)容都是通過分析Qt源碼搞明白的。這陣子研究CEF和PPAPI,也主要靠研究源代碼來搞明白用法。最近工作上要修改已有項(xiàng)目的一個(gè)子系統(tǒng),也是得硬著頭皮先讀懂代碼。
總之在開發(fā)工作這十來年中,讀過太多源碼了,從源代碼中學(xué)習(xí)到太多東西了,如果不閱讀源代碼,真不知道自己能否成長(zhǎng)起來。
寫代碼是從模仿開始的,提高也是從觀摩別人的優(yōu)秀設(shè)計(jì)和代碼開始的。所以閱讀源碼至關(guān)重要,接下來咱從下列方面聊聊閱讀源碼的事兒。
- 目的
- 工具
- 知識(shí)準(zhǔn)備
- 運(yùn)行與開發(fā)環(huán)境
- 筆記
- 實(shí)用技巧
- 心理調(diào)試(散步在各個(gè)環(huán)節(jié))
目的
當(dāng)我們閱讀面前的源碼時(shí),無非有以下幾種目的:
- 純粹學(xué)習(xí)
- 添加新功能
- 重構(gòu)舊代碼
- 修復(fù)他人的Bug
不同的目的會(huì)有不同的心情,會(huì)影響到工作的進(jìn)展,像修復(fù)他人的Bug這種事情,類似于沒被掰彎的男猿捏著鼻子給另外一個(gè)男人擦屁股,是很惡心的,很容易讓人拒絕的。所以因這種目標(biāo)而閱讀源碼,往往是欲拒還迎、欲說還休,效率較低。然而修復(fù)實(shí)際工作中幫別人修復(fù)Bug這種情形,十有八九你要遇到,無可逃避。所以,心理調(diào)試很重要。
為了學(xué)習(xí)去讀源碼,這是最愉快的最放松的。不過提醒一點(diǎn),設(shè)定可檢驗(yàn)的目標(biāo)才會(huì)有收獲,否則就會(huì)像走到大街上看見一美女擦肩而過那樣,驚艷一下下,過后嘛關(guān)系嘛收獲也沒了。
其他的目的,重構(gòu)舊代碼、添加新功能,比幫別人擦溝子(陜西話,屁股)略強(qiáng),因?yàn)樗麕в袆?chuàng)造性,創(chuàng)造性的活動(dòng)能給人帶來強(qiáng)烈的愉悅,所以雖然這兩種目的也有很多讓人不爽的部分,不過想到我可以讓一棵老樹煥發(fā)青春,不爽也就慢慢弱下去了。
工具
工欲善其事必先利其器,這是亙古不變的道理。要很好的完成閱讀源碼的任務(wù),我們大概需要下列這些工具:
- SourceInsight,最好的源碼瀏覽工具,它能維護(hù)符號(hào)庫,動(dòng)態(tài)顯示上下文,還能繪制調(diào)用關(guān)系圖,最好的,沒有之一
- 紙質(zhì)筆記本,隨時(shí)記錄心得和疑惑,隨時(shí)繪制各種圖(類圖、時(shí)序圖、框圖),比UML工具快,也比Visio快
- 中性筆
- 記事本、Notepad++、有道云筆記、為知筆記等,記錄閱讀源碼過程中的關(guān)鍵點(diǎn)、心得體會(huì)、分析過程
- Visio,用于繪制簡(jiǎn)單的框圖,表述源碼的模塊劃分、層次結(jié)構(gòu)等
- StartUML,用于最后繪制類圖、時(shí)序圖等,方便交流
- 掃描全能王(CamScanner),一款可以通過拍照達(dá)到掃描效果的App,可以用它掃描你在紙質(zhì)筆記本上寫下的文字,繪制的框圖,分享給其他人,如果你懶得用軟件繪制圖標(biāo),那手繪之后掃描成電子檔就最適合你了
知識(shí)準(zhǔn)備
前戲很重要,準(zhǔn)備好了后面水到渠成快感不斷,否則就會(huì)頻頻受挫直感道阻且長(zhǎng)。
- 業(yè)務(wù)基礎(chǔ),每一份有實(shí)際意義的源碼都離不開業(yè)務(wù),必須先對(duì)業(yè)務(wù)有概念
- 技術(shù)基礎(chǔ),這個(gè)源碼用什么語言,什么框架,什么第三方模塊,都需要先有所了解
- 文檔,盡量找到業(yè)務(wù)、需求、概要、詳細(xì)等文檔,幫助會(huì)很大,然而,我們經(jīng)常面臨的情況是,只有源碼,只有源碼,只有源碼,片言只字的文檔也無,所以只好堅(jiān)信——源碼是最好的文檔。這個(gè)心理門檻兒其實(shí)也容易過,你就想像著源碼只是神仙姐姐的畫像,看再多畫像也不抵當(dāng)面一眼效果強(qiáng)大——要么摧毀三觀要么魂?duì)繅?mèng)縈
- 人,搞明白哪個(gè)程序員維護(hù)過這份代碼,方便后面不懂時(shí)請(qǐng)教,有時(shí)人家點(diǎn)一下頂你自己瞎琢磨一天
運(yùn)行與開發(fā)環(huán)境
- 配置好開發(fā)環(huán)境,目的是為了調(diào)試,對(duì)有些程序員來講,調(diào)試是弄明白軟件內(nèi)部機(jī)理的最好方法,按著F5、F10、F11、F9,一切都搞定了
- 配置好運(yùn)行環(huán)境,為使用軟件、體驗(yàn)軟件做準(zhǔn)備,從用戶角度,從外面看看軟件到底是怎么回事,便于揣摩內(nèi)部邏輯
筆記
在閱讀源碼的過程中,做筆記是必須的。我有這樣的體會(huì),因?yàn)榇a不是自己寫的,很難很快在腦子里刻下印記,經(jīng)常是看著這里忘了那里,早上覺得弄懂了數(shù)據(jù)流向,中午吃個(gè)飯就忘了。所以,筆記就顯得尤為重要。
- 找到適合你的記錄方式,小本本、軟件皆可。用軟件(Notepad++、有道筆記、為知筆記等)來記錄有個(gè)壞處——必須切換屏幕,會(huì)在形式上中斷代碼閱讀過程。所以我經(jīng)常在緊張得不能中斷時(shí)隨手用筆寫些斷句殘章在本子上,告一段落時(shí)梳理下用軟件再記錄。
- 盡可能詳細(xì)的記錄,但不必看到什么記錄什么,要間隔性的記錄,比如弄明白了某個(gè)子模塊的邏輯、某個(gè)類的作用、某些函數(shù)的調(diào)用關(guān)系時(shí)再記錄,否則記錄這個(gè)動(dòng)作本身會(huì)打斷思考
- 每天工作結(jié)束,記錄進(jìn)度(弄明白的部分),記錄疑問,記錄第二天要弄明白什么東西,這樣你的工作狀態(tài)就入棧了,第二天來了很容易出棧,快速進(jìn)入工作狀態(tài)
- 記錄看到的優(yōu)秀設(shè)計(jì),提高審美,見賢思齊,自我成長(zhǎng)
滄海遺珠
我在漫長(zhǎng)的讀碼生涯里積攢了一些的經(jīng)驗(yàn),算是碎碎念,供參考:
- 理清某一業(yè)務(wù)如何映射在代碼執(zhí)行流程上的,這點(diǎn)很關(guān)鍵。
- 理清不同模塊間的業(yè)務(wù)關(guān)系,代碼調(diào)用關(guān)系,很關(guān)鍵
- 調(diào)試是弄明白代碼調(diào)用流程的最快方式,之一
- 找出關(guān)鍵代碼(代表實(shí)際對(duì)象的類、銜接不同模塊的類、代表業(yè)務(wù)關(guān)鍵節(jié)點(diǎn)的類)
- 分析日志可以幫助分析代碼執(zhí)行流程和業(yè)務(wù)流程
- 先用已有的可運(yùn)行軟件,體驗(yàn)業(yè)務(wù),琢磨你點(diǎn)這里一下點(diǎn)那里一下代碼可能是怎么做出反應(yīng)的
- 閱讀應(yīng)該圍繞目的,把實(shí)現(xiàn)目標(biāo)放在第一位,比如修改Bug,如果有期限,在最后日期前搞定是第一要?jiǎng)?wù),然后有時(shí)間就繼續(xù)讀源碼或改進(jìn)Bug修復(fù)方案,力求沒有副作用和后遺癥,再有時(shí)間就修修別人留下的破窗戶(你也可以順帶鄙視下前任維護(hù)者)
- 千萬次的問,還記得前面說要弄明白誰維護(hù)過你要讀的代碼吧,別不好意思,問吧,問吧,問吧
- 對(duì)著設(shè)計(jì)文檔、接口文檔或測(cè)試用例看代碼
- 心理調(diào)試,勿畏難,別放棄。我有時(shí)看代碼,看兩天也不知道看了個(gè)甚,一頭霧水兩眼發(fā)花是常有的事兒,有時(shí)真是覺得搞不定了,然而,這要么是你基礎(chǔ)知識(shí)沒準(zhǔn)備好,要么是你找錯(cuò)了入口,要知道,任何一份代碼,都有一條隱形的線串著,耐心點(diǎn),總會(huì)找到。這樣不行就那樣,多換換角度,多換換方法,讀不行,就調(diào)試,調(diào)試不行,就運(yùn)行,運(yùn)行不行,就研究日志,都不行,我靠,while(!i.isDead())i.analyzeCode(),跟Y死磕!總之,你不放棄自己,就沒人能放棄你!
- 給自己設(shè)置小獎(jiǎng)勵(lì),弄明白某個(gè)邏輯或某個(gè)模塊的代碼后獎(jiǎng)勵(lì)自己休息一下,5~10分鐘,走出辦公室轉(zhuǎn)轉(zhuǎn),或者干脆在網(wǎng)上瞎逛一下,瀏覽自己喜歡的網(wǎng)站
- 讀不懂才要讀,想不明白才要想,這是進(jìn)步和成長(zhǎng)的開始。那些阻擋你的蹂躪你的而殺又不死你的,終將幫助你成長(zhǎng)讓你變得更強(qiáng)大。