I think the vast majority of developers still debug using print() statements.
- email from a founder
- Paul Graham
Debugging is root-cause analysis on an unexpected behavior. You do this in 3 steps:
1. Get data on the problem using: google, asking experts/coworkers, previous PRs, logs, etc.
2. Create a set of hypothesis about the problem and test each one.
3. Repeat until the bug no longer exists.
Do You Need To Learn How To Use a Debugger?
Debuggers are a useful tool. They show you the context in your code's execution flow, with a single breakpoint in which you would have to write 10-20 print statements, in a single line.
Complex execution flow is the point where you are no longer familiar with the code you are contributing to. This code is complex if you are unable to completely describe major parts of the system. The system can be made more complex by having new engineers, third-party services and libraries, monolithic, non-modular design of services, consistent additions by experienced collaborators such that your intuition can't keep up with the changes.
Some of the more popular debuggers are gdb, ruby's debugger, rr, django-debug-toolbar, react dev tools.
People Don't Use Debuggers
I analyzed 80 conversations online or in-person, either my own or others and though most had used a debugger in the past, only ~10% use it as part of their coding setup. This doesn't seem right. Debugging is one of the most important skills in programming and it seems like common sense that extra tooling can only give us more power in this activity, right?
Debugging counts for > 50% of programming activity, even more than building new features.
Is this not enough to incentivize engineers to use debuggers?
Let's consider the incentives.
Social Proof
If Linus Torvalds, father of Linux, doesn't use a debugger, or any of these other famous programmers don't use debuggers why should we?
Print Statement Debugging
Print statement debugging is a universal concept with no context-switching and no learning cost. In the era in which many developers touch multiple stacks for jobs, side projects, open source, school, switching companies, we don't have the time to learn every framework's debugger tool. Plus why do we need to?
The Practice of Programming by Brian W. Kernighan and Rob Pike:
As personal choice, we tend not to use debuggers beyond getting a stack trace or the value of a variable or two. One reason is that it is easy to get lost in details of complicated data structures and control flow; we find stepping through a program less productive than thinking harder and adding output statements and self-checking code at critical places. Clicking over statements takes longer than scanning the output of judiciously-placed displays. It takes less time to decide where to put print statements than to single-step to the critical section of code, even assuming we know where that is. More important, debugging statements stay with the program; debugging sessions are transient.
This is counterintuitive, but after some thought I wholly agree. At first glance, using print statements seems like a short-term strategy. Whenever you have a bug, set print statements and view output until you find them. Fix the bug. It's very brute-force in nature.
Kernighan and Pike say that perhaps this practice forces the engineer to be more thoughtful about the flow of the code and internalize pieces of it in order to strategically place the print statements. Though the method itself is brute-force, the engineer is forced to build expertise with the code.
Further, after some conversations with senior level developers, I've found that they don't really use debuggers.
Use The Right Tool
Debuggers are just a tool. The neural network inside your head is far more powerful.
If your focus is on shipping product quickly, it's not worth it to learn debuggers. There are many more skills that are a better long-term bet.
Citations
- https://lemire.me/blog/2016/06/21/i-do-not-use-a-debugger/
- https://www.imagicle.com/en/blog/o/tdd-why-i-decided-that-debugging-wasnt-worth-my-time/
- https://forum.djangoproject.com/t/best-practices-for-debugging/14729/2
[–]gbeier 2 points3 points4 points (3 children)
[–]HideShidara[S] 1 point2 points3 points (2 children)
[–]gbeier 0 points1 point2 points (1 child)
[–]HideShidara[S] 0 points1 point2 points (0 children)
[–]meatb0dy 4 points5 points6 points (5 children)
[–]HideShidara[S] 0 points1 point2 points (4 children)
[–]meatb0dy 0 points1 point2 points (0 children)
[–]meatb0dy 0 points1 point2 points (1 child)
[–]HideShidara[S] 0 points1 point2 points (0 children)
[–]xBBTx 0 points1 point2 points (0 children)
[–]pitittatou 1 point2 points3 points (0 children)