Fred Brooks says to plan to throw one away. It won't directly help you keep your final product simple, but if you don't worry about making your first pass beautiful, you can get through it faster and learn all the details about your solution sooner. From there you can simplify. (I'm talking at the level of writing a function or two at a time, then simplifying)<p>I like to throw together my first try however feels easiest. Special cases, multiple loops, wrong data abstractions, whatever. Once it works, I look at the big picture: where are my data abstractions hurting me? Where can loops be combined? what macro-scale blocks of code could be re-shuffled to be clearer. Then I recursively look at subsections until I've gone as far as removing the superfluous variables and ensured everything is named sensibly. <i>Then</i> I push the commit (not earlier, or it's too likely to be interpreted as 'done')<p>As far as anti-patterns that lead to unnecessary complexity:<p>* Is anything un-idiomatic (Python especially)?<p>* Is the same information stored/handled in more than one place?<p>* Is any variable being asked to do double-duty?<p>* Are errors being detected/signaled/handled too early? Too late?<p>* Can the data be re-organized to provide a more natural problem?<p>* Are there un-necessary branches? (Where applicable, develop an algorithm that works for all inputs, instead of seperate algorithms for different classes of input)<p>* Has anything been added because it's "basically free"?