A while ago, I was listening to a podcast where Scott Hanselman interviews "Uncle Bob" about SOLID principles and took some notes. These are all very idealistic principles, but pave the way for well designed code.
SOLID Principles
"The closest thing to commandments of software engineering." - Scott Hanselman (paraphrased)
Single Responsibility Principle
Group things by their reason to change. Lots of methods that act on the same data might change for different reasons. If they change for different reasons, they really belong in their own classes. Methods should have a single reason to change (highly focused). If you have two or three if statements, it should be separated out. "A place for everything, and everything in its place."
Open/Closed Principle
Modules should be open for extension, but closed for modification. Polymorphism is the primary tool for this, using abstract classes and interfaces. Make sure that the things that will have to change only depend on things that don't change.
Liskov Substitution Principle
This refers to the "is a" relationship, and the expectation that related objects can be substituted without awareness. These relationships should be carefully examined.
Interface Segregation Principle
Clients of a "fat class" should be revamped in such a way that they depend on an interface. If there are 10 clients of a fat class, then you would create 10 interfaces for each of the clients, and apply them to the fat class. That way, if the "fat class" changes in some way, clients that depend on the interfaces are unaware and are thus unaffected. This lends itself to a design ideology of the separation of volatile from non-volatile (i.e. “new” should never happen in non-volatile, or the abstract layer).
Dependency Inversion Principle
Make sure that all dependencies point to things that are abstract; don't depend on anything concrete. Very idealistic, and apply it when able. Violations of this principle belong on the volatile side.
I think these pictures can sum up the SOLID principles pretty well.