For further actions, you may consider blocking this person and/or reporting abuse
Read next
Looking for an app where I can take a screenshot of a few different numbers and it'll sum them up!
Michael Tharrington -
Learning New Things
Rohit -
Bad Management Kills Your Favourite Tech Company or How Software Companies Die
Dmitry K -
6 Tips for Creating Better Website Surveys
Syed Balkhi -
Oldest comments (23)
Run the same code 4 more times to make sure itโs a real bug. If it is, itโs time to get the rubber ducky๐ฅ
If ducky can't help, I just ask this senior web developer for advice!
Get systematic: Remove possible variables in the code until you can isolate the problem. This is why it's important to be disciplined with your version control so you can freely delete swaths of code without complicating your life by being in the middle of some huge edits when you're trying to do it.
Add a failing test.
Debug it in isolation
I got a few:
Use breakpoints.
I agree with what people already wrote here. Maybe good idea would be to take pen and paper and draw what code does on more abstract level and then start with rubber duck method.
Sleep on it
I can't even remember how many times I was stuck on a problem for hours and it just took some minutes to solve the next morning after some rest
Planning for debuggability
Find a way to reproduce reliably, and quickly, and if possible, in an automated fashion (either through a unit test, or through an automated interaction, say scripting a browser). This means planning for mocking components, so that when a bug happens, writing a reproducible automated piece of code is just minutes away
When designing your system, design for debugging tools. For example, redux allows you to use the redux devtools to log, replay, export everything that interacted with the store. State machine frameworks often offer similar functionality.
Do preemptive logging. If you are able to log inputs and outputs of your system, do so. This will allow you to catch which inputs led to a bug in production, potentially sidestepping the entire debugging process itself.
Leverage git bisect
Now that you can quickly identify when a bug happens, use
git bisect
(which you can now run fully automatically) to identify the first commit that introduces the bug. Look at the commit to see if anything comes up. Usually, it gives you a sense of which files were modified.Focus on logging
Rely on printf debugging because it gives you debug logs to pour over, instead of single stepping slowly. You can also use automatic actions on breakpoints if you don't want to litter your code.
Use stacktrace logging and structured logging to augment the richness of your printf debugging. Log into a sqlite database, for example.
Log inputs and outputs of your system.
Ideally, you want to run your failing test case once, and figure out the bug just from looking at the logs.
Know your breakpoints/watchpoints
Set breakpoints and watchpoints to get an overview of what is going on. Be aware that breakpoints and watchpoints slow both you and the program down. Depending on what you are debugging, that might actually influence the behaviour of the system significantly too.
Single step when you think you know what might be causing issues, in order to inspect memory and get a look at the stack trace. If you think you know what might be causing the issue, use breakpoint conditionals and watchpoints to confirm your suspicion.
Explain the bug to someone else
Try to explain the bug to someone else, in the dumbest terms possible (don't make assumptions). Use a whiteboard or show the code if possible. Often the rubberduck effect will kick in, and the bug will magically solve itself.
Take a walk
After fighting a bit with the bug, actually take a walk. I used to be a smoker, and I can't even remember the number of times I solved a bug when going downstairs to smoke a cigarette. Now that I don't have the nicotine withdrawal, I have to actively remind myself to get my butt off the seat and go walk a little bit. Mild physical activity has proven link to solving problems in the subconscious.
More crazy techniques that I've used in the past, especially to figure out weird edge cases:
This is something you should do anyway, but:
put your system under immense pressure, and introduce faults into different subsystems. Every piece of software is going to break at scale in some way, might as well figure it out early. Bugs often happen in the error path / through cascading failures in the sidepath.
Embedded software
In embedded, be very careful with debuggers. They often shred the performance and behaviour of the system under test. If you can afford it and EE put in the right connectors, use a full CPU instruction trace debugger.
Use logic analyzer + scope and as many traces as possible. Know your tools inside and out (trigger settings, bus decoding, recording, etc...). Make sure the impedance of the probe doesn't mess with the signals (see next point).
Don't underestimate the power of putting your finger on communication buses / pins / power lines (provided they are low voltage). If the line starts going haywire on the scope while holding a finger somewhere, you have faulty traces or are missing proper impedance or bus termination. Many a bug is actually a badly connected bus line / missing pull ups.
Also, don't forget to check that your device is actually powered on: often, your device will get backpowered through the debugging adapter in the first place, and barely operate because of the low current (very fun).
Embedded again: use LEDs a lot, potentially even build additional LED boards that you can attach to subsystems without influencing voltage too much.
Again in embedded, use a little circuit with an amplified piezo, and put it on different communication lines or gpios. You can tick certain loops of your program, or toggle a gpio in an interrupt. Connect the piezo, which will start clicking in frequency. The human ear is very very sensitive, and you will identify any change in frequency or irregular patterns without even have to look at the device or the scope.
Use musical notes
Use MIDI events to debug your code instead of printf. For example, webmidi is very easy to use in the browser. Connect it to a synthesizer and choose notes for different events (or samples). You can now listen to your code executing, and don't have to look at the debugger / log output. You can hear if an unexpected event happens. The human brain is strongly connected to audio, chances are you'll remember the "melody" of a bug happening, which will allow you to figure out the execution path taken.
Woah, that midi technique sounds amazing, honestly! Are you using that on a regular basis?
No itโs been quite a while honestly but I was thinking of bringing it back out and making a nice example!
Yeah agree the midi sound technique litterrly sounds super intereting!
console.log
Jokes aside, learn the tools you have at hand to debug. There are plenty and your IDE has support for it. Learn it once and save a lot of time!
Everything everyone already said here, and:
You can use any system you like, from scattering logging calls or
print
statements to a fully-featured debugger. What you're most often doing is watching the state of variables and state data at different points in your code.You'll think something like, "this is a problem with X, so I should look at things that touch X". The tip here is that if it doesn't immediately jump out at you, then it's probably not anything to do with X and you should start browsing around for anything that looks suspicious. Don't get hyper-focussed on it thinking, "it must be a problem with this or that function".
Once it's done, you should have come with a fix. But before you apply it and commit it :
Run the test and check the code is failing, as before with the user and with you when you debugged.
Fix the code
Run the test, it should be green now
Commit and take your day off !