These days, if I were to write code it would be Java or even Haskell, and I would design the heck out of the system using UML, incorporating design patterns. Given half a chance, I’ll specify the operations formally, using OCL; and if you give me total freedom, I’ll specify it in Z (i.e. symbolic logic and set theory) and mathematically prove the design before coding.

Some of the software engineers that I’ve taught absolutely love this approach. They’re the ones who, if their software fails, have to live with the fact that someone has probably died.