如何更有效地學習開源項目的代碼?

學計算機的學生,空閑時間很多,又不方便出去實習,朋友說讓我看看開源代碼,可是漫漫開源社區,而且感覺項目都很龐大且複雜,不知道大家對這個有什麼看法。
ps.個人關注java 動態語言 web


我很認同庄表偉總結的 「學習開源,就儘可能在代碼里找答案,而不是在代碼之外找答案,那些都是二手的,而且很可能是不準確的。」 但是如何讀好,讀懂代碼,我這邊還是有不同的認識。

1. 需要從代碼管理庫下載完整的源代碼,而不是簡單的源代碼文件包或者source.jar.
這樣做有很多好處,一個是你可以獲取代碼的修改記錄,還有你可以獲取到完整的測試代碼,當你要提交patch的時候,你可以藉助版本管理工具生成針對不同版本的patch。

2. 示例代碼與單元測試
示例代碼可以幫助你學會使用相關開源項目的API。很多朋友在使用開源項目的時候遇到一個小問題就發信給開發者要這樣或者那樣的示例代碼,其實他們沒有發現大部分的開源項目在開發的過程中,為了驗證其實現的功能,都會寫很多單元測試代碼。這些代碼其實非常好的示例代碼。可能是下源碼,建工程會花費你幾個小時的時間,但是如果你想深入了解開源項目的話,這點投資還是很有價值的。

其實讀單元測試的好處太多了,這裡簡單給大家列一下:

  • 由於一個單元測試一般也就是幾個小時的開發工作量,你很容易就能讀懂相關的代碼。
  • 每個單元測試都是可以獨立運行的,這樣節省你跟蹤調試的時間。
  • 單元測試在很大程度定義了軟體的功能,可以幫助你快速掌握項目的相關API。
  • 如果你修改的開源項目的代碼,你可以通過修改單元測試來驗證你的修改是否正確。
  • 單元測試裡面也蘊含架構的技巧,如果被測試對象沒有很好解耦你是很難寫出精簡的測試代碼的。

3. 架構文檔
其實大部分的開源項目都會對其架構有一定的描述,這些描述可能會有點過時,但是通讀一下會讓你項目有一個比較深入的認識。這樣做好比是讓你對北京的二環,三環,四環,五環有個大體的認識。這樣在你要對代碼的某塊內容進行詳細研究的時候(例如找中關村的位置的時候,知道西北四環)就能很快定位了。


如何快速學習一個開源項目源碼?

你有個任務,需要用到某個開源項目;或者老大交代你一個事情,讓你去了解某個東西。怎麼下手呢?如何開始呢?我的習慣是這樣:

1.首先,查找和閱讀該項目的博客和資料,通過google你能找到某個項目大體介紹的博客,快速閱讀一下就能對項目的目的、功能、基本使用有個大概的了解。

2.閱讀項目的文檔,重點關注類似Getting started、Example之類的文檔,從中學習如何下載、安裝、甚至基本使用該項目所需要的知識。

3.如果該項目有提供現成的example工程,首先嘗試按照開始文檔的介紹運行example,如果運行順利,那麼恭喜你順利開了個好頭;如果遇到問題,首先嘗試在項目的FAQ等文檔里查找答案,再次,可以將問題(例如異常信息)當成關鍵詞去搜索,查找相關的解決辦法,你遇到了,別人一般也會遇到,熱心的朋友會記錄下解決的過程;最後,可以將問題提交到項目的郵件列表,請大家幫你看看。在沒有成功運行example之前,不要嘗試修改example。

4.運行了第一個example之後,嘗試根據你的理解和需要修改example,測試高級功能等。

5. 在了解基本使用後,需要開始深入的了解該項目。例如項目的配置管理、高級功能以及最佳實踐。通常一個運作良好的項目會提供一份從淺到深的用戶指南,你並不 需要從頭到尾閱讀這份指南,根據時間和興趣,特別是你自己任務的需要,重點閱讀部分章節並做筆記(推薦evernote)。

6.如果時間允許,嘗試從源碼構建該項目。通常開源項目都會提供一份構建指南,指導你如何搭建一個用於開發、調試和構建的環境。嘗試構建一個版本。

7.如果時間允許並且有興趣,可以嘗試閱讀源碼:
(1)閱讀源碼之前,查看該項目是否提供架構和設計文檔,閱讀這些文檔可以了解該項目的大體設計和結構,讀源碼的時候不會無從下手。
(2)閱讀源碼之前,一定要能構建並運行該項目,有個直觀感受。
(3)閱讀源碼的第一步是抓主幹,嘗試理清一次正常運行的代碼調用路徑,這可以通過debug來觀察運行時的變數和行為。修改源碼加入日誌和列印可以幫助你更好的理解源碼。
(4)適當畫圖來幫助你理解源碼,在理清主幹後,可以將整個流程畫成一張流程圖或者標準的UML圖,幫助記憶和下一步的閱讀。
(5)挑選感興趣的「枝幹」代碼來閱讀,比如你對網路通訊感興趣,就閱讀網路層的代碼,深入到實現細節,如它用了什麼庫,採用了什麼設計模式,為什麼這樣做等。如果可以,debug細節代碼。
(6)閱讀源碼的時候,重視單元測試,嘗試去運行單元測試,基本上一個好的單元測試會將該代碼的功能和邊界描述清楚。
(7)在熟悉源碼後,發現有可以改進的地方,有精力、有意願可以向該項目的開發者提出改進的意見或者issue,甚至幫他修復和實現,參與該項目的發展。

8.通常在閱讀文檔和源碼之後,你能對該項目有比較深入的了解了,但是該項目所在領域,你可能還想搜索相關的項目和資料,看看有沒有其他的更好的項目或者解決方案。在廣度和深度之間權衡。

以上是我個人的一些習慣,我自己也並沒有完全按照這個來,但是按照這個順序,基本上能讓你比較高效地學習和使用某個開源項目。

原文:如何熟悉一個開源項目?


如果你空閑時間很多,我建議你多參加一些比賽。我在大學期間就頻繁參加各種比賽,收穫很大。一個完整的項目,不管再小,只要做完了,就會有收穫。

大三的時候就是因為參加比賽,才開始看一些比較大的開源項目源代碼,大概幾萬行的樣子,看完了感覺受益匪淺,從網上成熟的開源代碼里,可以學到很多的設計思想。之後因為其他的項目,又陸續看了幾個開源項目的代碼,每一個代碼量都不算太大,大概幾千行到幾萬行不等。雖然我很熱愛編程,但是,我看開源代碼也全部是因為項目需要,是項目驅動的,感覺很突兀的拿來一個項目的代碼來看,找不到那麼強大的鬥志。

所以,我還是建議你從項目入手,以項目為驅動,激勵自己進步,是否一定要看開源代碼,就看你個人的興趣和需要了。


1. 畫出整個程序的流程圖,理解整個程序流程的思想。畫流程圖的方式更讓人很直接的理解程序的整體流程,而不會被代碼所干擾,讓程序員總體上把握整個程序。
  
2. 對流程各節點(函數或過程)的理解。流程的每一節點是構成整個流程的不可缺少的部份。
  
3. 再把流程和流程各節點串起來理解整個程序,可能的話最好寫出讀書筆記。
  
4. 如果想深刻的學習到源代碼的精髓所在,請寫一個相近的程序進行操練。當你理解了這個程序並不表明你掌握了這個程序,只有在你操練一個相近的程序時,你才知道你到底理解了多少,掌握了多少。


首先構想一個你想做的東西,比如論壇、博客、微博什麼的。
然後自己思考需要什麼功能,應該怎麼去實現,儘可能包括細節,有必要時記錄下來。
最後去找個類似的開源應用,看看它是怎麼實現的,和你的想法有什麼差異,有什麼可以學習或需要改進的地方。


了解對方寫這個項目的的動機

&>&> 了解對方寫這個模塊的動機
&>&> 了解對方寫這個函數的動機


雖然和你的方向不一樣,但覺得學習是相通的。我學習CG也有一段時間了,有兩點建議:

  1. 從簡單做起。剛開始的時候學習一些領域內基礎理論,然後找一些簡單的東西去實現,不用一開始就去找開源項目。我有個師兄就經常動手寫一些小程序,如改進宿舍網路登錄客戶端等。積小成多,就能顯著提高自己的編程能力。
  2. 學習東西一定要和自己生活或工作有聯繫,這樣才會有樂趣和動力。拿我來說,我平時做的項目跟計算機圖形學有關,然後了解基礎知識後,就開始學習OGRE這個開源渲染引擎,同時也會在CSDN博客上關注一些人關於OGRE的文章,個人感覺收穫還是很大的。

其實往往方法都是簡單的,最後比的就是堅持和韌性了。

以讀代碼來說,首先想辦法讓它能編譯運行跑起來,然後想辦法加減一些東西或者調用它實現一些簡單的功能,根據這些來觀察分析調試它的行為。


我來補充幾條和參與開發相關的。當然參與不是學習開源代碼必要的條件,但是實際的參與,和作者們直接的交流會更有效地幫助你理解和提高。

  • 選擇什麼項目很重要,如果重在參與和實踐,那麼最好選一個自己用得到,非常感興趣的項目。這樣可以有很強的動力支持自己做一些代碼,否則只是閱讀代碼很枯燥,效果也不好。
  • 項目的類型,名氣,成熟度以及社區開放性,都會對你的參與有影響。
  • 一般都會有一個 How to Contribute 的文檔,可以從那裡看起來,運氣好的話可以發現有 code walkthrough guide,或者是架構類文檔
  • 一定要去訂閱項目的開發郵件列表。IRC 一直掛著,每天至少一次用十幾分鐘掃描一下 IRC 上的討論。很多項目會有為新人準備好的入門 bug 列表,挑一個沒有人在做而你又特別有興趣的開始做起來,有問題一般都可以在 IRC 或郵件列表上問。
  • 建議「腦中」有一個大概的流程圖就可以,從高層去把握,不要花很多時間去畫細節的流程圖。一個是不必記憶太多細節,還有就是絕大多數不可以自動生成的圖形隨著代碼的演進都會過時。
  • 對一些文檔注釋極少的項目,有時可以利用版本控制工具回退到比較早期較簡單的版本,更容易整體把握。不過這個方法不是很通用,最好先問問作者們。
  • Coders At Work 這本書中有多次聊到如何閱讀代碼,有興趣可以找到讀讀

我想說
stackoverflow
+
github


其實,不管用什麼方法,最終起決定作用的無非就是「堅持」二字。


1 反覆地使用軟體,熟釋軟體的組成文件和軟體功能,注意IE地址欄內的地址變化;
2 打開資料庫文件或存放數據的XML文件,參照數據字典了解各個表和欄位的數據含意,
如果沒有數據字典,就運行軟體輸入數據,參照所輸入的數據,了解各個表和欄位的數據含意;
3 利用Visio進行反向工程,將類圖抽出來;
4 研究類之間的關係,注釋各個類的屬性和方法,弄清程序的整體框架;
5 另外開一個項目,按照軟體開發的流程,將代碼分段複製進新的項目,進行編譯調試,
關注一些實現細節,學習一些編程的技巧。


從項目下手,有目的的看,如果完全是為了學代碼而看代碼,可能會很難提堅持到最後


剛開始可以從文檔入手,看看開源項目的整體架構圖。先把這個開源項目先運行起來,當然開源項目的Example 很重要,必須先弄懂,後面就可以下載源代碼,搞清楚內部的運行原理。比較有效的辦法就是畫UML圖,對於理解很有幫助。


好像有本書是專門討論這個問題的,叫《代碼的閱讀與實踐》,裡面講的代碼閱讀的方法論非常,建議去學習。 http://download.csdn.net/tag/代碼閱讀方法與實踐 http://zhi.hu/C3E3


同意樓上的觀點,沒有驅動的看,結果就只有一個放棄


我覺得學習開源項目的目的比較重要,不能為了想要做貢獻而去學,這樣很盲目,會被牽著鼻子走,而且一個項目issue可能有幾百個,很難找到適合自己水平的bug來修改提交。
學習開源項目可以先找自己用的項目開始,fork一個項目,然後根據自己使用去閱讀對應的unit test,debug代碼,並做詳細注釋,因為是fork,可以直接Push到自己的項目庫里,這樣可以加深對項目的理解。
而且我認為選擇開源項目不用一定是自己用的語言,多擴展一些其他語言,反而對自己用的語言理解更深刻,比如java工程師,可以學習c語言的開源項目。


如果在github上下的一個項目,沒有整體架構圖,也沒有足夠的注釋,怎麼辦?各種調用,各種上下文,感覺還挺麻煩的。


重代碼入口開始,一步一步地走讀,就能挖出很多東西


整體-&>細節;演算法-&>實現; 語言特點分析-&>項目優勢分析;最後當然是你的使用看法和框架的用武之地了。單元測試和doc是很好的工具,當然,一個好的編輯器也能很好的幫助你。


推薦閱讀:

開源硬體的前景如何?

TAG:開源軟體 | 編程 | 開源 |