Yeah, my experience has lead me to believe that planning the solution in relatively high detail before touching my keyboard leads to faster feedback, better designs, and fewer bugs.
I’ll generally take a pad and pen and write down my requirements and assumptions. This helps flesh out any further information I’ll need before I begin.
Once I’m satisfied that I understand the problem I’ll sketch out a planned architecture (dependency graphs, data structures, etc). If this uncovers more missing information then I’ll get that information and revisit the requirements and assumptions. Sometimes the missing information is that I don’t actually know how to do something in the particular environment I’m coding in. In that case I’ll prototype the minimum code I need to figure out how to do what I need to (I never use the prototype in production code).
Once I have a planned architecture that I’m happy with, writing the tests and code is relatively mechanical and straight-forward.
I’ll do this for pretty much any change to a codebase that is more complicated than changing a single function.