閱讀源碼(IV)
往期系列: 《由閱讀源碼想到》 《由閱讀源碼想到 | 下篇》 《閱讀源碼(III)》
Eric S.Raymond的寫于2014年的《How to learn hacking》是一篇出色的談論如何閱讀源碼的文章。(Eric這里的hacking技術,指的是開源項目里的一種 an effective way to acquire general-purpose programming skills,即獲取通用編程技藝的有效方法。)
這篇文字里,Eric創造性地提出了incremental-hacking cycle的概念。在他看來,建立起堅實的技術實力,需要經過這么一個循環過程:
-
選擇一個你感興趣的開源項目。
-
如果你不是太了解這個項目,通過閱讀文檔,去學習如何使用這個項目。
-
為這個項目增添/修改一個小的feature。
-
不斷在代碼庫中做搜索,直至找到增添這個小feature的正確位置。
-
為你的改動,生成一個build,對這個build做測試、調式。并為這個改動撰寫文檔。
-
將你的改動作為這個項目的patch,發送給這個項目的維護者。
-
繼續詢問自己:我現在理解了整個項目嗎?如果不是,返回到第三步,選擇另外一個更復雜的feature來重復上述操作。
短短7個步驟,蘊含了開源社區如何滋養技術人的合作方式(之后另寫文章闡述),及自我技術修煉的精髓。
在這里,我想展開論述第三條。從技術角度講,第三條是閱讀源碼的必要衍生——不僅僅是閱讀代碼,而是要和代碼發生作用與反應。
但對于一個newbie來說,第三條充滿了陷阱和不知曉的誤導。特別是,當第三條的工作,是由你的上司或者同事指派下來,你往往會因為feature功能過于簡單,更加無法領會第三條的精髓。
例如,如果這個項目本身有one click的功能,而你被指派的任務是實現一個double click的功能,估計很多newbie會為此抓狂,并深深地感覺受到了傷害和智商上的侮辱。
但實際情況是什么呢?
這里的重點,其實不是寫一個簡單的feature, 而是以這個小的feature做引子,去帶動你找到能夠正確添加這個feature的準確位置。
換言之,這是在訓練你對代碼的搜尋能力和對代碼整體脈絡的把握能力。當你能夠自如地找尋到每一段代碼正確的添加位置時,你也就基本掌握了這個項目的代碼架構。
另一方面,“添加一段代碼”這句話,其實隱含了很多老兵默認但newbie卻不一定知道的東西:
-
如何證明你的添加是正確的?
-
這段代碼會對整個項目產生哪些影響?
-
如何證明只會產生你認為的這些影響?
-
支撐這段代碼的test case有哪些?
-
你撰寫的test case能否覆蓋、囊括了對項目產生的所有影響?
這些默認的隱藏思考點,對newbie是極其殘酷的。老兵們沒有義務去做過多的解釋,往往就是一句“你要多寫啊”,然后不斷地給你“reject”,不斷地重復“你要認真一點啊”這樣粗糙的指導。
而如何認真呢?你從來不知道。其實就是這些默認的規則、規范和細致考慮。這些東西是開源社區的默認規則,你得通過不斷地閱讀其他人的郵件列表和提交工作,來一步步歸納總結:應該在每個看似簡單的改動背后,做足、做踏實哪些相應的輔助工作。
如此,你更加可以理解:為什么不能夠只是通過閱讀代碼,而必須通過“寫代碼”的方式來理解一個項目。所謂的“牽一發而動全身”,如果沒有一個明確的操作目標和實際作用,你很難知道這個小小的位置,會造成那么可觀的連鎖反應。而添加代碼,就如同往河里扔進去一顆石子,能夠通過切切實實的作用,讓那些隱藏在背后的連鎖反應逐一顯現,從而讓你更深刻地去掌握項目背后的實質和邏輯關系。
這樣,你也可以理解為什么需要添加一些功能上無足輕重的代碼了。因為,如果你對本身的代碼架構不夠熟悉,而feature本身的技術細節又極端復雜,你將會陷入到一個double difficulty的處境。你的debug,不僅要解決feature的技術細節,還得考慮在代碼構架中所引發的影響,這對一個newbie來說就太過困難了。
總結起來,對于newbie來說,一個很矛盾的困境、但卻很少有人愿意為你解釋清楚的是:你很可能因為這個feature自身的簡陋甚至幼稚而輕視這項“添加feature”的任務。但你的輕視,源自于你將這項任務的“用意”弄錯了。
這項任務的主菜,不在于feature的高技術含量,而在于讓你去探索、評估、理解“即便是這么簡單的一個feature添加,它到底會對這個項目本身產生哪些影響?又該如何去驗證、測試這些影響?從而去加深你對項目的理解,提高自身吸收代碼的技藝。”
近期回顧
《閱讀源碼(III)》
《2018年03月寫字總結》
《再探羊、豬、狗》
如果你喜歡我的文章或分享,請長按下面的二維碼關注我的微信公眾號,謝謝!

更多信息交流和觀點分享,可加入知識星球:

VIP贊賞專區

浙公網安備 33010602011771號