There are many ways to become a better programmer, and many concepts that can help you, but if I have to pick one, start by mastering TDD and learn how to write tests at a single abstraction level. After that you can denounce TDD for all I care, but master it first.
It will teach you the difference between working code and provably correct code, and the difference between code that works on the inside and code that serves its clients on the outside.
It will help you to move away from "write once, suffer forever" code, towards code that remains infinitely maintainable.
There are valid criticisms of TDD, but I posit that unless you have intensely applied TDD for 6-12 months, the criticisms you can come up with are bullshit rationalisations.
WRT to the point about single abstraction level: If I have test that, say, clicks a button and then checks the result in a database, I'm mixing two levels (DB and UI). Same for calling a method at a higher level domain concept and testing it at a lower level concept.
A good test is about observable behaviour in a single level. In the test, execute some behaviour and then test the outcome at the same level. If you can't, it's a design smell.
BTW some the valid criticisms talk about type systems, type driven development, property based testing, the fact that TDD alone isn't going to magically give you good design, and that sometimes you can't TDD your way into a solution and you just have to crack the algorithm.
A productivity booster that is universal for all programming activity, is to reduce the time between having an idea for a solution, and being confident that it works. PBT, formal modelling etc give you higher confidence but TDD gives you a practical amount of confidence _fast_.