If you are getting stuck with number 3, the best thing I've found is to just start coding the problem in isolation. You are probably trying to jump from zero to the most elegant solution. Solve the simplest case first, in the simplest way possible. Throw all your OOD/Design Pattern/Best Practices knowledge out the window, and just solve the simplest case. From there, solve the next case, and the next one, eventually you will start to see the pattern, and the correct abstraction. From there, you can derive the elegant solution that fits all cases.
That is the problem with most solutions you find printed in books or on the web. They only show the problem and the fully refactored solution. Refactored solutions, even when fully explained, are just another form of obfuscation. Behind every tough problem, there are notebooks and whiteboards and hundreds/thousands of lines of discarded code that you never see. That is where the magic happens. You just have to do the work, you have to make your own ah-ha! moment.
This process is a lot easier if you use a language that has a REPL - like python, ruby, or the various lisp dialects. It is easier to work through problems this way, regardless of what your final target language may be.
"You are probably trying to jump from zero to the most elegant solution."
Oh god, yes. I realized recently that in practice, it's not done that way. Hard habit to break, though. I used to think that being smart meant that solutions were obvious.
That is the problem with most solutions you find printed in books or on the web. They only show the problem and the fully refactored solution. Refactored solutions, even when fully explained, are just another form of obfuscation. Behind every tough problem, there are notebooks and whiteboards and hundreds/thousands of lines of discarded code that you never see. That is where the magic happens. You just have to do the work, you have to make your own ah-ha! moment.
This process is a lot easier if you use a language that has a REPL - like python, ruby, or the various lisp dialects. It is easier to work through problems this way, regardless of what your final target language may be.