Actions As Objects
Published 2/21/2018
Take a minute to think about the last big bug you worked on and how you felt....today we're talking about a way to track down bugs and solving long, drawn out debugging sessions.
Today's episode is sponsored by Linode.
In 2018, Linode is joining forces with Developer Tea listeners by offering you $20 of credit - that's 4 months of FREE service on the 1GB tier - for free! Head over to https://spec.fm/linode and use the code DEVELOPERTEA2018 at checkout.
Transcript (Generated by OpenAI Whisper)
I want you to take a minute and think to the last bug, really the last big bug, the one that took a long time to fix, I want you to think back to how you felt in that moment. Really connect to the frustration and maybe the seemingly wasted hours that you spent just to figure out that it felt like a relatively obvious thing that you could have avoided and you just didn't. It wasn't a hard thing, it wasn't an algorithmic problem, it was something else, something seemingly simple. We're going to talk about a way, a practice that you can employ in today's episode that can help you track down these things a little bit faster, a little bit easier. There's so many ways of dealing with code and we're going to talk about one specific practice today that I believe is one of the most effective ways of dealing and ultimately kind of avoiding these long, drawn out bug tracing sessions. My name is Jonathan Cutrell, you're listening to Developer Tea. My goal in the show is to help driven developers connect to their career purpose and ultimately do better work to have a positive influence on the people around them. We talk about multiple different kind of classifications of information on this show. Specifically, we mentioned at the beginning of this year that we want to focus on practices, principles and purpose. This is the pillars of Developer Tea, sorry for the overuse of alliteration, but this is true, ultimately your practices and your principles will follow from your purpose. We need to talk about what those practices look like, what is the practice of a well-intentioned developer look like, and how can we do better things by changing our practices? We don't just change at the top, we don't just change the purpose and hope that everything else falls in place. We can identify spots all the way down that chain and improve in each of those areas. We talk about principles probably most of the time on the show because principles really drive everything else. There's an endless amount of conversations that we can have on principles. When it comes to practices, it's a little bit more limited in terms of how evergreen that content is going to be for people who find the show in one or two or three years. We don't really like to hyper focus on one specific practice in one specific language because really the insights that you can gain from the show, I think the highest leverage is when we can generalize this information to any language. When we can generalize these practices to any language or any paradigm, any environment that you're operating in. An interesting side effect of this focus that we have on practices and principles that scale to multiple environments, multiple languages, whatever your job title is. The interesting side effect is that a lot of the time these practices and principles can be taken out of the coding world, out of the software development software engineering DevOps, out of that world, and it can be applied in almost every other area of your life. It's not just about code, it's not just about engineering, it's also about patterns and ways of thinking, and models of thinking that can change the way you do everything in your life. That's why we believe the show really could be for anyone. You can gain a lot from the show, not only if you're a developer, and not only if you're a designer, and today's episode is no exception. Really excited to talk about this idea because I think it really can change the way you see the way you write code, but it can also change the way that you see performing your everyday activities. So I want to revisit this idea of encountering a bug that takes you a long time to trace down. Most of the time, when we encounter these bugs, it's because when we look at the code, there's either something that we aren't seeing at all, it's absent, or we're seeing something differently than it is in reality. Let me say that again. Either there's something missing and we don't realize it, or the code we're looking at doesn't do what we think it's doing. And these two frustrating positions to be in, they really leave you kind of scratching your head in either scenario. Because in both scenarios, you believe, by looking at the code, you believe that it should do what you're trying to do. Recently, I've been practicing kind of brushing up on my computer science skills. I never had a formal training in computer science. I had training and things related to it, but I never had formal algorithms class, for example. I've been brushing up on some of those things myself, just for my own interest. And so many times I've written an algorithm, maybe a sorting algorithm, for example. And I'm staring at the code and I don't understand why these test cases are not passing. It's a very frustrating position to be in. And there's always that moment. There's always a light bulb moment after I experiment a little bit further in the previous episode, recent, I guess, last week, we talked about how experimentation is so important and prototyping is so important for progress. But there's always this moment, this light bulb moment where either I realize, oh, that's not doing what I thought it was doing, or I realize, oh, I have to accommodate for this other thing, this other case that I wasn't thinking about this weird, you know, fringe example. It's a weird fringe case. But I want to talk about a way of potentially avoiding some of these positions of not really knowing what's going on. And we're going to talk about that right after we talk about today's sponsor, Linode. If you've been listening to Developer Teapretty much at all, you've probably heard us talk about Linode many times. And that's because Linode has invested in this community. They've been our longest running sponsor on this show. And they really invest in the development community, not just by buying sponsorships on Developer Tea, but also by creating services and documentation of those services that really make your jobs easier as developers. With Linode, you can deploy your own node, right, your own Linode node for $5 a month. This is their entry level plan. And pretty much everybody has $5 a month. So if you're serious about development and you want to launch a web service, for example, you can do that for $5 a month. And it's not a crippled server either. It's a gigabyte of RAM, which is more than enough for almost every experiment project that you have. So $5 a month is their first plan. And they go all the way up to astronomical high memory plans that you can find out more about these at Linode.com, by the way. So if you're interested in switching to Linode and you're kind of reticent, you don't really want to go through that work. Well, luckily, Linode has a migration guide. It's available right on their website. You can find it in their primary navigation. They know that a pain point for you, if you're going to come to Linode, is for you to migrate from your old place to your new place, right? This is kind of making things easier for you as a developer. But it doesn't stop there. They have tons of other services, tons of features on their servers that make your life easier. If you block yourself out of a system, for example, well, they have a way of getting out of that conundrum. So Linode really does go the extra mile. And on top of that, you're going to get $20 worth of credit just for being a Developer Tealistener. Go and check it out. Spec.fm, slash Linode, spec.fm slash Linode. Use the code Developer Tea2018 at checkout. You'll get $20 worth of credit. And you can use that on any of their services. Go and check it out. Spec.fm slash Linode. Thank you again to Linode for sponsoring today's episode of Developer Tea. So we're talking about ways of avoiding this weird scenario, this situation where you end up either not seeing something in your code or thinking that your code is doing something that it's not. And there's no silver bullet for this problem. There's no silver bullet for debugging, right? There are hard bugs that will ultimately take a lot of your time and energy to trace down. But there is a practice that I have found that really helps, especially when I'm dealing with object oriented code. Again, we'll try not to focus on one paradigm. But with object oriented code, this particular practice has been extremely effective for me. And that is to view everything that I do as an object. Let me explain that a little bit more thoroughly. Every action that occurs in your application, whether that's some kind of transaction of data, a change that a user makes, any kind of procedure at all. If we create some kind of record of this, it's not just saving it to the database, but creating some kind of object that explains what this action is. Don't just create the action itself, but create an object that represents that action. So if you're sending an email, for example, create an object that represents the sending action itself, not just the email, not just email.send, not just creating the send action, but instead creating an object that represents that action. What is the nuance difference here? Well, ultimately, what this allows you to do, and this is kind of the magic aha moment for this thinking of actions as objects or thinking of them in terms of transactions. If you start thinking this way and you start building your code this way, especially if you go kind of all the way with this. If you take every action into consideration and you record every single action, even if you're recording it in memory, you have the opportunity now to go back in history. If you're a react and redux developer, then you probably have already seen this, maybe in a demo, every single change is created and kind of stored in the redux store. What this means is you have every single change to the data, which ultimately results in a re-rendering if you're using React. In this particular example, it results in a re-rendering. Every single render that you have seen, you can go back and rewind and see what the render would have looked like at any previous state. This wouldn't be possible if you weren't recording the changes themselves. It's not just simply changing the data. It's recording what the change was. This allows you to replay all of those changes. It also allows you to debug in a much more effective way because you can kind of insert your debugger at any point in that line of changes. You can inspect the information that's happening at any given point as well. This allows you to have a lot more insight than simple procedural code would allow. The first response that I usually get in this kind of conversation is that this is going to be a lot of work. This is going to take a lot of time to abstract these things and put them in their own classes or create these kind of models for managing this stuff. The reality is this isn't a new idea. A lot of the time you're going to find, for example, a Ruby gym, you're going to find some kind of software package that will help you do this in a more robust and automatic kind of plug-and-play way. I also want you to recognize that you don't actually have to, as we said already, you don't actually have to save this stuff to the database for this to be an effective concept. If you create highly detailed log messages, for example, give yourself a lot of information in the log and trace every action that you're taking, trace every change to the data that you're making. Log more often throughout those processes, what you'll find is a lot of the time we don't actually take advantage of those logging features. We don't know what the state is at a given point in time. We don't actually watch the changes as they occur. We can't really look back at that history, at that trail that we leave behind, and we're making guesses. There's really so much that we can do to stop guessing. There's so much that we can do to avoid being in that situation where you think your code should be doing one thing, but it's actually doing another. Thank you so much for listening to today's episode of Developer Tea. Of course, this is not, once again, it's not a silver bullet solution. It is one way that you can start to get more control over your code. There's a lot of ways of implementing this. Again, this is not a novel concept. This is not something I made up. This is essentially the same thing as having versions or having a kind of log of changes, a history. There are a lot of different paradigms that will accomplish the same goal. Again, start thinking of your actions in terms of objects. There's a lot of other implications to this. If you go really far down this road, then you can connect every action. For example, if you're building a web application, you can connect every version and every change that you've made to a URL. You can make each of those versions available if you wanted to. That's one example of a benefit, even an extra benefit on top of the debugging benefits that you'll get. You also have more flexibility of what you can do now with that information if you gather it. Thank you so much for listening and thank you again to Linode for sponsoring today's episode of Developer Tea. Head over to spec.fm slash Linode, user code Developer Tea2018, and checkout. You'll get $20 worth of credit. Thank you again to Linode. Thanks so much for listening. Go to whatever podcasting app this is playing in right now before you forget. Go ahead and subscribe. This is going to allow you to be notified whenever a new episode comes out. We have three of them a week. So it's very important that if you want to stay up to date, then you subscribe. Thanks so much for listening and until next time, enjoy your tea.