One very useful thinking tool I've used a lot when evaluating code is the concept of "Levels of Perspective". I haven't seen too many references to this concept, I orginally saw it as a simple side bar in UML distilled by Martin Fowler. There's a few people who have picked up on this idea and I find it really good. I have another blog post sitting in draft where I was going to flipantly make reference to this idea but I thought I should blog on it for those who may not of come across it. It's a fantastically useful tool because I find in a lot of peoples code these perspectives get mixed up willy nilly and its a great tool to work out how to start refactoring a tangled mess back to sensibility. When pointing out this idea in relation to code I see people going "Ah!". (hmmm, wonder if I've praised this concept enough?)
The levels of perspective are :-
The conceptual perspective is to do with classes of objects in your design. What responsibility each object has and hence where methods should live. Common mistakes you can make when you get this wrong is methods on the wrong object hence some objects knowing too much about other objects. Names of classes and methods dont make too much sense when trying to explain your design. Abstract and concrete concepts are mixed together ( I'll do a blog post on this one a few posts down the track because this is one of the main causes of bad design that I've seen, but, theres a few other ideas I want to chuck out there first).
The specification perspective is the particular steps you need to take in order to fufill a responsibility. eg a Move responsibility would require a "Remove From Source" and "Add to Target"
Implementation is the actual code that achieves a particular step of the specification.
A common thing I see is that specification and implementation stuff get mixed together. Often this is done innocently at the beginning but can start making the code confusing as it evolves. Simply separating out these two perspectives can make for much simpler methods.
Once you have specification stuff separated out it then gets simpler to pull this out as an interface then you can vary the implementation by simply providing different objects that implement this interface which then allows for any kind of dependency injection (blog post to follow later....). If your using a language which has duck typing then this is even easier. The specification also helps with talking abstractly about how to solve a problem which then helps you rationalise about the closure (blog to follow later...) of the abstractions you have made. What I mean by this is that you create a language where you can fully talk about the concept your working with.
For example if you are working with a stack, the language "push", "pop", "top", "empty" provides a language to play with stacks. If you forgot to put the "empty" method in then you wouldn't have closure and it would get harder to express how you want to manipulate a stack.
So developing a good specification perspective helps you rationalise about your objects, it helps clear up abstractions, which provides good language that helps you write more understandable code.
All of this is nicely summed up with the "Open Closed Principle (OCP)" (bog to follow later...). A fundamental idea of OO deisgn but OCP is almost too simple of an idea that its often hard to appreciate the subtle influences it can have on your design. That's why I think you need a bunch of thinking tools, like levels of perspective, to help you reflect on how all these thinking tools work.
There's a lot more that could be said about levels of perspective that I could be here forever! However this idea overlaps with many other ideas and I'll refer back to this idea in other blog posts which will hopefully shed more light on all of this.