Home  >  Q&A  >  body text

http - 如何通过 debugging 来学习软件的运行原理?

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

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

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

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

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

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

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

伊谢尔伦伊谢尔伦2712 days ago585

reply all(2)I'll reply

  • 阿神

    阿神2017-04-22 09:01:18

    Personal opinion, for reference only.
    Using debugging and code is a good way to learn a framework, but the premise is that you understand the basic knowledge. If you are not familiar with the http protocol itself, then looking at the framework that implements this is like reading a bible.

    For example, this identity verification.
    First of all, you need to know that http in most cases is a short connection. The client (browser in most cases) establishes a connection with the http server, sends data, and then gets the data returned by the server, and then the connection is disconnected.
    Secondly, you need to know that the data in http communication is divided into request (Request) and response (Response). The request is sent by the client (to the server), and the response is returned by the server to the client. The request and response are divided into Header and Response. Content (Content), the header is required, and the content can be empty

    .

    After knowing the above two points, let’s look at identity verification.
    Identity verification is roughly divided into two processes:
    1. User login;
    2. When a user accesses other resources, you obtain the user’s identity and determine whether he can access this resource;

    As mentioned above, http is a short connection in most cases, and the above scenario is a short connection.
    Users log in and access other resources, which are obviously two connections.
    Then the server cannot determine that both connections are from you, so how do you obtain the user identity when you connect to the resource for the second time?
    In order to solve this problem, the http protocol stipulates cookies.

    In the first connection - when processing user login, if the user logs in successfully, the header of the server's response (Response) contains the Set-Cookie header, which contains the user's information, indicating that the client Save some cookies and stipulate under what circumstances (see cookie provisions for details) the client should send these cookies back to the client.
    During the second connection - when accessing resources, because the conditions for sending cookies are met, the client will put the cookie in the header of the request (Request) as a Cookie header. In this way, the server gets the cookie by parsing the request header, and also gets the user's information from it.

    This is the underlying implementation process of an identity verification.

    Among them, the browser handles the Set-Cookie in the response header, saves the cookie, and puts the cookie in the request header and sends it to the server when the conditions are met.
    Placing Set-Cookie in the response header and reading Cookie information from the request header may be implemented by the framework you use.

    ////////// Add reply to answer //////////
    After the questioner responded, I added the content discussed with the questioner into the answer.
    What I mentioned above is the prerequisite for understanding the framework. That is to say, you must first understand what the framework has done for you, and then look at how the framework does these things.
    The following is the content of the discussion, so I just copied and pasted it:
    Let me talk about my general understanding: The Web framework is responsible for the decoding of requests and the encoding and encapsulation of responses. When developers need to write logic, they only need to get parameters and return data. How the parameters are taken from the request and how the returned results are encoded into responses are all done by the framework.
    Therefore, generally speaking, you can set breakpoints at the beginning and end of the logic you write, and then follow the processing inside the framework.
    Let’s start with setting a breakpoint at the end. This is relatively simple, because after your logic processing is completed and the data is returned, it is handed over to the framework for processing. At this time, you can follow the inside of the framework code through single-step tracing and watch your return step by step. The data is processed by the framework.
    The other is to set a breakpoint at the beginning. At this time, the processing part of the framework has actually been executed, but general debugging tools can see the call stack. You can use the call stack to see what code the framework executed before executing your logic code. Then find the code where the request just arrived, set a breakpoint here, send the request again, and then follow it step by step.
    After following the starting and ending codes, you will already understand the processing flow of the entire framework.

    reply
    0
  • 天蓬老师

    天蓬老师2017-04-22 09:01:18

    First of all, debugging is necessary for any language. If the language does not provide good debugging tools. So the language is a piece of shit. Especially I hate some so-called debugging that is not needed. A program that is compiled as it is written.

    The way to learn something is. Let’s take a quick look at the introductory book first. Read it again. Just understand the concept. Then code as required. The first one can be compiled successfully (C++). Or can run (python). this state. It mainly relies on the IDE error correction function.

    Wait until the IDE error correction is completed. Various problems will occur after running. Mainly logic errors or SegmentFault (C++).
    What to do at this time. Looking at the code over and over is simply unbearable.

    Generally some people will tell beginners. Printf/System.Out.println/print/ and other output to check whether each variable is normal and has the value you want.
    These are intolerable to experienced people (requirements for the first two of the three virtues of programmers (irritability, laziness, and arrogance)), and writing Print is very tiring. It will also be deleted when published. And some calling interfaces don't know the return value. Make a printf and run it. It takes time and energy.

    So what does a skilled person do? debug. This is the source of the debug mentioned by the poster.
    I don't need to print anymore. You can directly check whether each data is normal. Is it the desired value.
    in Java/C++. Debug is okay.
    You don't know the return value or effect of a function. debugging. Stop in the environment where it needs to be run. Test function. You can know its corresponding return value. Know how to keep writing.
    When a runtime error pops up on the stack, directly set the breakpoint to the corresponding stack. Which piece of code is causing the problem? It is clear at a glance which variable has a null value.
    There is also the process of running the program. Did some operations. You can also track the code running process by controlling debug. This is the learning function that the poster mentioned.

    But this is just debug.
    There are two more things at the back:
    One is Log: you are not allowed to debug online. What to do if something goes wrong. Log what you think is the problem, and it will be clear to find the bug when the time comes. .
    One is Test: only unit testing. Testing is another way to make sure your code is OK. For example, you write a very small part of the project. The main function of this part is very far away. Only very special circumstances are involved in your code. (Of course, Java/Python can write unlimited Main functions, but some cannot). But after you write the unit test. Start directly with unit tests. kindness. Simulate your desired input and output. Function errors can be discovered in time. There is no need to write out a big project in its entirety. Then I looked for errors in countless stacks.
    Also, unit testing can eliminate bugs in certain environments. For example, your code runs normally on your computer. All satisfied. But it doesn't work properly on other computers. With unit testing, you can quickly find out which piece of code has a problem.

    If you get here. I believe you are already a qualified programmer.

    But masters have two more things. Performance testing and performance analysis. to this point. You will need to have in-depth knowledge of each language or the underlying knowledge of the virtual machine. I won’t say much for a newbie like me

    reply
    0
  • Cancelreply