Here's a step 0 for your debugging strategy: spend a few minutes thinking about what could account for the bug. Prior to its occurrence, you are thinking about what could go wrong, but now you are thinking about what did go wrong, which is a much less open-ended question.
I've had large success by treating the bug as a binary search problem as soon as I identify an initial state that's correct and a terminal state that's incorrect. It seems like a lot of work, but that's underestimating just how fast binary searches are.
Depends of course on the nature of the bug whether it's a good strategy.
A subcategory of the design flaw I find quite a lot is the case where the code works exactly as intended, it's just not having the desired effect because of some erroneous premise.
I was such a bad developer that I realized I had to automate the re-running of parts of the system to find the bugs.
Of course, the code I wrote to exercise the code I wrote had bugs, but usually I wouldn't make offsetting errors.
It didn't fix all the problems I made, but it helped. And it helped to have the humility when trying to fix code to realize I wouldn't get it the first time, so should automate replication
Unit/integration tests are anything but a buzzword. And my intentions were not to belittle, but to praise.
Some actions simply make so much sense to do, that any sensible person (unaware of the concept) will start doing them given enough practice, and in process they "reinvent" a common method.