00:00:21.109
Thank you for coming to my first-ever conference talk. Before we begin, I just want to point out that I have links to my slides in the top left corner if you want to follow along, and my Twitter handle is in the upper right corner if that's something you're interested in.
00:00:31.590
The title of my talk in the program is 'Filling the Knowledge Gap: Debugging Edition.' This is really just a fancy way to say that this talk is about what I wish my boot camp had taught me about debugging.
00:00:53.930
So first off, let me introduce myself. My name is Mina Slater, and my pronouns are she/her. I graduated from a coding boot camp in April of 2018, so about a year ago. I am currently a developer at a consulting agency in Chicago called Tandem, and this is my first time attending RailsConf.
00:01:04.080
A fun fact about me: I’m terrified! If you’ve been in a career for a long time like I was, starting a new job in a new field can be quite daunting. I was transitioning from a 10-year career in theater, where I was the expert at my job, to a new industry and a team where everyone knew more than I did.
00:01:28.470
Sure, I knew I was going to be the most inexperienced developer in my company, but I was ready to face the challenge of this new career head-on. I was prepared to put in a lot of time and energy into learning, improving, and becoming the best developer I could be, but I wasn't prepared to discover just how much I didn't know.
00:01:43.800
I quickly found out where my skills were lacking. I was inefficient and at a loss when it came to testing and debugging. Unfortunately, I don't think my experience was unique. A majority of coding boot camps leave graduates with significant knowledge gaps in essential skills like debugging, and many of us struggle at our first jobs because of it.
00:02:09.300
When I first started learning to code, seeing an error message was genuinely scary. It was my code telling me that I did something wrong or that I had made a mistake. Since we've all been conditioned to avoid mistakes, it felt like a failure on my part.
00:02:35.099
The big red error messages reminded me of the big red X's that my teachers used to put on my tests in school. They were intimidating, causing me to shy away from running my code often because I figured I couldn't get error messages if I didn't run the program, right?
00:02:59.790
So, I would write my code in the bubble of my text editor, staring at it and wondering if it looked right. The only indication I had of whether I was correct was the very limited knowledge I had about the programming language I was using.
00:03:14.110
As you can imagine, I wasted hours upon hours trying to make things right before running any event. When I eventually let the program run, it, of course, didn’t work, and without having been taught to debug or seeing anyone demonstrate, I didn't have any idea how to approach it.
00:03:49.719
I didn't know how to read the error messages or that I should even read them at all. My only approach was to stare at the code, combing through it line by line, and hoping to find any typos or obvious mistakes. No one told me that there were better ways, and I practiced myself into bad debugging habits without knowing it.
00:04:08.900
Now, don’t get me wrong: I’m not saying that boot camps don’t produce quality developers. In fact, more companies showcase career changers and boot camp graduates because we bring past experiences and soft skills that are harder to teach. However, that’s a 40-minute talk for another day.
00:04:39.740
Now, there’s only so much you can cram into someone's brain over the course of three months, so I understand that boot camps have to make compromises. They usually focus on things like syntax and very basic practices, such as assigning variables and making loops.
00:04:54.430
Testing and debugging often get pushed to the side. After I finished boot camp and started working, it quickly became apparent that there were better ways to fix bugs. I had to stop just staring and hoping, but I didn’t know what to replace it with.
00:05:23.940
Thus, the part of my brain that should have contained debugging knowledge was a big empty gap that I needed to fill with proper tools and strategies. At Tandem, we pair program all the time, which gives me an opportunity to observe more experienced developers at work.
00:05:46.930
I have a really supportive team that lets me openly confront what I don’t know and encourages me to ask questions. We break things together and fix them as a pair, which also gives me exposure to how different people like to approach bugs and errors.
00:06:09.080
For instance, Shamil is excellent at using the network tab in the developer tools, and Sasha is a wizard in the Rails console. A senior developer once told me that in software, you have to break everything before you can piece it back together and make it work.
00:06:30.780
I think that applies to learning as well because if we can’t admit what we don’t know, we won’t learn it. Having a supportive workplace allows me to confront my knowledge gaps so that I will know when I see something that I want to store away in those spaces.
00:06:51.130
That can include a new approach to a problem or a new tool. Over the next 30 minutes, I want to share with you the most important lessons I learned about debugging over the course of my first year working in software.
00:07:14.660
I’m not trying to turn you all into master debuggers; honestly, 30 minutes won’t be enough for that. I also want to give you a better starting point than where I was a year ago, so you can go further.
00:07:48.090
Throughout that year, I organized the things I learned about debugging into three main categories or lessons: 1) Look under the hood, 2) Tap the phone lines, and 3) Find a bug, write a test. These are not meant to be strict roadmaps, but rather starting points where debugging can begin. Based on the issue at hand, we can use one of these starting points, mix and match them, or take an entirely different route.
00:08:41.330
So, let's jump into lesson number one: look under the hood. To be honest, I wasn't exaggerating when I said that I wasn't taught any debugging strategies at all. We were told to console.log everything, which means I knew I could make the program print out certain things.
00:09:02.260
We mainly use this to obtain the values of variables at runtime, which we then compare to our expectations to pinpoint where our code needs to change. I learned about print debugging in Ruby; we use print, puts, or P instead of console.log like in JavaScript.
00:09:24.790
All three methods serve a similar purpose: they output information from our program into the console. However, using P gives more useful information about our objects than just printing their values.
00:09:49.960
For example, if you take an Active Record object, an instance of a puppy named Dotty, we can see how P behaves differently than puts when we output the object in the Rails console.
00:10:06.960
Print debugging lets us leave breadcrumbs around our code in the form of these print statements, allowing us to visually track the path of our program and identify whether the actual pieces of data are what we expect.
00:10:42.960
If an output we expected to see is missing, it’s safe to say that our program never hit that section of the code. Aaron Patterson is a famously self-proclaimed puts debugger, and a link to his blog post on that topic will be included at the end of my slides.
00:11:02.880
Most of the concepts he covers in that post feel very much over my head; honestly, I'm not a print debugger like him. Now, my go-to tool for exploring the internal workings of my Rails application is Pry, a gem that allows us to open a console session at any point in our code.
00:11:41.890
By dropping 'binding.pry' into the code, when we run the program, it will pause and give us an interactive console in the terminal. That’s why this approach is called interactive debugging—it serves the same purpose as using puts, but gives us more freedom in our explorations.
00:12:05.649
I built a simple app called Puppy Gachi about a year and a half ago when I was trying to teach myself Rails. In this app, users can log in to check on their puppies, which get hungry and bored over time, allowing users to feed or play with them.
00:12:58.520
I have put a couple of breakpoints into the service object that ages the puppies and resets their hunger and boredom levels. So if we reload the page in the browser, we can see that the page appears to be unresponsive. If we check the server logs, we can see the request made to the server and where it hits our first 'binding.pry.'
00:13:37.090
Most things we can do in the Rails console are accessible to us in the Pry session, but the gem also provides additional commands for detailed information about our program. One such basic command is LS, which allows us to get an overview of everything available in the current context.
00:14:21.780
We can see the public instance method 'process' among other things, but it won't show private methods since we don't have access to them from within Pry. Another gem that I often use alongside Pry is 'pry-byebug,' which provides us commands to navigate through the codebase.
00:14:47.040
In the next step, we can tell Pry to continue running the program until it hits the next breakpoint. After finishing our session, we can then exit to step out of Pry and return to our normal program execution.
00:15:18.080
Being able to peek under the hood of my program has been a game changer for me. The hardest part of learning to code was overcoming the disconnect between the text in the editor and what shows up in the browser.
00:15:54.480
It's especially challenging when working with dynamically typed languages like Ruby where we can assign data types to the same variables without warnings about potential issues. Has anyone run into this error message before? The actual method name in this error message may change, but it essentially indicates that the program is attempting to invoke a method on something that doesn’t have the right data type.
00:16:28.710
The message tells us that the select method is built-in for arrays and enumerable types, so if the object isn’t an instance of either class, we receive this error. Since there are many answers to where and why the data is unexpectedly of the wrong type, opening the program using puts or Pry can provide valuable insights during debugging.
00:17:09.060
By using these tools, we can identify the problem areas and follow clues to find solutions. Now, let's move on to lesson number two: tap the phone lines.
00:17:24.450
I worked at a consulting agency where everyone on our team is a polyglot. Currently, the project I’m working on consists of a Rails API with a React front-end. Testing features in the browser as we write code is standard practice in our typical development flow.
00:17:56.250
Usually, when things aren't functioning correctly, the best-case scenario is that we’ll see some sort of error in the JavaScript console. However, many times we only face an unresponsive UI or a blank screen.
00:18:37.560
Something that has been tremendously helpful in these cases is the built-in dev tools in the browser. When we open the dev tools, we can access all of the tabs, including elements for HTML and styling, the JavaScript console, and the Network tab where we can view our network activities.
00:19:12.440
In the Network tab, we can make sure that resources are being downloaded or uploaded correctly, and we can check the status of the application’s requests to and from the server. When we first open the dev tools, we won’t see any network activities logged, but we can reload the page to see the logs populate with network activity.
00:19:42.480
Every row in the table represents an HTTP request, with columns providing additional information about those requests. I often check the names of the resources, their status codes, and the resource types.
00:20:00.570
If a row appears in red, it may indicate a bad request, such as a 500 internal server error or a 403 forbidden message. Clicking on one of these lines allows us to see further details, including request and response headers as well as the response body.
00:20:41.510
This information helps us ascertain whether the requests sent to the server include all necessary information that the back-end needs to process them correctly. This is crucial because even though a bug shows on the front-end, it doesn’t always mean that the issue lies within the front-end code.
00:21:03.180
I've made the mistake of investigating the React code only to realize later that the backend was where the issue originated. We can also look for similar information from the server-side logs. The server logs will tell us about each incoming request, how the server processed it, and what the result was.
00:21:39.080
This is also where we check for exceptions, error warnings, and where the Pry session will open if our program hits a breakpoint. Just like with the browser's network tab, we can see the HTTP request, the route it hit, the response status code, and any exceptions raised.
00:21:59.520
Understanding how our program behaves when it runs correctly helps us recognize when something goes wrong. Now, let’s move on to lesson number three: find a bug, write a test.
00:22:19.320
Bugs and errors are a normal part of software development because developers are only human. However, we want to ensure that any changes made to the code don’t create regressions and lead to the same bugs cropping up again.
00:22:39.600
Often, bugs arise because we fail to account for and write code to cover certain edge cases. Most times, the program operates smoothly, but our goal is to ensure it works seamlessly for as many end-users as possible.
00:22:57.200
Writing tests that cover the conditions under which our bugs appear will help to prevent regressions and inform us when a bug has been fixed. By running the tests, we can also gather clues about how to proceed with troubleshooting.
00:23:28.080
For example, recently my co-workers Shamaia and I were tasked with writing a method to sort some Active Record objects into a list for the front end. We had one query that returned an array of evaluations and another that fetched a single evaluation.
00:24:17.590
The goal was to combine these results into one list, sorted based on specific attributes, to display them correctly. In our implementation, we wrote tests to cover all potential cases we could envision.
00:24:47.480
With all the tests passing and our user interface behaving as expected, we created a pull request. After the team reviewed it, we merged it into the codebase. A few hours later, while my colleague Sasha was performing QA, she discovered the page we had worked on was broken.
00:25:15.250
Upon investigation, she found that the issue stemmed from one of the queries returning nothing. Our method had inadvertently included a nil value in the objects list we passed to React, leading to rendering issues due to attempting to display undefined items.
00:25:48.940
After discussing the bug with her, the first thing she suggested was to write tests to account for this specific state within the program. Our tests essentially stated that if one of the queries brought back no results, it should be excluded from the list passed to React.
00:26:07.600
Although we initially weren't sure which lines of code to change or what the alteration would require, backed by the tests, we could immediately tell when the bug was resolved.
00:26:40.300
Also, each time we attempted a solution, running the tests allowed us to see if they failed in new and insightful ways. Sometimes, as developers, it feels like we are continuously battling bugs, fixing them as often as we write new lines of code.
00:27:01.800
Good debugging habits are almost as important as writing clean code. Now, for the developer I was a year ago, this idea was quite anxiety-inducing—I could write method after method but struggled to identify that one variable causing issues.
00:27:33.020
Fortunately, I work with knowledgeable developers who have a wealth of experience. Through pair programming, I've gathered a little of each of their strategies into my own debugging toolkit as I've filled in my knowledge gaps.
00:27:54.720
In a perfect world, boot camps would focus more on teaching debugging techniques and practices. This would prevent graduates from developing bad habits and prepare us better for our first jobs.
00:28:15.580
As things stand, we can help each other by sharing valuable knowledge and being open about what we don’t know.
00:28:34.560
I recognized early on that I had no idea how to handle errors when they occurred, which allowed me to focus on those challenges and learn the lessons I shared with you today.
00:29:02.580
Now, I’d like to return to a thought by Aaron to close this talk. I read something he tweeted back in January: 'It’s not a bug; it’s just taking the code path less traveled.'
00:29:19.640
He was likely making a joke, but framing it this way made me feel more comfortable with debugging. Errors and bugs are merely edge cases we haven’t accounted for yet.
00:29:34.320
We shouldn’t be intimidated by them, and I hope, after our time together, that you feel more equipped to tackle your next bug or error.
00:29:41.590
So now, please go ahead and break your code! Thank you!
00:29:51.529
If I could have another minute of your time, I want to share a bit about the company I work for. Last time we were at RailsConf, we were known as Deaf Mind, but we've since changed our name to Tandem.
00:30:39.590
Tandem is a design and technology consulting agency located in Chicago. Our mission is to create products and services that positively impact our community. Having recently completed our apprenticeship program, I personally benefited from Tandem's commitment to hiring and developing talent.
00:31:27.130
We utilize pair programming to help each other grow and maintain the quality of our work. If any of you are looking for work, we are hiring, so please come talk to me if you’re interested in learning about available positions.
00:31:55.860
Thank you again!