I've learnt plenty of programming languages, from C to Java to Squeak to Haskell to Lisp, but I have not made as many 'finished' programs as I'd like.
I've found, despite knowing and using plenty of programming constructs, I've not really managed complexity as well as I'd like.
The result being my programs end up being too complex to maintain, with the ultimate result being they're left to rot in some directory in my filesystem.
I've heard of 'Thinking in Java/C++' and 'The Practice of Programming'. Does HN have any recommended books on software design?
You already know more programming paradigms than most working programmers including those that have contributed to software you use daily. That's great and invaluable. Each of these paradigms told you something new about managing complexity (message passing in Squeak, reflection in Java, metalinguistic abstraction in Lisp). You can now apply them outside of those languages (that's what Design Patterns are about): multiple dispatch via Visitor Pattern in Java, message passing OO in Lisp[1], interfaces and implementations in C and so on.
[1] http://okmij.org/ftp/Scheme/oop-in-fp.txt
What you don't have is practice applying these lessons iteratively: put in effort, ship something (even with inadvertent mistakes), receive constructive criticism, find bugs and missing features, put in effort to improve design as needed to add features and fix bugs, ship an improved version and so on.
You're afraid of shipping something you're embarrassed of, or of failing to ship something that delivers on its promises. Every programmer feels that, it's perfectly natural and fine: its what motivates us to improve. Acknowledge this fear, but don't let it paralyze you.
There's a Russian proverb: eyes fear, hands do. Apply it.