<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                #分析程序的方法   在“借鑒“階段的時候,需要掌握一些分析開源程序的方法。我總結了幾條分析開源程序的方法,供大家參考。 ##先看文檔了解程序功能   很多人可能習慣拿到代碼就開始看,這時候對程序整體一點不了解,是十分痛苦的,我們大腦對整個程序都是陌生的,很容易觸發緣腦的阻礙機制。我們要先說服緣腦, 先大概了解程序的功能,如果有文檔的話,先看文檔,這樣先了解功能后再去看源碼,對大腦來說就不會那么陌生,減少緣腦的阻礙。   有些開源程序還在文檔中講了程序的編程思想、架構原理的。如果我們不看文檔光想通過看代碼看出編程思想是比較困難的,先看文檔了解編程思想再去看代碼就比較容易理解。   每種編程語言都有將注釋生成文檔的工具,比如PHP有phpdoc, Java有JavaDoc , iOS有AppleDoc。大家需要了解這些工具,有時候雖然程序沒有穩定,但程序注釋符合一定規范,可以用這些工具把注釋生成一份文檔。 ##斷點調試   我們的程序運行速度是非常快的,幾毫秒就執行完了, 根本看不清楚執行過程, 有沒有一種方法,能放慢程序的運行過程,讓我們看清楚程序執行的每一步?這樣就方便我們分析程序執行的每個過程。   斷點調試就能做到這樣的效果,   程序每執行一行代碼都會暫停,在編輯器中顯示出執行這行代碼時各個變量的值、調用棧等信息(如圖1-15)。等我們點擊下一步按鈕,程序才會執行下一行代碼。這樣我們可以一步一步分析程序。 ![](https://box.kancloud.cn/2016-01-12_5695156127350.png) 圖1-15 netbeans和xdebug結合調試   PHP做斷點調試需要xdebug擴展結合一個IDE編輯器(如netbeans,phpstorm等編輯器)。其他編程語言也有相應的斷點調試方法,大家可以在搜索引擎搜索對應工具進行學習。 ##內置函數   很多內置的函數也有利于分析程序代碼,我以PHP為例,列舉幾個用內置函數分析程序代碼的方法。 * 用debug_backtrace看調用棧   調用棧能顯示出程序的調用過程,比如一個程序先執行了A函數,A函數中又調用了B函數 ,B函數中又調用了C函數, 那么C函數的調用棧顯示出來就是 A->B->C 的執行順序。比如執行下面的示例代碼 ``` <?php function a(){ b('hello'); } function b($arg){ c(); } function c(){ var_dump(debug_backtrace()); } a(); ```   我們在c函數中, 用debug_backtrace 獲得調用棧并用var_dump輸出。debug_backtrace函數返回值是一個數組,數組中記錄了每一步調用信息,包括文件、行數、執行的函數名、函數傳參參數。這個調用棧要從下往上看:先看數組最后一個元素,它是第一步程序執行過程;倒數第二個元素為第二步程序執行過程。運行結果如下: ``` array(3) { [0]=> array(4) { ["file"]=> string(27) "/Users/luofei/test/test.php" ["line"]=> int(6) ["function"]=> string(1) "c" ["args"]=> array(0) { } } [1]=> array(4) { ["file"]=> string(27) "/Users/luofei/test/test.php" ["line"]=> int(3) ["function"]=> string(1) "b" ["args"]=> array(1) { [0]=> &string(5) "hello" } } [2]=> array(4) { ["file"]=> string(27) "/Users/luofei/test/test.php" ["line"]=> int(13) ["function"]=> string(1) "a" ["args"]=> array(0) { } } } ```   debug_backtrace獲得調用棧非常詳細,包括每個傳參的值都顯示出來了。但有時候我們不需要這么詳細,可以使用 debug_print_backtrace函數打出一個簡單的調用棧。這個函數自己有輸出行為,不需要用var_dump打印。 將上面示例代碼 `var_dump(debug_backtrace())` 改為 `debug_print_backtrace()` , 再運行程序,我們得到如下結果: ``` #0 c() called at [/Users/luofei/test/test.php:6] #1 b(hello) called at [/Users/luofei/test/test.php:3] #2 a() called at [/Users/luofei/test/test.php:13] ```   調用棧幫助我們快速分析程序的執行流程,比如我們在分析一些開源的MVC框架時, 很想知道核心代碼是哪兒調用Controller的, 這時候我們就可以在Controller中 用debug_backtrace 打印出調用棧來分析,比我們一行一行的找代碼快很多。 * 用get_included_files看加載了哪些文件   很多開源程序都有一些共通之處,比如一般都有配置文件,數據庫DB類等。 如果一個剛拿到一個陌生的開源程序,我們想快速找到它的配置文件,可以用get_included_files 顯示出程序加載了哪些文件,然后根據文件名可以快速找到配置文件的位置,配置文件的文件名一般都叫“config”。 比如我們打印出了ThinkPHP5加載的所有文件,從這個文件列表中我們能開始發現ThinkPHP5的項目配置文件地址應該為`/thinkphp5/application/config.php` ``` array(20) { [0]=> string(20) "/thinkphp5/index.php" [1]=> string(29) "/thinkphp5/thinkphp/start.php" [2]=> string(28) "/thinkphp5/thinkphp/base.php" [3]=> string(44) "/thinkphp5/thinkphp/library/think/loader.php" [4]=> string(43) "/thinkphp5/thinkphp/library/think/error.php" [5]=> string(35) "/thinkphp5/thinkphp/mode/common.php" [6]=> string(44) "/thinkphp5/thinkphp/library/think/config.php" [7]=> string(34) "/thinkphp5/thinkphp/convention.php" [8]=> string(41) "/thinkphp5/thinkphp/library/think/app.php" [9]=> string(33) "/thinkphp5/application/config.php" [10]=> string(35) "/thinkphp5/application/database.php" [11]=> string(32) "/thinkphp5/application/route.php" [12]=> string(41) "/thinkphp5/thinkphp/library/think/log.php" [13]=> string(53) "/thinkphp5/thinkphp/library/think/log/driver/file.php" [14]=> string(43) "/thinkphp5/thinkphp/library/think/cache.php" [15]=> string(55) "/thinkphp5/thinkphp/library/think/cache/driver/file.php" [16]=> string(42) "/thinkphp5/thinkphp/library/think/lang.php" [17]=> string(45) "/thinkphp5/thinkphp/library/think/session.php" [18]=> string(49) "/thinkphp5/application/index/controller/index.php" [19]=> string(46) "/thinkphp5/thinkphp/library/think/response.php" } ``` * 變量的輸出方法   輸出變量時,echo函數會有一些問題, echo調試時如果變量是一個空字符串,看不見輸出的內容,經常會誤以為是程序沒有執行到調試的地方。還有,用echo如果是要輸出的變量是對象或數組只會打印出變量的類型,不知道變量的內部結構。   用var_dump調試不會有這些問題, 如果是輸出空字符串,var_dump也會有顯示:`string(0) ""` ,不會讓人誤以為程序沒有執行。出數組或對象的時候,var_dump也能輸出對象的內部結構。所以建議大家用var_dump調試而不用echo。   有時候不能直接輸出調試信息,比如在線上環境調試時,如果輸出調試信息,正式使用產品的用戶也能看見了。這時候你可以會把調試信息寫到日志文件中。   寫日志文件時不要用覆蓋的方式,程序執行了很多次但最能看見最后一次結果,追加的方式能看見每一次的執行結果。PHP設置文件寫文件的方式:file_put_contents 設置第三個參數為FILE_APPEND。   如果寫入文件是一個對象或數組,我們要用var_export,將變量導出再寫入日志文件,否則無法看見變量的內部結構。 下面代碼演示如何將一個數組以追加的方式寫入文件。 ``` $arr=[1,2,3,4]; file_put_contents('/tmp/log.txt',var_export($arr,true),true); ``` ##SocketLog   像上面說的不能直接用var_dump輸出調試信息的情況,以前需要寫日志文件來調試,有了SocketLog比用日志文件更方便。它可以把調試信息實時的打印到瀏覽器控制臺,可以打印字符串、對象、數組等各種變量類型,可以靈活定義打印字符串的樣式,可以打印調用棧,還方便分析開源程序,有助于我們二次開發開源產品。   github地址:http://github.com/SocketLog ,我們按官方文檔安裝好SocketLog,然后運行官方的例子可以看見簡單的效果。   示例代碼: ``` slog('msg','log'); //一般日志 slog('msg','error'); //錯誤日志 slog('msg','info'); //信息日志 slog('msg','warn'); //警告日志 slog('msg','trace');// 輸入日志同時會打出調用棧 slog('msg','alert');//將日志以alert方式彈出 slog('msg','log','color:red;font-size:20px;');//自定義日志的樣式,第三個參數為css樣式 ```   用瀏覽器查看的效果如下: ![](https://box.kancloud.cn/2016-01-12_5695156177738.png) 圖1-16 SocketLog打印日志的效果   如圖1-16,我們并沒有把調試信息打印到網站的正文,而是打印到了chrome瀏覽器的控制臺中,還可以輸出不同樣式的日志。需要打開chrome瀏覽器的控制器才能看見日志,window下可以按F12打開, Mac下同時按下“?+alt+i” 可以打開控制臺。   SocketLog調試的原理是什么呢? 如圖1-17 ![](https://box.kancloud.cn/2016-01-12_569515618854c.png) 圖1-17 SocketLog運行原理   當PHP程序無法直接把調試信息輸出到瀏覽器時,我們借助了WebSocket ,搭建一個WebSocket服務,PHP將日志傳送給WebSocket, WebSocket再將日志發送給chrome瀏覽器。所以要使用SocketLog,需要啟動websocket服務器同時瀏覽器需要安裝一個接收日志的插件。   我們還可以把程序執行的所有SQL語句打印出來,從而有助于我們分析開源程序,我以OneThink的程序為例為大家做說明 ![](https://box.kancloud.cn/2016-01-12_569515619ecaf.png) 圖1-18 用SocketLog分析OneThink程序 如圖1-18,我們用SocketLog打出OneThink的SQL語句后,當我們訪問每個頁面,都知道了這個頁面執行了哪些SQL語句,并且點開每條SQL語句能顯示出執行SQL語句的調用棧,這很方便我們找到自己想要的代碼。 假設我們在做OneThink的二次開發,想在自己新增的程序里面也讀取OneThink的文章,讀取文章這種操作肯定OneThink已經封成函數了,我們如何能快速找到這個函數?如上圖所示,只需要訪問一下文章詳情頁,然后看哪條SQL語句像是在讀取文章。```SELECT `id`,`parse`,`content`,`template`,`bookmark` FROM `onethink_document_article` WHERE ( `id` = 1 ) LIMIT 1 ,``` 這條SQL很像是在讀取文章,我們點開這條SQL語句的調用棧,很快就會發現 DocummentModel::detail方法就是我們想找的代碼, 這比一行一行的去找代碼快多了。   很多開源程序都做了對數據庫操作的封裝,一般叫著Db類,程序對數據庫進行操作都要調用這個類,我們只要找到這個Db類,加上SocketLog調試,將SQL打印出來,就能到達上圖顯示效果。以OneThink為了,需要修改ThinkPHP/Library/Think/Db.class.php文件的debug方法加上代碼 `slog($this->queryStr,$this->_linkID);` debug方法是每次數據庫操作都會執行的方法, $this->queryStr 就是這次數據庫操作的SQL語句, slog的第二個參數$this->_linkID傳遞的是數據庫對象,當第二個參數為數據庫對象是, SocketLog會對SQL語言性能進行分析并打出調用棧。   SocketLog是我以前發現調試API十分麻煩時所開發的工具,程序員本來就是有創造性的,不要忍受自己覺得麻煩的地方,你可以自己開發工具解決問題,你可以做到自動化。SocketLog為我們團隊帶來很多便利,我們團隊現在如果沒有SocketLog都快感覺不能工作了。   SocketLog還能做微信調試,如圖1-19 ![](https://box.kancloud.cn/2016-01-12_56951561c80b5.png) 圖1-19 用SoketLog調試微信   我們在開發微信公眾號的時候,接口出錯時微信上面只會提示“該公眾號暫時無法提問服務,請稍候再試”, 然后并不知道出錯原因,這給開發帶來很多麻煩,而我們將微信API配上SocketLog后,可以把調試信息和程序報錯打印到瀏覽器的控制臺上。如上圖所示,我們很快知道API出錯是因為程序報錯`Call to undefined function...` 調用了一個不存在的函數。 要做微信調試, SocketLog需要設置force_client_id 這個配置項,從而將調試信息打到指定的瀏覽器,具體如何使用大家可再參考一下官方文檔。 ##整理思維   再做開源程序分析時,會看很大量的代碼,如果光是靠腦力記,會很累,越記越亂。如何把腦袋里煩亂的思緒理順? 這時候可以用思維導圖工具xmind,如圖1-20是用Xmind整理的ThinkPHP5的執行流程。 ![](https://box.kancloud.cn/2016-01-12_569515622ef9d.png) 圖1-20 用Xmind整理ThinkPHP執行流程   Xmind的每一個分支都是可以拖動的, 我們先把雜亂內容統統列到xmind上, 然后再拖動進行歸類,從而理清思緒。   另外,在整理程序類和類之間關系時,可以畫UML圖形(如圖1-21) ![](https://box.kancloud.cn/2016-01-12_569515625e64d.png) 圖1-21 用UML圖形分析類和類的關系 UML圖形能表示出類與類是繼承、組合還是聚合等關系,可以使用staruml等軟件要畫UML圖形,如果你之前對UML不了解,建議再網上找更多相關的資料來學習一下。
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看