This brings to mind what Christopher Alexander (an architect, and the inventor of pattern languages).
Architecture is traditionally a visual discipline. However Alexander says that in the first stages of a design, when we are exploring user need. We should use linear language (spoken, written, even sign-language e.g. BSL ).
However we need to keep ideas simple.
Therefore
- Consider what a function/procedure/variable does, before considering how it will do it (or whether it will be a function, procedure or variable).
- Decide how you will test it before you write it.
- Write only as much code that is needed to make the test pass.
- Write only as much test that is needed to make the test fail.
- Keep each function/procedure/variable simple: ensure it does one thing, and consequently short.
- Name functions/procedures/variables well: give them names that make sense at the point of use.
I have the same problem.
I sometimes work with people that are brilliant. They create code that is so complex that even they don't always understand it. I can not do this. My code is simple. My code has very few bugs. My code has higher functionality. But I just can't write complex code.
I can't debug complex code. However I have found that I can guess where the code will break (without really understanding it), and am very good at finding some of the bugs (no one can find them all in overly complex code, not even brilliant people).
I think it is this inability that has led me to investigate and discovering methods to writing software, that have a high probability of producing bug free, easy to maintain code.