| I often practice test driven development. This can help, especially in dynamic languages, to structure your code in a way that forces you to keep it simple. 1. Write the test first, start with the smallest cases. 2. Write the code to make the test pass, the first thing that comes to mind which works. 3. Refactor what you just wrote. Use functions to remove unnecessary intermediate variables, avoid repetitive code by extracting common patterns, turn literals into parameters constants, etc. 4. Add another test, usually an inductive step. If your base case, smallest input is n, try writing a test that should pass for n+1. 5. Repeat 2-3 until the new test passes. 6. Add the smallest edge cases that should return an error result or fail. 7. Repeat 2-3 until the new test passes. Keep building up those tests as you go. They should form a low-level specification of a module, class, or function that suits your needs. Some high-level principles to think about when coming up with tests: 1. Parse, don't validate! [0] Code that takes data in from the outside world should do it best to parse it into an acceptable structure as early as possible so that code down stream doesn't have to check if the data it receives is valid or not. 2. Push effects to the edge If something has to talk to the outside world make sure it happens in, ideally, one place. Writing tests first ensures that your code is easy to test so putting effect-full code all over the place is painful. 3. There are different kinds of correct. Know ahead of time what success will be for your task. Passing tests is one kind of correctness. Functional correctness of the system is another -- you will want to reach to tools like TLA+ or Alloy to write specifications for the latter. 4. Talk to your team. Sketch out your ideas first and shop them around and spit ball them with other experienced team members. Get their take on it before you start coding. [0] https://lexi-lambda.github.io/blog/2019/11/05/parse-don-t-va... update forgot the link |