Giving it some more thought, I think it boils down to realizing when one is solving more than one problem, and then being able to write the code so that each problem is solved in isolation, yet without introducing complex APIs between the different pieces of code.
Often though the sub-problems are subtle and hard to predict, plus realizing that two problems are being solved is not in itself enough to figure out how to actually split it up (sometimes splitting things up contributes to the perceived complexity)…