JavaScript's Anxieties: Shifting Gears from Ruby, pt 1

Posted by Craig Donavin on March 4, 2020

A message my instructors at Flatiron school emphasized repeatedly to their cohorts was “Don’t become reliant on test feedback to get you through”. I believe the JavaScript section was designed quite specifically to wean us off of our dependence on prebuilt tests, like those in RSpec files in our coding labs.

Of course, there were always other ways of checking our work before running a test or walking through an app we just built. In plain ol’ Ruby, there was irb, that little virtual playground to create anything we saw fit and then a bang and an exit and back into the real (Bash) world we went. After that, there was binding.pry (implying there were other methods I could call onbinding, but I haven’t learned them, yet), which acted more as a peek under the curtain. Most importantly was that it stopped your code from running before it threw out the massive stack trace indicating you forgot to put an end somewhere. Little did I realize how much I would miss that enormous stack trace. When moving to Sinatra, and later, Rails, the nature of the multi-view, multi-page structure meant that you’d get a big red error screen if you forgot something. Big glaring instant feedback whether it’s a missing route, an undefined variable, or forgot to close a tag. I couldn’t quite absorb how this changed in JavaScript and some of the lessons were so hard to grasp. While the lessons in Flatiron’s modules are fairly concise and tend to be very germane to the upcoming project, it was such a shift from Ruby that it took me a while to process how things like context would affect me right away. (I’m waiting for the other shoe to drop regarding functional programming). It was learning to test for context that finally got the momentum I needed to finish the project.

First, let’s go to our feedback bits. With Ruby, you could use a built-in method like puts or print to quickly log something to the console. There are a few other ways to do things like this, such as VSCode’s logpoint feature (particularly nice because it requires no input to your code to function, meaning you could leave it in all the way to production). Similarly, JavaScript has the console.log feature, which you’ll make a looooot of use of throughout your time in Javascript. I had dismissed the use of this method, because when I was doing labs and exercises, I just used the values read out in the test messages. Since console.log didn’t return anything, I didn’t see it as valuable, and I deemed it less so when moving to front-end development. Little did I realize, it would prove as an invaluable tool for testing return values on things like fetch and map methods, effectively showing me the output at whatever stage of the function or app I wanted to see. It’s not even a bad idea to just put console.log(this) to see if there was a change in context.

Another invaluable tool is the JS debugger tool, which you can drop in with the line debugger. [Note: I’m pretty sure this is a JS thing and not a VSCode thing, happy to take correction on this if I’m wrong] Similar to binding.pry, this pauses this code run in place, and gives you a couple other controls. One, in the browser console, you are effectively in the app’s space, meaning that all of your variables and functions are “there” and available for you to test. Type in this and see the object printed out just below. Type this. + different objects and functions in your code and see the output in the current state. The other thing is that it lets you advance the code line by line. If you have a function returning undefined that wasn’t at an earlier point, now you can see exactly when it stops returning, just by advancing the code and checking the function in the console, at every line if you need to.

So here’s where some of my major slip-ups occured. First, remember all that stuff I said about console.log? I sure didn’t think I needed that, and as you might guess, I sure wasn’t keeping my console open. So I’m sitting there, clicking buttons, typing code and reloading the page, and I have no idea nothing is happening. Well, had I had my console open, I probably would have gotten the necessary feedback that I needed to put my script paths in my index.html file. Later on, actually reading the error messages would have told me that my fetch function (not just fetch(), but the function I call to use it) needed a return stuck in these somewhere to, you know, return the output. Instead, I just assumed I knew better and spent an undue amount of time in my API looking for a problem that didn’t exist.

The other blocker I ran into was a context issue. I had a Form class to handle one of the forms created in the app. A handleClick() function was created to take the values of the inputs, gather them into a params object and send them in a POST request back to the API. The problem is that I somehow had to grab data from the current customer object, which was well-defined in my App class, but I had changed context. I had drummed up ways to move from my App context to my Form context while keeping my customer object intact, but I couldn’t seem to switch it to App again. No joke, I probably would have lost even more time on this bug without being able to 1) identify my lost context and 2) realize that you need to put your functions where your context is, not just what they interact with. So while the Form class might have been initialized at this point in the code, there’s no reason to pack up my active objects and move over there.

I could continue on this digression and I will. What I’m hoping I showed here is that I was able to move on from “Nothing’s happening!” to “The wrong thing is happening!” simply because I was able to generate some feedback on my own, which is an important step forward from moving on from just “getting the tests to pass”.

The follow-up posts to this are a few things I learned when it comes to getting a stuck project moving from its early phases.

Thanks for coming to my CRAIG talk.