http - 如何通过 debugging 来学习软件的运行原理?
伊谢尔伦
伊谢尔伦 2017-04-22 08:59:18
0
2
631

第一次在 SegmentFault 提问,请多关照 ^^

这个问题可能有点泛泛,请先让我具体描述一下。我是一个编程小白初学者(本职是设计,编程是好奇心作祟),不过我也系统学习了 HTTP 以及一些基本的编程技术,最近经人介绍学起了 Rails 才逐渐了解和学习到编程方方面面的知识,很喜欢,刚刚跟着一个教程编写了一个非常简单的注册/登录功能,目前工作良好。

然而我的导师(带我入门的朋友)跟我说:

在 Web 开发中,身份校验是非常典型的功能,所有的 Web 开发框架都会提供哪怕是最基本的支持,同样也有很多第三方的插件和扩展包来提供更丰富的接口和功能。尝试学习和了解经典的身份校验原理对于 Web 开发者来说简直就是必修课。比如你刚才实现的东西,行话说就是:'基于 cookie 的认证机制'。你觉得不难,那是因为 Rails 帮你做了很多很多事情,而你做的只是最表层的,也是最简单的一些必要步骤而已。有机会的话,不妨试试去跟踪登录时框架的全过程,对你大有裨益的。

以上是他的原话(略作整理),我听了以后第一感觉好像很有道理……于是我问他怎么跟踪这个过程,但由于我们通讯不便(在外地旅游),他只给我讲了一些很抽象很难懂的要点。他建议我上这里来问问各路英雄,遇见类似的问题(不限定于注册/登录,也不限定于 Rails/Ruby),如果你们需要跟踪源代码来学习和理解某一个具体的功能实现,一般会怎么做?有什么要注意的事项或技巧呢?

其实我自己知道是要用到 debugging 的技术的,一些基本的技术我之前也学习过,至少知道如何给自己写的代码打断点,然后查看运行时的变量值或者步进/跳转之类的。但是就上述问题来说,当我登录的时候,我并不知道(举例) Rails 框架何时何地向我的浏览器发送 cookie 等等,在这种情形下,面对庞大的框架(随便看看就头晕)我要如何找到下手的地方呢?

真心请教各位学长前辈们,希望能从你们身上获得宝贵的启发和经验,谢谢!

伊谢尔伦
伊谢尔伦

小伙看你根骨奇佳,潜力无限,来学PHP伐。

全部回覆(2)
阿神

個人意見,僅供參考。
用debugging跟程式碼是學習一個框架的好方法,但是前提是你了解基礎知識,如果你對http協議本身還不熟悉,那麼去看實現這個的框架就是如同看天書一般。

比如說這個身分校驗。
首先你要知道大多數情況下的http是短連接,客戶端(大多數情況下是瀏覽器)與http伺服器建立連接,發送數據,然後拿到伺服器返回的數據,之後連接就斷開了。
其次你多少要知道http通訊中的資料分為請求(Request)和回應(Response),請求由客戶端(發送到伺服器,回應是伺服器傳回給客戶端的。請求和回應的分成頭(Header)和內容(Content),頭是必須的,內容可以為空。

知道上面兩點知識後,再來看身分驗證。

身份驗證大概分為兩個過程:
1、使用者登入;
2、使用者存取其他資源,你取得到使用者身份,並判斷他能不能存取這個資源;

由於上面提到http大多數情況下是短連接,像上面的場景就是短連接。

使用者登入和存取其他資源,這顯然已經是兩個連線了。
那麼伺服器是無法判斷兩個連線都來自你,那麼你是如何在第二次連線-存取資源時,取得到使用者身分的呢?
http協議為了解決這個問題,規定了cookie。

在第一次連線-處理使用者登入時,如果使用者登入成功,那麼伺服器的回應(Response)的頭(Header)中,包含了Set-Cookie的頭,其中包含使用者的訊息,表示讓客戶端儲存一些cookie,並規定了什麼情況下(具體請參閱cookie的規定)客戶端應該把這些cookie發回給客戶端。

在第二次連線-存取資源時,因為滿足發送cookie的條件,客戶端會將cookie放在請求(Request)的頭(Header)中,作為一個Cookie的頭。這樣伺服器透過解析請求頭,拿到了cookie,也就從中拿到了使用者的資料。

這就是一次身分校驗的底層實作過程。

這其中,處理回應頭中的Set-Cookie,保存cookie,並在滿足條件時將cookie放在請求頭中發送到伺服器,是瀏覽器來實現的。

而在回應頭中放置Set-Cookie,以及從請求頭中讀取Cookie訊息,可能就是你所使用的框架來實現的。

////////// 把回覆補充到回答上來 //////////
經題主回复,我把與題主討論的內容補充到答案中。
上面我提到的,是要了解框架的前提條件。也就是首先要了解框架幫你做了哪些事,然後再去看框架是如何做這些事情的。
以下是討論的內容,我就偷懶直接複製貼上了:
說下我一般的理解:Web框架負責了請求的解碼處理和回應的編碼封裝。開發者需要寫邏輯時,只需要拿參數和回傳資料即可。參數如何從請求中取,以及傳回的結果如何被編碼為回應,這都是框架做的事情。
因此一般來說,在自己編寫邏輯的最開始和最後下斷點,然後一直跟到框架內部的處理即可。
先說在最後下斷點,這個比較簡單,因為在你的邏輯處理完成,返回數據之後,就交由框架來處理了,這個時候通過單步跟踪跟到框架代碼的內部,一步一步看你返回的數據被框架如何處理即可。
另外就是在開頭下斷點,這個時候實際上框架處理的部分已經執行完成,但是一般調試工具都可以看到調用棧,可透過調用棧看到執行你的邏輯代碼前,框架執行了哪些代碼,然後找到請求剛剛到達的程式碼,然後在此處下斷點,再次發送請求,然後一步一步跟著看。
跟完開始和結束的程式碼,你就已經了解整個框架的處理流程了。

Peter_Zhu

首先Debug對於任何一門語言都是必須的。如果語言不提供良好的debug工具。這麼這門語言就相當於一坨shit。尤其是討厭某些所謂的不需要debug。一邊寫一邊編譯的程式。

學東西的方法是。先快速看入門書。看一遍。懂概念就行。然後依需求打代碼。首先打的能編譯成功(C++)。或能運行(python)。這個狀態。主要靠的是IDE糾錯功能。

等IDE糾錯完成後。運轉後會出現各種問題。主要是邏輯錯誤或SegmentFault(C++)。
到這個時候怎麼辦。從程式碼一遍遍看簡直不能忍耐。

一般有些人會告訴初學者。 Printf/System.Out.println/print/等各種輸出查看各個變數是否正常是否是你想要的值。
這些對於熟練者是不能忍的(程式設計師三大美德(暴躁,懶惰,傲慢)中的前兩美德的要求),寫Print很累。發布的時候還要刪除。而且有些呼叫的介面不知道回傳值。打一個printf運行一下。耗時耗體力。

那麼熟練者怎麼做。 debug。這就是樓主所說中debug來源。
我不需要打Print了。直接就可以看個個數據是否正常。是否是想要的值。
在Java/C++中。 debug還可以是。
你不知道某個函數的回傳值或作用。 debug中。再需要運作的環境裡面停下來。測試函數。就可以知道其對應的回傳值。知道怎麼繼續寫。
當運行錯誤爆出到堆疊的時候,直接設定斷點到對應的堆疊時。哪段程式碼出問題。哪個變數是空值一目了然。
還有程式運行的流程。做了些操作。也可以透過控制debug來追蹤程式碼運行的流程。這就是樓主說的學習功能了。

但是這只是debug。
後面還有兩個東西:
一個是Log:線上是不讓你debug的。出問題怎麼辦。把自己覺得哪裡出問題的點打log,到時候找bug就一目了然。 。
一個是Test:只說單元測試。測試是另一種確定程式碼沒問題的方法。例如你寫專案中的很小一部分。而這一部分的main函數很遠。要很特殊的情況才牽涉到你的程式碼。 (當然Java/Python這類可以無限寫入Main函數,但某些不行)。但是你寫好單元測試後。直接以單元測試啟動。恩。模擬你想要的輸入和輸出。及時就可以發現函數的錯誤。不需要全部寫完一個大工程。然後在無數個堆疊中找錯誤了。
還有單元測試可以在排除某些特定的環境中的bug。例如你這段程式碼在你的電腦運作正常。一切滿意。但是在其他電腦上運作不正常。用單元測試可以很快就能知道哪一段程式碼出問題。

假如走到這裡。相信你已經是個合格的程式設計師了。

但是高手還有兩個東西。性能測試和性能分析。到這一步。你就需要深入各個語言或是虛擬機器底層的知識了。我這種菜鳥就不多說了

熱門教學
更多>
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板