The basic strategy I use now in writing new code is this:<p>1. Write out requirements in a form following RFC guidelines: the keywords like MUST, CANNOT, etc. are very, very important because they can be broken out into a spec for a single codepath or function: when your spec says "it always has to do this, and it can never do that", you can make simplifying assumptions.<p>2. Skeleton code: Your first run at the problem should be to attempt to return answers statically: if "a", return 1, if "b", return 2, and so forth. Many practical engineering problems are effectively "lookup table code" with routine answers and do not need a solution more complex than this. This can help even if your spec implies that a non-linear solution with some kind of algorithm is called for, because it immediately gets you to a point where you are filling out enough of the spec to see if you need to revise requirements, and you can build tests in tandem with this process. Often a run at the problem fails not because you can't keep going, but because you realize that you can define it in a more simple way. You want to iterate towards the simple because the alternative is to heap up requirements that are more incidental in nature(e.g. a feature that exists because of two other features that produce edge cases when used together - a very, very common outcome in complex systems).<p>3. Algorithmic strategies. OK, you've filled out enough to know that you need an algorithm. What class of algorithm will it be? In the majority of cases it'll be one of these:<p>"I have an analytic problem using a standard math formula" (therefore you implement the formula)<p>"I have a sequence of symbols that needs to be mapped into a different sequence of symbols" (this describes most parsing problems)<p>"I have a data collection or an answer set resulting from a prior event that needs to be searched, ranked or ordered" (list processing, constraint solving, AI; if the data needs persistence, serialization formats, databases etc may come into play.)<p>Master application of just those strategies, and you've covered many domains of programming entirely. A lot of the literal aspects of coding appear in setting up and tearing down the environment needed to apply that core algorithm, and then in providing enough of a user interface to configure the environment(whether it's an application user or another developer interacting with the code later).<p>At scale, code is building on other code, but in the sense of "communicating with a ghost". You don't get to dictate how older systems and APIs that you're building on behave. Often you can abstract them, but that only means you're talking with your abstraction, which in due course turns into another ghost if it actually gets put into production.