What is your most memorable de-bugging session? Today, we're talking about fixing our losses by reframing the situation.
If you're looking for an automatic platform and configuration detection, to build, test & deploy in minutes check out Bitrise. They've got an open source library of 170+ integrations, and the best part there's no scripting needed! Run the same config locally with the open source CLI by downloading the bitrise.yml
If you're looking for a job, they're hiring tooling & dev-Ops engineers at their Budapest office
If you have questions about today's episode, want to start a conversation about today's topic or just want to let us know if you found this episode valuable I encourage you to join the conversation or start your own on our community platform Spectrum.chat/specfm/developer-tea
Transcript (Generated by OpenAI Whisper)
What is your most memorable debugging session? We talk about debugging on the show a lot because a lot of our job as developers is to debug our code. Most of the time when we write code, we write it wrong to begin with. The rare circumstance where we write code that isn't wrong to begin with, usually that code is doing something particularly straightforward like some kind of hello world. I imagine that some of you have actually written a broken hello world. From time to time this happens to every developer. In fact, most of our jobs is about figuring out what we did wrong. We talked about this on the show before. It's part of the reason why developers need to focus on their wins a little bit more than the average person because most of our jobs are focused on fixing our losses, fixing our mistakes. But we're not talking about imposter syndrome or anything like that today. Instead, we're talking about problems. This is the second episode on the discussion about problems. It's a series that we're doing here on Developer Tea. Problem solving is in and of itself a skill. In fact, it's a conglomeration of a lot of different skills. And that's why we are focusing on it for a couple of episodes on the show. My name is Jonathan Cutrell and you're listening to Developer Tea. My goal on the show is to help driven developers connect to their career purpose and do better work so they can have a positive influence on the people around them. And what better way to have a positive influence as quickly as possible than solving a problem? Now, the problems that we're talking about solving in today's episode, we're talking mostly about solving a problem in code. That's kind of the lens that we use. But really, these techniques they go well beyond problems just in code. They apply to interpersonal problems. They apply to systematic problems outside of the realm of software development. So I encourage you to carry this information forward outside of your daily practice as a software developer and into your life as just a human being, but also your professional life beyond the code. Now, I asked you about your most memorable debugging session because for most people, the story sounds a little bit like this. While I was asleep and somebody called me at 2 a.m. and the server had gone down. We're trying to figure out why the server had gone down. So I wake up and I run to my computer and it takes five hours of me debugging and trying to figure out, digging through these logs or looking through our last couple of commits. Nothing seems to be standing out to me. And then suddenly I notice a missing semicolon. And of course, my brain wasn't on the semicolon the whole time, but I was looking for the more technical problem, the memory overflow errors or some major DDoS attack. I was looking at the big picture when really all that was happening was a simple syntax error. This happens all the time, doesn't it? These are the most memorable stories because perhaps the most unexpected thing occurs and has these major consequences. Now while you're not going to be able to avoid every time that you have ever written a missing semicolon, you're not going to be able to avoid every single scenario like that. What you can do is structure your debugging sessions a little bit differently. In today's episode, we're going to be talking about two different framing techniques for you to debug better. We're going to do that right after we talk about today's sponsor, BitRise. If you want mobile continuous integration and delivery for your team, go and check out BitRise. BitRise allows you to take all of the services that you already use and that you're probably using one at a time, manually triggering a build in one place and then sending a post request to a server somewhere else and then uploading all of this code to the Google App Store and writing all of your release notes, doing all of that manually. BitRise allows you to create a single, simple automated solution for all of those things to happen together. It's kind of like if this than that, but much more powerful and specifically made for mobile app development. There's over 170 integrations that you can use. And we're not just talking about the big app integrations that most things have, like for example, sending a Slack message, of course, that's available in BitRise, but you can also do much lower level things, like for example, running a shell script. So the power of the platform can't be overstated because it's so flexible and beyond being flexible, it's also easy to share your integration setup. You can share your configuration because all of these services, once you kind of strap them together, you can download that integration configuration as a bitrise.yaml file. So this is easily ported to everybody's local environment. Go and check out what BitRise has to offer. Head of respect.fm slash bitrise. Thank you again to BitRise for sponsoring today's episode of Developer Tea. So we're talking about different ways of framing your debugging sessions and more broadly different ways to frame problems and trying to understand the problem really is what we're talking about. There's a lot of ways to understand problems. It's not easily stated and there's a lot of kind of famous quotes about this that a well-described problem is halfway solved. That's been attributed to pretty much everybody under the sun. So what are some ways that we can debug better? How can we bring in some new perspective on how to frame a problem? I'm going to share two framing techniques that I have used successfully in the past and that other developers have certainly used as well. And again, these are framing techniques that will work outside of the realm of software development as well. So the first one is to rebuild your problem. Rebuild your problem. This sounds like it's going to take a lot of time, but I want to focus on a specific aspect of this that I think is really often missed. And that is to take the things that you think are contributing to your problem and rebuild them in a very straightforward way. I'll give you an example of this. Whenever I am facing a strange browser rendering bug, right, in the browser I have something that I've created, I have some kind of HTML and some CSS. And for whatever reason, it's not showing up how I expect it to be showing up. Something is not working like I expected to work. I take out the relevant kind of mini pieces, right? So I take out the relevant HTML and I copy the relevant CSS and I bring it over into a different platform, something like code pin, for example, right? And I drop that HTML in and I drop that CSS in and I try to identify and eliminate as many variables as I can to see if the things that I think are contributing to the problem are actually contributing to the problem. And this process of elimination is kind of a theme of problem solving. You're eliminating variables as you go along. One of the ways that you're going to eliminate variables is through this recreation process. As you recreate each of the pieces of the puzzle, what you'll find is that you're more able to identify when that problem showed up, right? So you're adding things in our browser rendering bug, for example, you're starting to add the HTML and you add the CSS, maybe you add it one rule at a time or, you know, one declaration at a time and as you're adding it, everything looks right until this particular line. This is a really effective problem solving strategy, especially when you're doing something that is easily rendered. In other words, you're going to get some quick feedback, right? So you can easily see which particular thing that you did led you astray, rebuild your problem. Now, the way that you keep this from being really expensive and time consuming is by eliminating things that are irrelevant. So for example, let's say you are getting some information from a database and you know that that information is being pulled in reliably. You've identified that that information that that's not where your problem is actually coming from and you've verified that. Well, now you don't necessarily need to rewrite a connection to a database. You can just take the data itself, the static data and plug it in statically. So now you kind of cut down the complexity of your kind of rebuilt problem space. It's also important to remember that this is going to work particularly well for narrow scope problems, much smaller problems, things that you would probably consider bugs rather than an entire design decision or design domain. That's not really what we're talking about. We're talking about figuring out some kind of confounding bug. So that's the first reframing technique. Rebuild your problem. Now I want to add on to this because I still feel like this concept is a little bit difficult to grasp. Really what you're doing is you want to create kind of a miniature model of your problem. You're not recreating all of the details. You're creating something that tests a very narrow portion of what you had created originally. It's almost like creating a prototype that highlights a specific set of functionality. Okay, let's move on to reframing technique number two. Use a real example, use a real example. This is something that developers very often forget or ignore because it can be a little bit difficult. Using a real example often means taking real data, for example, user input, right, or even user behavior, taking that real information and identifying how your program, how your software interacts with that information. And here's why this is so important, especially when we're talking about software that deals with some kind of input, some kind of interaction. Until you actually use real information, real input, you're not actually seeing, you're not testing the software thoroughly. I'll give you a very simple example. Let's say you're a friend and developer and you've created an interface and the interface kind of gives some transitions between form elements. As you fill out one form element, it kind of fades out and a new form element comes in. And you're receiving bug reports that are saying, yeah, this form is very slow. And you know from your performance data, you can look at the performance data and everything is optimized and you can't quite connect the dots between what these people are saying. The form is very slow and actually the data says it's not very slow. In this case, what these reports are likely referring to is how long these animations are taking. In other words, it's taking such a long time between filling out one field and the next field that by the time I get to field number 10, I spent so much longer on this form than I really wanted to spend. Now taking in a single snapshot view, one of those form inputs might have felt quite nice. It might have felt like it was designed well. But when you take a real example, when you take a real person who is spending the time to fill out this form, well now, regardless of how nice that one interaction was, these reports of the form being slow, they suddenly make sense. So the underlying principle or system at play here is that everything in practice requires more than theory. Everything that we build as software developers, even though it is informed by some kind of theoretical model, we must apply real examples to know how thoroughly those theoretical models are covering us. There's a famous quote that is attributed to statistician George Box. The quote goes something like this. All models are wrong, but some are useful anyway. In some ways, this can be applied to theory, especially as it relates to software development in particular software development for human interaction. We have theories of how humans should interact with our software. And yet, so often, real examples challenge those theories, or they take them to their very limit. So we must be willing to accept that as we practice with real examples, our theories may only provide some support rather than imperative direction. Thank you so much for listening to today's episode of Developer Tea. I hope that I can help you solve problems better through things like reframing techniques. If you want to learn more about problem solving and a thousand other topics that are relevant to not only software developers, but anyone really who wants to become better at what they do, and is willing to challenge the status quo. I'm willing to admit that their minds are biased in that their approaches are not necessarily always going to be good just because they want them to be. That's the kind of things we talk about on this show. Please subscribe and whatever podcasting app you're using, and while you're at it, go and check out BitRise. Head over to Spectatofim slash BitRise. BitRise is a continuous mobile integration and delivery for your team. Thanks again, Spectatofim slash BitRise. Thank you so much for listening to today's episode of Developer Tea. Until next time, enjoy your tea.