<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          如何高效、優(yōu)雅、愉快地閱讀項(xiàng)目源碼?

          共 4923字,需瀏覽 10分鐘

           ·

          2021-09-12 18:48

          點(diǎn)擊上方藍(lán)色字體,選擇“標(biāo)星公眾號(hào)”

          優(yōu)質(zhì)文章,第一時(shí)間送達(dá)

          引子

          在 “解鎖優(yōu)秀源代碼的基本方法與技巧” 一文中,探討了閱讀優(yōu)秀源碼的基本步驟、方法、技巧、所面臨的障礙及克服之策。多加訓(xùn)練,應(yīng)該可以達(dá)成如下目標(biāo):
          • 能夠讀懂獨(dú)立類和基本容器的實(shí)現(xiàn);
          • 能夠讀懂小型的基礎(chǔ)庫和框架;
          • 通過源碼閱讀來調(diào)試和解決實(shí)際中的問題。
          本文進(jìn)一步探索如何閱讀成熟框架的源碼。

          溫馨提示
          欲速則不達(dá)。閱讀源碼很容易理解為就是直接去閱讀代碼本身。實(shí)際上,代碼只是形式,邏輯才是神韻。
          凡是有助于去理解邏輯,理解其原理、架構(gòu)、實(shí)現(xiàn)的,都是值得閱讀的。包括而不限于官方文檔和 API 文檔、架構(gòu)設(shè)計(jì)分析文章、原理分析文章、源碼閱讀分析文章。磨刀不誤砍柴工。準(zhǔn)備工作做充足,充分借助各種資源輔助,閱讀源碼才能事半功倍。

          預(yù)思考

          有需求才有目標(biāo),有目標(biāo)才有設(shè)計(jì),有設(shè)計(jì)才有框架。在閱讀某個(gè)源碼模塊之前,思考若干基本問題是必要的。
          • 需求是什么?用一句話說清楚;
          • 設(shè)計(jì)目標(biāo)是什么?用一句話說清楚;
          • 核心優(yōu)勢(shì)和適用場(chǎng)景是什么?分別用一句話說清楚;
          • 基本原理是怎樣的?先自己思考怎么實(shí)現(xiàn),然后閱讀框架原理文章;
          • 整體設(shè)計(jì)是怎樣的?先自己思考怎么設(shè)計(jì),然后閱讀架構(gòu)設(shè)計(jì)的文章;
          • 技術(shù)難點(diǎn)是什么?先自己思考其中的難點(diǎn)及解決方案,然后閱讀相關(guān)文章;
          • 數(shù)據(jù)結(jié)構(gòu)及算法流程是如何設(shè)計(jì)的?閱讀框架的源碼解析文章。
          比如 SpringBean 模塊:
          • 需求:有一套通用機(jī)制去創(chuàng)建和裝配應(yīng)用所需要的完整的 Bean 實(shí)例,使得應(yīng)用無需關(guān)注 Bean 實(shí)例的創(chuàng)建和管理,只要按需獲??;
          • 設(shè)計(jì)目標(biāo):根據(jù)指定的配置文件或注解,生成和存儲(chǔ)應(yīng)用所需要的裝配完整的 Bean 實(shí)例,并提供多種方式來獲取 Bean 實(shí)例;
          • 核心優(yōu)勢(shì):支持多種裝配方式、自動(dòng)裝配、依賴關(guān)系自動(dòng)注入;支持不同作用域的 Bean 實(shí)例創(chuàng)建和獲取;穩(wěn)定高效;
          • 適用場(chǎng)景:有大量的 Bean 需要?jiǎng)?chuàng)建,這些 Bean 存在復(fù)雜的依賴關(guān)系;
          • 基本原理:反射機(jī)制 + 緩存;
          • 算法流程:創(chuàng)建 bean 工廠對(duì)象 -> 掃描資源路徑,獲得 bean 的 class 文件 -> 生成 bean 定義的 beanDefinition 實(shí)例 -> 根據(jù) beanDefinitioin 實(shí)例創(chuàng)建 bean 實(shí)例并緩存到 bean 工廠對(duì)象 -> 依賴自動(dòng)注入 -> 執(zhí)行鉤子方法 -> 完整的 bean 實(shí)例準(zhǔn)備就緒。
          • 技術(shù)難點(diǎn):依賴自動(dòng)裝配、循環(huán)引用;解決自動(dòng)依賴注入和循環(huán)引用問題需要用到緩存機(jī)制。

          需求與目標(biāo)
          需求與目標(biāo)往往容易混為一談。但需求不等于目標(biāo)。
          • 需求是寬泛的,目標(biāo)是具體的;
          • 目標(biāo)是需求的一種實(shí)現(xiàn)途徑,往往是設(shè)計(jì)一個(gè)具備某些關(guān)鍵特性的系統(tǒng)或產(chǎn)品。
          目標(biāo)是功能與質(zhì)量的結(jié)合體;除了功能部分,確定質(zhì)量指標(biāo)也是尤為關(guān)鍵的。質(zhì)量指標(biāo)可參閱:“Web服務(wù)端軟件的服務(wù)品質(zhì)概要”
          對(duì)于某個(gè)框架來說,需求、適用場(chǎng)景和核心優(yōu)勢(shì),都是可以直接在官網(wǎng)或項(xiàng)目主頁獲取到的。如何還原框架的設(shè)計(jì)目標(biāo)呢?可以從核心優(yōu)勢(shì)中獲取基本說明,更多的就要從 API 文檔里來提煉了。

          方法

          很多開發(fā)童鞋可能對(duì)閱讀源碼心生畏懼。其實(shí)讀源碼既不神秘也不復(fù)雜:寫個(gè) Demo,打斷點(diǎn),運(yùn)行,然后細(xì)細(xì)揣摩。閱讀源碼就是觀摩高手出招的過程。
          1. 確立目標(biāo),通常是理解某個(gè)模塊的原理、設(shè)計(jì)或者為了解決實(shí)際問題;
          2. 寫個(gè) demo,能夠?qū)⒅髁鞒踢\(yùn)行起來;
          3. 找到框架運(yùn)行的入口點(diǎn),通過靜態(tài)代碼分析,大致了解整個(gè)實(shí)現(xiàn)流程;
          4. 在預(yù)估會(huì)經(jīng)過的關(guān)鍵地方打斷點(diǎn),單步調(diào)試;
          5. 仔細(xì)查看主流程經(jīng)過的主路徑、每一個(gè)主要對(duì)象及其成員變量的值及變化,細(xì)細(xì)揣摩其設(shè)計(jì)意圖和方法技巧;
          6. 繪制整體流程框圖和類的交互圖;
          7. 學(xué)習(xí)和理解關(guān)鍵類及關(guān)鍵方法及實(shí)現(xiàn)(代碼)。
          閱讀源碼,要把握主要與擴(kuò)展:
          • 首先把主流程及涉及到的主要類弄透徹;
          • 理解其擴(kuò)展機(jī)制;
          • 理解主要擴(kuò)展實(shí)現(xiàn)(需要的時(shí)候徐圖之)。

          閱讀源碼,常常要將“靜態(tài)代碼分析”和“單步調(diào)試”結(jié)合起來使用。

          靜態(tài)代碼分析
          靜態(tài)代碼分析,就是沿著方法調(diào)用鏈,“順藤摸瓜”一路點(diǎn)擊下去。通常能夠?qū)φw流程有一個(gè)大概的了解。
          由于框架實(shí)現(xiàn)常?;诮涌诰幊?,有時(shí)會(huì)遇到有多個(gè)實(shí)現(xiàn)的情形。這時(shí),可以根據(jù)直覺和經(jīng)驗(yàn),選擇一個(gè)最有可能的默認(rèn)實(shí)現(xiàn)繼續(xù)跟下去,或者通過單步調(diào)試來弄清楚是哪個(gè)具體實(shí)現(xiàn)。

          單步調(diào)試
          單步調(diào)試,是看似笨拙卻很實(shí)用的源碼閱讀方法。單步調(diào)試在以下情形尤其有用:
          • 接口調(diào)用有多個(gè)實(shí)現(xiàn),難以確定是哪個(gè)是具體實(shí)現(xiàn)時(shí);
          • 查看某個(gè)比較復(fù)雜的具體類的成員時(shí);
          • 理解實(shí)現(xiàn)細(xì)節(jié)時(shí)。

          框架解析

          框架的設(shè)計(jì)實(shí)現(xiàn)通常包括三層:
          • 問題域及解決方案構(gòu)成的抽象層,解決問題的核心部分;
          • 封裝和交互構(gòu)成的設(shè)計(jì)層,確保靈活性、可擴(kuò)展性和應(yīng)用集成;
          • 各種細(xì)節(jié)構(gòu)成的實(shí)現(xiàn)層,用于保證性能和容錯(cuò)等。
          閱讀順序是:抽象層 -> 封裝與交互層 -> 細(xì)節(jié)實(shí)現(xiàn)層 或者 抽象層 -> 細(xì)節(jié)實(shí)現(xiàn)層 -> 封裝與交互層。抽象層好比匣中的寶珠,不能干買櫝還珠的事情。

          抽象層
          抽象層即是問題求解層。技術(shù)面試中問到的原理或?qū)崿F(xiàn)機(jī)制,通常都屬于這一層。
          由于封裝和交互、實(shí)現(xiàn)細(xì)節(jié)的大量代碼往往會(huì)將用于解決問題的核心代碼“淹沒”,因此,在探索抽象層時(shí),要學(xué)會(huì)大膽過濾封裝和細(xì)節(jié),直接跳過大量的分支條件語句,暫時(shí)跳過令人疑惑的地方,始終聚焦和直擊解決問題的核心部分。用于解決基本問題的核心代碼通常是不多的。
          比如,Bean 實(shí)例創(chuàng)建的核心代碼是 ClassPathBeanDefinitionScanner.doScan(掃描資源路徑,生成 beanDefinition 對(duì)象) 和AbstractAutowireCapableBeanFactory.doCreateBean 方法(根據(jù) beanDefinition 創(chuàng)建 bean 實(shí)例)。

          設(shè)計(jì)層
          要弄明白設(shè)計(jì)層,就要先弄清楚框架的整體設(shè)計(jì):
          • 有哪些子模塊,子模塊的設(shè)計(jì)意圖是什么;
          • 子模塊之間的關(guān)聯(lián)是怎樣的,如何串聯(lián)成一個(gè)完整的設(shè)計(jì)意圖。
          框架的設(shè)計(jì)實(shí)現(xiàn)常常會(huì)用到設(shè)計(jì)模式。
          • 常用設(shè)計(jì)模式:工廠、單例、外觀、策略、適配器、裝飾、代理、模板、組合、觀察者、迭代器;
          • 不同問題域可能會(huì)用到的設(shè)計(jì)模式,比如 DB 驅(qū)動(dòng)接口實(shí)現(xiàn)會(huì)用到生成器模式和橋接模式,web 請(qǐng)求處理用到職責(zé)鏈模式。
          常用設(shè)計(jì)模式的使用場(chǎng)景:
          • 如果需要?jiǎng)?chuàng)建實(shí)例,則通常離不開工廠和單例模式;
          • 如果涉及較為復(fù)雜的算法流程,部分算法需要在子類實(shí)現(xiàn),則會(huì)用到模板方法模式;
          • 如果需要多種實(shí)現(xiàn),并依據(jù)特定場(chǎng)景來選取使用,則會(huì)用到策略模式;
          • 如果要將客戶端接口及實(shí)現(xiàn)與框架的調(diào)用隔離,則會(huì)用到動(dòng)態(tài)代理模式;
          • 如果要靈活疊加多種功能,則會(huì)用到裝飾器模式;
          • 如果涉及到事件機(jī)制,則離不開觀察者模式;
          • 如果需要在庫實(shí)現(xiàn)的基礎(chǔ)上提供簡(jiǎn)潔接口,則通常用到外觀模式;
          • 如果要將多種實(shí)現(xiàn)與多種接口定義進(jìn)行連接,則會(huì)用到橋接模式;
          • 如果需要涉及大量配置(規(guī)格)并生成實(shí)例,則通常用到生成器模式;
          • 如果涉及容器元素訪問,則離不開迭代器模式;
          • 如果需要以統(tǒng)一接口訪問整體與部分的行為,且整體由部分組成,則通常用到組合模式。
          理解基本設(shè)計(jì)模式的特征和適用場(chǎng)景,識(shí)別設(shè)計(jì)模式的使用,可以更自如地在框架源碼之間穿梭。

          細(xì)節(jié)層
          細(xì)節(jié)是最考驗(yàn)源碼閱讀的心性了。細(xì)節(jié)藏魔鬼。關(guān)鍵細(xì)節(jié)考慮不周全,可能會(huì)導(dǎo)致整個(gè)設(shè)計(jì)的失敗。因此,細(xì)節(jié)層也是值得仔細(xì)推敲的。技術(shù)面試中也常常考察實(shí)現(xiàn)細(xì)節(jié)。如果能夠回答上來,大概率會(huì)讓面試官眼前一亮。
          有時(shí),一些實(shí)現(xiàn)細(xì)節(jié)可能讓人摸不到頭腦。此時(shí),可以上網(wǎng)搜索一下,往往會(huì)“茅塞頓開”。

          克服障礙

          閱讀成熟框架源碼,遇到的一大挑戰(zhàn)就是對(duì)象之間的錯(cuò)綜復(fù)雜的交互關(guān)系。令人生畏。這實(shí)際上考驗(yàn)著開發(fā)者的抽象和建模能力。

          原理流程圖
          原理流程圖非常重要,就像地圖一樣,指引人更容易地在“代碼迷宮”中穿行而不迷失方向。
          在閱讀源碼之前,設(shè)法弄到并理解框架的原理流程圖,往往能起到事半功倍的效果。就如行兵打仗,先弄清楚天時(shí)與地形。不可不重視之。

          概念圖景
          優(yōu)秀的軟件設(shè)計(jì),往往是先建立一個(gè)比較完整的概念圖景。概念圖景,就是關(guān)于某個(gè)問題域的概念及其關(guān)聯(lián)關(guān)系的整體圖。
          譬如蓋房子吧。有的人蓋房子就是:砌磚!砌磚?。∑龃u?。?!要安裝窗戶怎么辦?把其中一大塊磚墻錘空了再安。
          有的人,則會(huì)“設(shè)計(jì)先行”:
          • 原材料 => 子部件 => 組合與集成。
          • 原材料:磚、石、木、鋁、銅、玻璃等;
          • 子部件:墻、窗框、窗戶、門、地板、樓梯、鎖、通道等;
          • 房子:由子部件進(jìn)行組合和集成而成;
          • 機(jī)制:子部件的組合與集成的原理支撐,比如形狀的組合與契合、承壓計(jì)算等。

          如何理清其中的復(fù)雜交互關(guān)系,從而理解其中蘊(yùn)含的設(shè)計(jì)思想呢?需要先理清楚框架的概念圖景。
          有兩種技巧可以結(jié)合使用:
          • 由于接口定義了具體類的行為規(guī)范,可以通過閱讀接口定義及文檔來了解其設(shè)計(jì)思路和骨架;
          • 查看具體類的實(shí)例成員(暫不涉及方法),根據(jù)經(jīng)驗(yàn)揣摩其設(shè)計(jì)意圖。

          核心類成員
          要深入到具體實(shí)現(xiàn),則無法避免核心類的閱讀。核心類往往擁有十幾個(gè)甚至幾十個(gè)成員及方法,展示出了十足的源碼閱讀勸退誠(chéng)意。面對(duì)這種情況怎么辦呢?有三個(gè)技巧可以結(jié)合使用:
          • 按快捷鍵 Alt+7,可以查看該類的所有成員及方法,概覽一下,大致猜測(cè)其意圖;
          • 首先只關(guān)注那些對(duì)核心問題求解有重要影響的成員,暫時(shí)忽略那些用來提升性能、可擴(kuò)展性等方面的成員;
          • 單步調(diào)試,仔細(xì)看看運(yùn)行時(shí)的成員對(duì)象如何,這樣會(huì)更加直觀具體一些。比如 DefaultListableBeanFactory 這個(gè)類,單步調(diào)試后得到如下圖示:

          技術(shù)難點(diǎn)
          技術(shù)難點(diǎn)也是理解源碼實(shí)現(xiàn)的一個(gè)主要障礙。技術(shù)難點(diǎn)主要有三類:
          • 數(shù)據(jù)結(jié)構(gòu)與算法:比如 HashMap 用到了哈希表和紅黑樹,需要先閱讀文獻(xiàn)(比如《算法導(dǎo)論》)理解其結(jié)構(gòu)與算法;
          • 原理機(jī)制:比如 IO 讀寫、內(nèi)存管理、文件系統(tǒng)、編譯原理、網(wǎng)絡(luò)協(xié)議,先學(xué)習(xí)相關(guān)的原理機(jī)制,夯實(shí)基礎(chǔ);
          • 編程模型:特別的編程手法和技巧,比如讀 hystrix 源碼,就要先熟悉函數(shù)式編程和響應(yīng)式編程。
          如何找到論述原理機(jī)制的相關(guān)文獻(xiàn)呢?有一些基本方法可循:
          • 經(jīng)典書籍:比如數(shù)據(jù)結(jié)構(gòu)與算法,就有《算法導(dǎo)論》、《算法》、《計(jì)算機(jī)程序設(shè)計(jì)藝術(shù)》(排序與查找)等;
          • 經(jīng)典論文:一些還沒來得及寫入書籍的論文解讀,比如 Raft 算法等;
          • 技術(shù)書籍:比如 Linux 操作系統(tǒng)內(nèi)核實(shí)現(xiàn),TCP 協(xié)議詳解等;
          • 官方文檔:優(yōu)秀項(xiàng)目主頁的文檔部分,往往有相關(guān)原理機(jī)制的介紹,比如 ES 的官方文檔;
          • JavaDoc:優(yōu)秀源碼的 Java Doc 往往會(huì)引用相關(guān)出處,比如 AQS 的源碼;
          • 優(yōu)秀博文:優(yōu)秀博文往往有一些文獻(xiàn)引用,可以閱讀相關(guān)文獻(xiàn)引用;
          • 百科與搜索:在維基百科上搜索出處和引用來源;或者使用搜索引擎。
          越到后面,就會(huì)發(fā)現(xiàn),真正需要仔細(xì)閱讀和鉆研的書籍和論文,其實(shí)并不多?;ㄙM(fèi)很多時(shí)間閱讀網(wǎng)絡(luò)文章,這些偷懶和捷徑,反而是走了彎路。

          耐心與意志
          閱讀框架源碼需要很大的耐心和意志。有點(diǎn)像蠶寶寶吃桑葉,需要一點(diǎn)一點(diǎn)地啃。各個(gè)擊破。在這個(gè)過程中,需要克服不少障礙,才能“修得正果”。
          可以使用多種輔助手段:
          • 邊聽音樂邊閱讀代碼;
          • 拉取代碼分支,邊讀邊做標(biāo)記并提交;
          • 閱讀原理、架構(gòu)及源碼分析文章。

          小結(jié)

          源碼閱讀技能,可以說是程序員的“內(nèi)功心法”之一。若是能讀通優(yōu)秀源碼,則應(yīng)對(duì)日常編程工作游刃有余,而應(yīng)對(duì)難題則有路可循。
          路漫漫其修遠(yuǎn)兮,吾將上下而求索。

            作者 |  琴水玉

          來源 |  cnblogs.com/lovesqcc/p/14403497.html


          加鋒哥微信: java1239  
          圍觀鋒哥朋友圈,天天推送Java干貨!

          瀏覽 41
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  日韩黄色视频频在线播放 | 亚洲成人无码专区在线 | 中文字幕人妻一区二区 | 人人操人人摸人人操 | 98无码人妻精品一区二区三区 |