Mistakes were made: how to make debugging easier

I had just finished dynamically placing windows onto the background of the level. To avoid working with shaders, I planned to program a script that will dynamically build the background around the levels.  Below you can see what I was aiming to create.

Finished Background

I planned out the entire code,  separated each smaller task into a function, and clearly defined my members variables.  The list I wrote is below:

Notes for what I want to do
        - Find all spaces that are valid and cover them with a background.
        - Scale the background to that size

        1. Find first valid space
        2. Find Invalid space in that row
        3. Measure area between spaces and save coordinates of space
        4. Go to next row
        5. measure up to same distance, if invalid space stop
        6. Spawn Column
        7. Make all those spaces invalid
        8. Go back to step 1 until all spaces are invalid

    Supporting functions Required
        - Spawn 1 wall with texture
        - Generate new texture
        - Keep track of scaling and offset of texture

This was were I made my mistake.  I programmed all the individual functions, then connected them all, then watched as nothing was working the way I planned.  I spent the next 6 to 8 hours debugging the entire program at once, because I had thought I understood what was wrong. It turned out that multiple different functions all had minor issues:  Inequality symbols facing the wrong way,  functions ordered incorrectly, and incorrect variables being used.  I only discovered these issues once I finally started looking at each function individually and analyzing their outputs directly.

When I was in college for Mechanical Engineering, a teacher once said to me, "When you design how your final project is going to work, also design how you are going to test it."  Although this seems like simple advice,  I needed to make this mistake to fully understand the depth and importance of this advice.  This advice was told with mechanical systems in mind, but can and should be applied to programming practices as well. When we as programmers make a functions we know exactly what we expect out of it, but we just assume it works the way to planned, no debug errors, no problems. Since we know how to test the function why not make sure each function works as we program?  Function 1 leads to function 2 so make sure function 1's output is what you wanted before moving on to program function 2.  

This is probably obvious to a lot of programmers, but it was not obvious to me.  It took me making a 6 to 8 hour mistake to learn to test each function as they are created rather than after the full system is created,  but it was a lesson that I needed to learn.