
Executional abstraction; The role of programming languages; States and their characterization; The characterization of semantics; The semantic characterization of a programming language; Two theorems; On the design of properly terminating; Euclid's algorithm revisited; The formal treatment of some small examples; The linear search theorem; The problem of the next permutation.
The architecture of Concurrent Programs, Per Brinch Hansen
Literate programming--see http://www.literateprogramming.com/
I don't recommend Design Patterns, as these are elements needed if your programming language is inadequate.
There are many more.
Even though I don't use any of his techniques, Dijkstra's "A Discipline of Programming" did affect the way I see things considerably.
And there's it's big brother Predicate Calculus and Program Semantics by Dijkstra and Scholten that more rigorously formalizes the same approach.
Dafny[2] is one approach out of Microsoft Research that attempts to provide automated tooling around some of those concepts.
All of the above are excellent places to start if you're interested in learning how to write better code with the imperative languages that you're actually going to use professionally.
Being able to apply mathematical reasoning to programming is perhaps the main reason to use a functional approach. But mathematical reasoning isn’t restricted to functional style programs! All imperative programs can be described by purely functional mappings between points in a program state space with each in scope variable naming a dimension.
1) A Method of Programming.
2) A Discipline of Programming.
Browse the EWDs and read those whose titles interest you. My favourites are those dealing with Program Correctness and Languages.
Note that understanding Dijkstra can be hard; so don't be discouraged if you don't "get" something at the first read.