衡阳派盒市场营销有限公司

0
  • 聊天消息
  • 系統消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發帖/加入社區
會員中心
創作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

如何去閱讀源碼,我總結了18條心法

jf_ro2CN3Fa ? 來源:三友的java日記 ? 2023-07-17 16:00 ? 次閱讀

這篇文章我準備來聊一聊如何去閱讀開源項目的源碼。

在聊如何去閱讀源碼之前,先來簡單說一下為什么要去閱讀源碼,大致可分為以下幾點原因:

最直接的原因,就是面試需要,面試喜歡問源碼,讀完源碼才可以跟面試官battle

提升自己的編程水平,學習編程思想和和代碼技巧

熟悉技術實現細節,提高設計能力

...

那么到底該如何去閱讀源碼呢?這里我總結了18條心法,助你修煉神功

61cf2db4-2442-11ee-962d-dac502259ad0.png

學好JDK

身為一個Javaer,不論要不要閱讀開源項目源碼,都要學好JDK相關的技術。

所有的Java類開源項目,本質上其實就是利用JDK已有的類庫和關鍵字實現一種業務功能,所以學會了JDK相關的類庫是看其它的源碼基礎。

如果你不懂JDK,你去閱讀源碼會發現有太多看不懂的地方,會影響讀源碼的心情和信心。

學習JDK主要包括使用和原理兩部分。內容大致包括以下幾部分:

集合相關,比如常見的Map,List,Queue的實現,包括線程安全與不安全

并發相關,比如synchronized、volatile、CAS、AQS、鎖、線程池、原子類等等

io相關,包括bio和nio等等

反射相關

網絡編程相關

...

基于 Spring Boot + MyBatis Plus + Vue & Element 實現的后臺管理系統 + 用戶小程序,支持 RBAC 動態權限、多租戶、數據權限、工作流、三方登錄、支付、短信、商城等功能

項目地址:https://github.com/YunaiV/ruoyi-vue-pro

視頻教程:https://doc.iocoder.cn/video/

了解設計模式

在一個優秀的開源項目中,設計模式處處存在,所以在你開始閱讀源碼之前最好先了解一下常見的一些設計模式。當你了解了一些設計模式以后,在源碼中遇到了相關的設計模式,你就可以快速明白代碼結構的設計,從而以整體的視角去閱讀相關代碼。

同時,學習設計模式不僅可以幫助我們閱讀源碼,在日常開發中也可以幫助我們設計出更易于擴展的程序。

學習設計模式的話可以看看《大話設計模式》這本書,如果不想看書也可以找一些視頻或者專欄。

基于 Spring Cloud Alibaba + Gateway + Nacos + RocketMQ + Vue & Element 實現的后臺管理系統 + 用戶小程序,支持 RBAC 動態權限、多租戶、數據權限、工作流、三方登錄、支付、短信、商城等功能

項目地址:https://github.com/YunaiV/yudao-cloud

視頻教程:https://doc.iocoder.cn/video/

先從官網入手

官網是介紹開源項目的地方,同時也是學習一個開源項目最開始的地方,通過官網我們可以快速的了解項目,比如:

項目的定位

一些核心概念

功能

使用教程

整體的架構和設計

常見的問題及解答

...

61f47736-2442-11ee-962d-dac502259ad0.png

RokcetMQ官網

當你了解了項目的一些概念、功能等信息之后,如果你在讀源碼一旦發現了代碼是實現這些概念或者功能的足跡,那么能夠幫助你更好的理解代碼。

熟悉源碼模塊結構

當你對項目有大致的了解之后,就可以從Github上把代碼clone下來,官網有項目源碼的Github地址。

當成功拉下來代碼之后,就可以對項目源碼模塊進行簡單的分析,熟悉模塊結構,分析模塊功能,混個眼熟。

62170bd4-2442-11ee-962d-dac502259ad0.png

如上是RocketMQ源碼,如果前面閱讀過官網相關的一些概念介紹,就大致可以知道這些模塊有什么功能。

622a0f40-2442-11ee-962d-dac502259ad0.png

RocketMQ概念介紹

比如說,源碼中的broker模塊,官網說broker主要是負責消息存儲,那么broker模塊代碼塊肯定就主要實現了消息存儲的功能。

還有些模塊可以根據單詞的意思進行判斷,比如common模塊,一看就是存儲一些公共類的模塊,example模塊,就是RocketMQ使用代碼示例的模塊等等。

順著demo開始讀

有的小伙伴在讀源碼的時候不知道從哪里開始讀比較合適,最后隨便從源碼中的某個模塊就開始讀,讀讀越來越發現讀不下去。

讀源碼正確的姿勢應該是從demo開始讀。

比如說,現在我想要閱讀一下RocketMQ生產者是如何發送消息的,整個過程是什么樣的,那么我首先至少得寫個發送消息的demo,看看代碼是如何寫的。

demo一般可以從官網中查看

625251a8-2442-11ee-962d-dac502259ad0.png

RocketMQ官網發送消息代碼示例

除了官網,一般開源項目在源碼中也會有相應的demo,代碼放在示例模塊,就比如上面提到的RocketMQ的example模塊。

最后還可以通過谷歌搜索一下demo。

DefaultMQProducerproducer=newDefaultMQProducer("sanyouProducer"); //指定NameServer的地址 producer.setNamesrvAddr("localhost:9876"); //啟動生產者 producer.start(); //省略代碼。。 Messagemsg=newMessage("sanyouTopic","TagA","三友的java日記".getBytes(RemotingHelper.DEFAULT_CHARSET)); //發送消息并得到消息的發送結果,然后打印 SendResultsendResult=producer.send(msg);

如上是RocketMQ生產者發送消息的一個demo,消息發送源碼閱讀就從這塊代碼開始入手,一步一步進入源碼中,這就算開始閱讀源碼了。

帶著目的去讀

帶著目的去讀其實很好理解,就拿上面生產者發送消息流程源碼來說,讀源碼的第一個目的其實就是弄懂生產者發送消息的流程。

除了弄懂生產者發送消息,你還可以帶著其它目的去讀。

比如說,消息發送的核心邏輯是send方法實現的,那么除了消息發送,是不是可以去弄懂生產者在啟動的過程做了哪些事,也就是start方法的作用。

再比如生產者發送消息肯定涉及到網絡通信相關的內容,那么了解RocketMQ底層網絡通信模型是不是也可以算一個目的。

當你帶著這些目的,你讀源碼就有很強的目的性,讀完印象會很深刻。當然如果你最開始想不到這些目的,也沒有什么關系,你可以先往下讀,在讀的過程中再去嘗試發現一些其它的目的。

先抓主線,再抓分支

有的小伙伴在讀源碼的時候,每個方法都使勁一直往下點,最后都不知道代碼進入到哪了,這其實是非常不可取的。

正確的方法應該是先抓住主線流程,分支流程先大致看看,知道大概是什么作用,等讀完主線之后,再回過頭仔細讀一下分支代碼。

舉個例子來說,在Spring中,ApplicationContext在使用之前需要調用一下refresh方法,而refresh方法就定義了整個容器刷新的執行流程代碼。

627af1c6-2442-11ee-962d-dac502259ad0.png

refresh方法部分截圖

當在讀這段代碼,你可以先讀一讀refresh中各個方法大致都做了什么,等讀完之后,你可以具體的去讀每個代碼的具體實現,比如說prepareRefresh干了什么,obtainFreshBeanFactory是如何獲取到BeanFactory的,prepareBeanFactory又在對BeanFactory做了什么事等等。

不要過度摳實現細節

有的小伙伴在閱讀的時候特別喜歡深究,想要弄清每行代碼是如何實現的,這不僅非常難而且也是不可取的。

就比如說,我們都知道,在Spring Bean的生命周期中,當存在基于xml的方式來聲明Bean的方式,Spring會去解析xml,生成BeanDefinition。當你想要了解Bean的生命周期過程的時候,其實是沒有太大的必要去過度扣Spring是如何解析xml生成BeanDefinition的細節,這對你整體了解Bean的生命周期沒有太大的意義,只需要知道最終會轉換成BeanDefinition就可以了。

那什么時候去扣實現細節呢?

當你需要使用到的時候,比如說你遇到了一個bug或者是需要擴展

阻礙你理解功能實現的時候

大膽猜

讀源碼的時候也需要我們發揮一點想象力,去猜一猜功能是如何實現的。猜不是瞎猜,而是基于目前了解的一些知識、技術或者是思想合理地去猜。

就比如說,當你已經知道了OpenFeign最終會對每一個FeignClient接口生成動態代理對象,之后注入的對象都是代理對象,代理對象中實現了RPC的請求之后,那么當你在學習dubbo的時候,是不是就可以去猜測注入的dubbo接口最終也是一個動態代理對象,并且這個代理對象也實現了RPC的請求?

之后你在讀代碼的時候就需要著重注意發現是否有動態代理生成的代碼,這就算是一個目的,一旦發現了動態代理相關的代碼,那么這塊代碼很可能就是dubbo RPC實現的核心。

學會看類名

不要小看類名,優秀的代碼命名都是見名知意的,所以從類名也可能窺探出這個類的一些蛛絲馬跡。

如下列舉了幾個比較常用的命名習慣

以Registry結尾的一般都是存儲功能,比如Spring中的SingletonBeanRegistry就是用來保存單例Bean的;Mybatis中的MapperRegistry就是用來保存Mapper接口的

以Support、Helper、s、Util(s)結尾的一般都是工具類

以Filter,Interceptor結尾的一般都是攔截作用,一般會配合責任鏈模式(Chain)使用

以Event、Listener結尾的一般都是基于觀察者模式實現的事件發布訂閱模型

...

除了一些比較通用的命名習慣,也有一些項目獨有的一些命名習慣。

比如說Spring中常見的以PostProcessor結尾的都是擴展接口,實現這些接口可以拿到某個比較核心的組件,從而實現對Spring的擴展。

其實很多開源項目的命名都比較偏向Spring的命名風格,當你遇到了跟Spring的命名比較像的時候,那么可以大膽猜測類的作用。

學會看類結構

類結構也非常重要,他也能夠幫助我們窺探類的大致功能。

6290d766-2442-11ee-962d-dac502259ad0.png

ApplicationContext

如上圖,是Spring中ApplicationContext的繼承體系,當你需要了解ApplicationContext的時候,可以先去熟悉一下它的父接口的作用,當你大致弄明白了每個接口的作用,那么ApplicationContext有啥作用就大致就清楚了。

除了可以看類繼承體系,還可以瀏覽一下類大致提供了哪些方法,了解對外提供的功能。

類方法通過快捷鍵 ctrl+F12(mac:fn+command+F12)查看,并且還支持模糊搜索方法名,我本人就非常喜歡這個快捷鍵

62aacab8-2442-11ee-962d-dac502259ad0.png

ApplicationContext

總結類的職責

當我們在讀完一個類的代碼的時候,一定要總結這個類的職責,明白這個類存在的意義。一般情況下一個類核心職責只有一個,遵循單一職責的設計原則。

舉個例子,在RocketMQ中有一個類MQClientAPIImpl

62cfee9c-2442-11ee-962d-dac502259ad0.png

MQClientAPIImpl

其實從名字大概看不出這個類主要是有什么功能,但是當我讀代碼的時候發現每個方法最終都調用RemotingClient方法,而RemotingClient只有一個實現NettyRemotingClient,所以從這個實現和類名可以猜出來RemotingClient是發送網絡請求的客戶端,所以當讀完MQClientAPIImpl源碼之后,我就知道了MQClientAPIImpl這個類的職責大致是封裝參數,然后通過RemotingClient向MQ發送消息的。

當知道這個類的職責的時候,那么其它地方在調用這個類的方法的時候,就知道大概在做什么事了。

習慣閱讀注釋

當你在讀源碼的時候,如果有注釋,最好能先讀一下注釋,這樣能幫助你厘清類或者方法的功能,先知道功能,再去讀源碼就容易多了。

注釋一般都是英文,如果看不懂,可以裝個插件

62effa0c-2442-11ee-962d-dac502259ad0.png

寫好注釋

俗話說的好記性不如爛筆頭,寫好注釋也是閱讀源碼中很重要的一個環節,好的注釋可以幫助快速回憶起實現細節和功能。

注釋并不需要對每行代碼都注釋,當然如果你愿意也沒多大問題,但是注釋應包括以下幾點內容:

核心類和方法實現的核心功能

核心功能大致的實現邏輯

核心的成員變量的作用

方法中不易讀懂的代碼實現細節

6308e8aa-2442-11ee-962d-dac502259ad0.png

DefaultMessageStore

如圖,是我讀RocketMQ中對于DefaultMessageStore類閱讀的注釋,這個類是RocketMQ中一個非常核心的類,從名字可以看出來跟消息的存儲有關。這個類的功能非常多,所以我寫了很多注釋,列舉了這個類主要有哪些功能和這些功能實現的一些細節。

總結思想,及時輸出

當你讀完某個功能模塊的時候,就可以嘗試對這塊功能實現邏輯或者思想進行總結。

比如說,當你了解了CAS思想的時候,你會發現,原來保證線程安全不僅僅可以通過加鎖的方式,還可以基于樂觀鎖的方式來實現。

在總結之后可以輸出成一個文檔,又或者是流程圖。我個人比較喜歡畫圖,這里推薦兩個在線畫圖工具:

processon

draw.io

processon我平時就在用,功能多,但是需要收費;draw.io的話免費,圖標和顏色感覺比processon好看,平時文章中的貼圖就是用draw.io畫的。

這里多說一句,總結思想還是非常重要的,在我閱讀了很多源碼之后,我發現很多技術或者功能的實現原理最終都是殊途同歸。

提前了解依賴的技術

一般一個開源項目不是所有的技術都是自己實現的,它也會依賴一些其它的框架或者是思想,提前了解這些框架或者是思想,可以幫助你更好地閱讀和理清代碼。

比如說,RocketMQ底層是基于Netty框架實現網絡通信的,當你對Netty有所了解,知道Netty在啟動的時候需要注冊一堆ChannelHandler用來處理網絡請求,那么在讀RocketMQ底層網絡通信功能的時候你就可以去找一下Netty啟動的代碼,看看都注冊了哪些ChannelHandler,然后就知道RocketMQ是如何處理和發送請求的。

查閱相關資料

當在閱讀源碼的時候,對某一塊代碼功能實現不太清楚的時候,可以通過查閱相關資料來輔助閱讀,包括但不限于以下幾種通道:

官網

書籍

Github

文章

視頻

堅持

最后一點也是最核心的一點就是堅持。只有你長期堅持讀源碼,不停地思考,總結,不斷提升自身技術的廣度和深度,找到適合自己的閱讀方式,閱讀源碼才會是越來越容易的一件事。

聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。 舉報投訴
  • 模塊
    +關注

    關注

    7

    文章

    2735

    瀏覽量

    47750
  • 網絡通信
    +關注

    關注

    4

    文章

    814

    瀏覽量

    29947
  • 源碼
    +關注

    關注

    8

    文章

    652

    瀏覽量

    29455

原文標題:如何去閱讀源碼,我總結了18條心法

文章出處:【微信號:芋道源碼,微信公眾號:芋道源碼】歡迎添加關注!文章轉載請注明出處。

收藏 人收藏

    評論

    相關推薦

    【收藏】268PCB Layout及電路設計規范

    本文總結了PCB布線與布局和電路設計總共268設計規范,下面與大家一起分享。
    發表于 09-08 14:26 ?5212次閱讀

    基于DS18B20和LabVIEW的多點溫度測量系統

    今天我們一起完成一個比較完整的作品,基于DS18B20和LabVIEW的多點溫度測量系統。重點介紹實現多點DS18B20溫度驅動模塊的思路,具體實現大家可以閱讀
    發表于 09-26 10:28 ?1825次閱讀

    Always過程塊語法總結

    Always過程塊是FPGA編程的很頻繁的語句,有時很可能出錯,本人總結了一下供大家參考.
    發表于 01-19 19:49

    心法

    有誰知道質心法定義啊,還有它的優缺點,謝謝啦。
    發表于 12-01 23:59

    總結了EXTI的定義、相關配置和配置方法

    本文主要總結了EXTI的定義、相關配置和配置方法。
    發表于 08-13 06:16

    下載編譯源碼的要點和搭建源碼閱讀環境的方法

    下載編譯源碼的要點和搭建源碼閱讀環境的方法。下載編譯源碼,一方面是為了搭建源碼閱讀環境,另一方面
    發表于 01-10 06:49

    總結模擬電路設計經驗12

    模擬電子的相關知識學習教材資料——總結模擬電路設計經驗12
    發表于 09-20 16:10 ?6次下載

    總結了PCB設計疊層算阻抗的4大注意事項 幫助提高計算效率

    在高速PCB設計流程里,疊層設計和阻抗計算是登頂的第一梯。下面我們總結了一些設計疊層算阻抗是的注意事項,幫助大家提高計算效率。
    的頭像 發表于 01-22 14:00 ?5930次閱讀
    <b class='flag-5'>總結了</b>PCB設計疊層算阻抗的4大注意事項 幫助提高計算效率

    總結了區塊鏈技術的四個方面來了解區塊鏈

    是的,區塊鏈是正經技術,對于這個技術,頗多贊美之詞。但是,在贊美之余,還是想潑幾杯冷水。區塊鏈很美,但也有美中不足之處,大致總結了四個方面。
    的頭像 發表于 01-22 15:48 ?6165次閱讀

    工程師跨度13年、回顧194個bug總結18編碼、測試和調試經驗教訓

    工程師跨度13年、回顧194個bug總結18編碼、測試和調試經驗教訓。
    發表于 02-27 16:50 ?1093次閱讀

    搞AI,在不斷精進自己代碼的同時,更應該閱讀大量論文

    熱點。這也是優秀工程師和普通工程師的本質區別。 就連硅谷大佬吳恩達,都會利用碎片化的時間讀AI論文,吳恩達老師不僅經常讀AI論文,還給我們總結了讀論文的方法。 他認為,我們在讀論文時,要帶著4個問題讀: 作者試圖解決什么
    的頭像 發表于 12-16 11:41 ?1452次閱讀

    分享一個超級實用的源碼閱讀小技巧

    工欲善其事必先利其器; 發現函數調用圖可以讓我們更加直觀地了解到源碼函數直接的調用和層次關系,提高閱讀源碼的效率 。 1 前言 看源碼的時
    的頭像 發表于 05-29 11:50 ?2112次閱讀
    分享一個超級實用的<b class='flag-5'>源碼</b><b class='flag-5'>閱讀</b>小技巧

    如何提高閱讀源碼的效率

    另外還需要gcc編譯源碼生成dumpfile文件,如果想要方便一些,可能還需要自己寫腳本實現自動化,如果大佬有更好的辦法,歡迎留言區討論。
    的頭像 發表于 07-06 10:01 ?711次閱讀

    基于DS18B20多點測溫源碼

    DS18B20 單線數字溫度傳感器,多個 DS18B20 可以并聯在惟一的單線上,實現多點測溫。里面包含源碼和文章詳解。致力于開源項目的分享!
    發表于 01-05 16:28 ?25次下載

    閱讀開源項目源碼的實用技巧(上)

    本文分享一下在使用或者學習開源項目源碼的過程中的一些經驗技巧。 因為最近在研究 Apache Pulsar 這款消息隊列,所以就以這個項目為例, **不過本文介紹的都是通用的技巧,完全可以用在其他大型開源項目中** 。
    的頭像 發表于 04-12 11:34 ?1184次閱讀
    <b class='flag-5'>閱讀</b>開源項目<b class='flag-5'>源碼</b>的實用技巧(上)
    大发888 dafa888游戏| 百家乐官网二游戏机| 百家乐赌场作弊| 大发888手机版下载安装| 网络百家乐官网内幕| 澳门百家乐娱乐场开户注册| 利高百家乐官网现金网| 百家乐EA平台| 吉安县| 在线百家乐怎么下注| 优博娱乐城| 太阳城百家乐的分数| 青海省| 真人百家乐新开户送彩金| 永利高足球博彩网| 百家乐投注技巧建议| 邓州市| 百家乐网上真钱娱乐场| 雷波县| 百家乐说明| 百家乐官网网络赌博网址| 威尼斯人娱乐城lm0| 百家乐官网技巧辅助软件| 青鹏棋牌官网下载| 百家乐视频交流| 澳门足球博彩| 娱乐城百家乐可以代理吗| 百家乐官网官方网址| 百家乐英皇娱乐场| 百家乐官网稳赢技法| bet365官方| 百家乐大小桌布| 太阳城百家乐官网客户端| 免费百家乐追号软件| 百家乐官网平注法到6568| 百乐门线上娱乐城| 帝王百家乐的玩法技巧和规则| 百家乐官网画哪个路单| 博九娱乐网| 百家乐群博乐吧blb8v| 网上百家乐官网网|