如何通过 debugging 来学习软件的运行原理?
第一次在 SegmentFault 提问,请多关照 ^^
这个问题可能有点泛泛,请先让我具体描述一下。我是一个编程小白(本职是设计,编程是好奇心作祟),最近经人介绍学起了 Rails 才逐渐了解和学习到编程方方面面的知识。刚刚我跟着一个教程编写了一个非常简单的注册/登录功能,目前工作良好。
然而我的导师(带我入门的朋友)跟我说:
在 Web 开发中,身份校验是非常典型的功能,所有的 Web 开发框架都会提供哪怕是最基本的支持,同样也有很多第三方的插件和扩展包来提供更丰富的接口和功能。尝试学习和了解经典的身份校验原理对于 Web 开发者来说简直就是必修课。比如你刚才实现的东西,行话说就是:'基于 cookie 的认证机制'。你觉得不难,那是因为 Rails 帮你做了很多很多事情,而你做的只是最表层的,也是最简单的一些必要步骤而已。有机会的话,不妨试试去跟踪登录时框架的全过程,对你大有裨益的。
以上是他的原话(略作整理),我听了以后第一感觉好像很有道理……于是我问他怎么跟踪这个过程,但由于我们通讯不便(在外地旅游),他只给我讲了一些很抽象很难懂的要点。他建议我上这里来问问各路英雄,遇见类似的问题(不限定于注册/登录,也不限定于 Rails/Ruby),如果你们需要跟踪源代码来学习和理解某一个具体的功能实现,一般会怎么做?有什么要注意的事项或技巧呢?
其实我自己知道是要用到 debugging 的技术的,一些基本的技术我之前也学习过,至少知道如何给自己写的代码打断点,然后查看运行时的变量值或者步进/跳转之类的。但是就上述问题来说,当我登录的时候,我并不知道(举例) Rails 框架何时何地向我的浏览器发送 cookie 等等,在这种情形下,面对庞大的框架(随便看看就头晕)我要如何找到下手的地方呢?
真心请教各位学长前辈们,希望能从你们身上获得宝贵的启发和经验,谢谢!
ruby debug ruby-on-rails cookie http
Answers
个人意见,仅供参考。
用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框架负责了请求的解码处理和响应的编码封装。开发者需要写逻辑时,只需要拿参数和返回数据即可。参数如何从请求中取,以及返回的结果如何被编码为响应,这都是框架做的事情。
因此一般来说,在自己编写逻辑的最开始和最后下断点,然后一直跟到框架内部的处理即可。
先说在最后下断点,这个比较简单,因为在你的逻辑处理完成,返回数据之后,就交由框架来处理了,这个时候通过单步跟踪跟到框架代码的内部,一步一步看你返回的数据被框架如何处理即可。
另外就是在开头下断点,这个时候实际上框架处理的部分已经执行完成,但是一般调试工具都可以看到调用栈,可通过调用栈看到执行你的逻辑代码前,框架执行了哪些代码,然后找到请求刚刚到达的代码,然后在此处下断点,再次发送请求,然后一步一步跟下来看。
跟完开始和结束的代码,你就已经了解整个框架的处理流程了。