When faced with ugly code I learned a simple pattern. First I would break the code into paragraphs and comment it liberally. Since I hate code that requires comments, my next step is to take one comment at a time and change the code to make the comment unnecessary. Often that is the matter of changing a variable name or function name. Sometime it takes extracting a function or method. Sometimes it means introducing explanatory variables. Eventually the code doesn't need any of the comments anymore. It is smaller and cleaner and usually faster as well.
Then I started working with teams. I found that teams accrue process and practices the way that code acquires comments. They are in a difficult situation, and so they add more steps, more process, more tools, more tricks. Ultimately ripping away the existing process will leave the team with the original problems and no coping mechanisms, just as deleting comments would have left the code just as crufty and perhaps more unreadable than before.
The secret with the code wasn't to rip away the coping mechanisms, but to obviate them and then remove the redundant comments.
Now I'm seeking out coping mechanisms, looking for ways to fairly judge them, reach beyond the coping mechanisms and obviate them, and replace them with something more functional. It's a simple pattern but surprisingly hard to apply at times.