1. Start small, then extend.
    1. Always start by making a very simple version with almost none of the required functionality. Then, extend the solution step by step, until it does what it is supposed to. It’s almost impossible to plan everything out in detail from the beginning.
  2. Change one thing at a time.
    1. When you develop, and some tests fail, or a feature stops working, it’s much easier to find the problem if you only changed one thing. In other words, use short iterations: do one thing, make sure it works, repeat.
    2. If you have to refactor the code before you add a new feature, commit the refactoring first, then (in a new commit) add the new feature.
  3. Add logging and error handling early.
  4. All new lines must be executed at least once.
    1. Before you are done with a feature, you have to test it.
  5. Test the parts before the whole.
  6. Everything takes longer than you think.
    1. Especially in programming. It is hard to estimate how much time a feature will take even if everything goes smoothly, and when developing software, it is quite common to run in to unexpected problems.
    2. Hofstadter Law: “It always takes longer than you expect, even when you take into account Hofstadter’s Law.”
  7. First understand the existing code.
    1. Most coding requires changing existing code in some way. Even if it is a new feature, it needs to fit into the existing program. And before you can fit the new stuff in, you need to understand the current solution.
    2. Reading code is a skill that is as necessary as writing code. It is also part of the reason why seemingly small changes can still take a long time – you must understand the context in which you make the change.
  8. Read and run.
    1. Fortunately, there are two complementary methods for understanding code. You can read the code, and you can run the code. Running the code can be a great help when figuring out what it does. Be sure to make use of both methods.
  9. High cohesion, low coupling.
    1. High cohesion (the degree to which software elements are related) and modularity (how interchangeable or plug-n-play components are)
    2. Low coupling (the level of interdependency between software elements)