One trick I found very useful and it has helped me in the past is write doc before, during, and after you code.
When designing an API to be used by other people I usually document the design before writing code. If I was over engineering the design, the design spec usually full of conflicts and nonsense.
During coding, I usually stub out the class definition and function body and start writing doxygen comments for them. In the comments I'll have use case, sample code, and assumptions of the interfaces. During this phase, before too much real code is written, the class interface usually gone through redesign multiple times. I know I was over engineering when the sample code is hard to write and I have a hard time explaining the interface. A lot of the bad design ideas are exposed and eliminated when you try to explain to people how to use your API.
After coding, I replace the sample code in the comments with real compiled and tested code copied from my unit tests and further document the behavior of the interface. Another sign of over engineering is when my unit tests cannot keep up with the interface change because there are too many moving parts and too many ways to do the same thing and unit tests growth at an exponential proportion.