One strategy that was on my mind today: Whenever you're writing an API start on the "consumer" side. If you had the perfect version of this interface, what would the code that's using it look like? I find that if I start on the "implementation" side I'm more likely to come up with a solution that closely reflects what was easiest/most direct to implement, whereas starting thinking from the perspective of the user of the interface tends to lead me to better abstractions.
You can also use it when writing a block of code where you haven't decided what kind of functional abstractions or data structures you want. Write the code you wish you could write. Then fill in the code needed to support that.
This is 100% my coding strategy in every context where it makes sense. Code to an imagined ideal API that makes what I'm currently writing clear and concise. Once I have that written, I just repeat the process from the next level of abstraction down. This strategy has served me well over the years.
I like having static analysis for undefined names in my IDE for exactly this reason: I can write the program in the natural order (high level to low level), and then have a little reminder about what I haven't finished yet.
This is a great technique. I find it particularly useful if I'm stuck on writing some aspect of the implementation that I can't quite grok. Often pulling back and writing it from the point of view of a consumer of the implementation will help get me moving again on thinking about the problem.