Hacker News new | ask | show | jobs
by hzhou321 2609 days ago
When you live in the debugger, you understand your code by seeing how your code work. When you live without the debugger, you have to imagine how your code work. The speed of seeing how your code work cannot match the speed of imagining how your code work. In addition, see your code works brings a lot of noise that is not part of your focus; in contrast, you only imagine where you focusing. Of course, the effectiveness of each depends on your experience in each respectively.

There is no denying that seeing is the real world, and imagining is just imagination :).

4 comments

Being able to visualize your code in your head is a great advantage, and I've fixed many bugs that way. But sometimes your imagination hits its limits and using a debugger to understand what's happening in the code is very useful.

Some cases where your imagination could be limited are:

- Code that you didn't write.

- Code that you wrote long enough ago that you don't remember the details.

- Code that you know very well, but you're having a bad day and can't figure out the problem just by thinking about it.

> Some cases where your imagination could be limited are:

> - Code that you didn't write.

This has become the norm with software written by a team; and to my stress, I find many coders have given up understanding code that other people wrote and reduce to the minimum that get by. My premise is the necessity of understand the code -- not only how the code work, but also how the code is conceived and where the code is evolving toward. After that premise, there is no difference between code that you didn't write or you did.

> - Code that you wrote long enough ago that you don't remember the details.

That says a lot that the code was not written in its optimum way. Treat that as a bug, and debug why the details cannot be easily retrieved.

> - Code that you know very well, but you're having a bad day and can't figure out the problem just by thinking about it.

You should always take a rest and tackle it the next hour or next day when you can work effectively. Continue to push through a bad day only has the opportunity to make the day worse.

That says a lot that the code was not written in its optimum way. Treat that as a bug, and debug why the details cannot be easily retrieved.

I wrote code dealing with railroad car repairs years ago.

https://www.railinc.com/rportal/documents/18/260737/CRB_Proc...

Should I be able to remember all 200+ pages of the audit rules by heart for both the car owner side and the repair shop side and remember why I wrote all of the special cases?

If you are writing special cases because a 200+ page rulebook says you need them, then the special cases should be commented to indicate exactly what rule they are meant to address such that someone with the rulebook can quickly look it up.

Ideally, you would have all the rules encoded in a central place so this lookup becomes obvious from the structure of the code, but that is often not possible.

I am involved in a simmilar project now. We have a proprietary data format which has, over the years, evolved slightly different versions as different teams extended it in slightly different and incompatable ways. The code has all kinds of special cases, to the point where we developed internal style guidelines for how to comment them

So now you have the rule book and the comments and if there is a bug in any of the code, an I suppose to remember what all the code does and think through it? Am I suppose to be able to just think through why the one set of hundreds of records that came from one of 200+ repair yards is giving back erroneous results or should I just use a debugger and set a conditional breakpoint?
In this particular case you should probably implement some logging or alternative output that shows how the rules are being applied. Also perhaps the rules shouldn't be part of the code itself. It would be preferable to be able to add/remove/update a rule without needing to deploy a new version of the program (without going down the rabbit hole of implementing an entire logic engine).
Even when I’m starting a program from scratch It’s not just my code I have to understand, it’s all of the libraries, franeworks, APIs, etc. I’m integrating with.

For instance, am I suppose to “imagine” how all of AWS Boto3 functions work?

https://boto3.amazonaws.com/v1/documentation/api/latest/inde...

What reason is there to think “Imagining how your code works” should always be faster than “seeing how your code works”? It is certainly the case that sometimes one of these is faster than the other but it’s gonna be codebase, tooling, and scenario dependent which one actually is faster.
Did I say "always"? If I did, that is not the point.
I’m trying to think through why removing the debugger should help one build a mental model of the code faster than having constant access to one.

I guess I can imagine workflows that are overly debugger dependent - the programmer has a “trust nothing” mentality and checks the behavior of the code against their mental model of the code “too much” thus slowing them down.

But I think theres reason to think the programmer can maintain a mental model of the program while using debugger queries to verify aspects of that model in a way that’s a lot more efficient than relying on mental model alone. Beyond that at some point observation of the behavior of the program will come into play — and I don’t see why utilizing the power of a debugger to generate a lot of precise observations quickly isn’t a pure win ...

Seems that you are agreeing with imagining and use debugger to verify is a lot more efficient. And for verification, print is more direct than orchestrating the breakpoints and then print with debugger's syntax (or gui navigation).
I see imagination as a processor's L3 cache. It's really fast and ideally you want everything to be in there.

But it can only fit so much so I prioritize hotpaths to live in my imagination.