Writing code backwards helps you:
- Clarify your thinking
- Write cleaner calling code
- Avoid YAGNI pitfalls
What Does it Mean to "Write Code Backwards"?
If you want to avoid compile errors while you write code, you need to create a function or sub before you try to call it.
That's why when most people write code, they start by writing the function or sub first, and then they write the code to call that function or sub. That seems to be the normal way of doing things.
When you write code backwards, you don't worry about those initial compile errors (compile errors are cheap and easy to fix). Instead, you start by writing the calling code first. Then, once that high-level code is in place, you fill in the details.
Here's the step-by-step approach:
- Write a code comment for each step.
- Convert each comment into a procedure call (ignore the compile errors).
- Write the declaration line for each procedure (i.e., its method signature).
- Write the body of each procedure.
- Create additional nested subroutines as needed.
Clarify Your Thinking
If you love to write code, it's tempting to jump right into developing the smallest details.
As soon as I encounter a challenge, my mind starts racing to solve it. But, for me at least, my mind doesn't start with the big picture. Instead, it starts by attacking the smallest details. And, as I begin forming solutions in my head, I feel a compulsion to translate those ideas to code.
This is the exact wrong way to solve a complex problem, though.
A better approach is to step back and take a wider view. Approach the problem from the top down. Start by writing the half dozen or so steps needed to solve the problem. Only after you understand the big picture should you start working on the details.
"Writing code backwards" forces you to think through the problem in a structured way.
Write Cleaner Calling Code
How many times have you written a procedure or function, only to realize when you try to call it that the calling code does not have some key piece of information you assumed it would have when writing the routine?
When this happens, there's usually a large sunk cost in the form of development time that you spent writing the routine. Due to the sunk cost fallacy, we as humans will go to great lengths to avoid having to throw out something we've already spent time on, even if that would be the most efficient choice. Instead, we'll twist the calling code into knots in order to make it mesh with the poorly designed underlying routine.
If you start by writing the calling code first, you can avoid this problem entirely.
Avoid YAGNI Pitfalls
YAGNI is an acronym for "You Ain't Gonna Need It."
Oftentimes when writing code, we get so caught up in accounting for every possibility that we end up overengineering the solution. We make the procedure more complicated than necessary. We add support for parameters that will never get called. We add handling for code paths that will never be reached.
While these things may seem innocuous, they contribute to the project's technical debt.
Refactoring the code becomes harder. You have to check to make sure you handle all the possible values that could be passed for a given parameter, even if in practice only a single value ever gets passed to the parameter. You have to apply refactoring to areas of your codebase that never get reached. Other developers (or future you) will see an unreachable code path and assume that it wouldn't exist if it did not serve some purpose. In other words, it will appear to be "the exception proving the existence of the rule."
When you start by writing the calling code first, you don't have to wonder what parameters the routine needs to support; you will know them by virtue of them being variables in the calling code.