- understand your whole system before you code
- list possible data by kinds that need to be processed differently at each point in control flow
- look for what changes together and what changes independently and adjust the code flow so you don't need to test for the same things twice
- when requirements change - don't do workarounds and quick hacks, change the underlying mechanism
- solve problems at the level they originated, not at the level they were detected (for example null pointer is better solved by returning empty collection than by copy pasting if (x!=null) all over the place)
- don't treat anything like black box when you need to change something - if you never change things inside black boxes you will get a lot of nested black boxes doing the same thing over and over, just slighlty differently - this is wrong, no matter what OO theory says about hermetization