 about Webster's Dictionary defines empathy as the action of understanding, being aware of, being sensitive to, and vicariously expi- you know what, I don't know what this means. I'm not actually going to read you the definition of empathy from Webster's Dictionary. Instead, I'm going to tell you my definition of empathy. And to be honest, it's actually not my definition, I took it from someone else. I actually took it from one of the kids in this picture. So in a previous life, before I had ever written a single line of code, I used to be a sixth grade teacher. And I had 34 10-year-olds in my classroom every day. Yeah, I'm just, let it sink in, it's a lot of middle school hormones. And I remember one day, in the middle of a lesson, a fight broke out in class. I was still pretty new, I didn't really know what I was doing, but it was really violent and the kids were being super aggressive and I just had to stop everything I had planned for that day. So instead, I threw out the agenda and I kind of decided to wing it. And instead of talking about whatever we were going to talk about that day, we all sat in a circle and we talked about the fight that broke out in class. What we ended up doing was trying to reconcile our differences and understand and talk through what had happened. And we ended up talking about empathy. And I didn't really plan on bringing it up and I had a hard time describing to the kids what it was. But then one of the kids in this picture just kind of looked at me a matter of fact and he was like, oh, teacher, that makes so much sense. Empathy is just understanding how someone else feels. And that definition, I mean if I could trademark it I would, I think is the best definition for something, for a concept that is just really hard to wrap your head around even as grown adults. And it's even more difficult to try to identify and practice. But after I left the classroom I kind of forgot about that definition. I forgot about it until I started working with, so I think one of the pillars of programming and this extends beyond Ember and JavaScript or anything really is that inevitably at some point or another, no matter how good of a developer you are, you are going to get stuck, right? Please tell me it's not just me because I would feel really bad and the next 22 minutes are going to be pretty boring. You're going to get stuck. And sometimes, hopefully, the more you practice, you can get unstuck on your own. Sometimes you need a little bit of help from someone else. As developers, the term that we like to use for this is, of course, debugging. For some of us, for those of us who have been doing it long enough and we are able to get unstuck on our own, debugging is super fun. And like exciting and like solving a puzzle. Here's where it gets tricky. When you're trying to learn something new and you get stuck. So when I was learning Ember, the very first Ember application that I was a part of, debugging for me kind of felt a little bit like this, for him, he's trying so hard, oh, God. It's great because it's awesome when it works and you're building things and things come out of the box and you're creating things out of nothing. And you feel like a wizard and then you fall on your face because you don't understand what's going on. And you don't know enough about the framework or sometimes even the language to know where to start getting unstuck. As cute and as adorable as this taco is and as much as I empathize with him. I think it's actually something really significant to hit upon because when you're learning something new and you get stuck, things start to feel impossibly hard. And then that leads you to feel unbelievably frustrated. And it's at that point that you start to find yourself thinking, and this is where it gets really dangerous, maybe I should give up. Maybe I'm just not cut out to do this. Maybe I can't do this. Maybe this is not the right framework or language or career for me. And it's really important to acknowledge this because most of us in this room, all of us in fact, have gotten unstuck. We wouldn't be here if we hadn't, right? How do you get unstuck at that moment? I'm sure there's a lot of good techniques that all of you in this room have. And they're all significant and valid. But I found one technique while working with Ember that really surprised me. I've actually extended it to whenever I'm building an application that's not Ember or not even in JavaScript. And that is empathizing with my code. I know it might sound a little bit strange, but stick with me. When I got stuck with my first Ember application, I did exactly what I told my sixth grade students to do. When they got overwhelmed and frustrated with their code, I told them to empathize, sorry, they wouldn't get frustrated with their code, they would get frustrated with each other. When they got frustrated with each other, I would tell them to empathize with each other and try to understand where the other person's coming from. So when I got frustrated with my code and overwhelmed with it, I tried doing the exact same thing. Especially because I was at a loss of what to do. So how did I do that? I put myself in my code shoes. I tried to understand what does it have access to? Where is it getting its information from? Am I being really hard on it unnecessarily because I wrote really bad code? Probably most of the time, yeah. I think if we think like our code, instead of getting frustrated, we can have a little bit of fun. So hopefully in a few quick examples, I'll show you how you can do that. So for our first Ember application, we run into a bug pretty early. We're building a recipe tracker app. And it's not anything really fancy. It's just simple crud functionality. You can keep track of your recipes. You can update them and delete them. It's great. We built it really fast. But we hit a bug. And the bug is kind of odd. It's this. I have enlisted recipes. And I just want to click on one so I can change the ingredients in it. Or maybe tweak it a little bit. So when I click on a recipe, cool. Everything looks fine. Those are all the stuff that I would expect. All the values of the recipe. But here's something really weird. When I refresh the page, it's really broken. And that's not expected behavior. So how do we start debugging this? Where do we start? Who do we empathize with? Well, OK. Let's just start with where our code is being rendered. The view. We just have a bunch of sorted recipes that we're iterating through. And we have this link to helper. And when we click on something, we click on a recipe name, we should be able to see our recipe. But sometimes it works, and sometimes it doesn't. So let's think about where this view, if we were that view, would get our information from. It'd have to be coming from somewhere. Maybe the route. We have a recipe route that's using a dynamic segment. Nothing looks really complicated about this. It looks the way it should. But what does our route have access to? Well, it looks like it doesn't have access to very much. Pretty empty. But our router would tell us, would lead us to believe that we should have an object there. Why does that object not seem to render? Well, it's like half the time it works, and half the time it doesn't. So half the time the view has the object, and half the time it doesn't. So maybe we're making some assumptions about what our poor route actually is doing. So if we were a route, where would we get our model from? It doesn't just magically appear, right? It has to come from somewhere. We have to pass it that object somehow. Well, luckily, there's a great lifecycle hook called a model hook. And we can write it pretty easily in just three lines. We can use the ID of the object. We can use the ID coming from the URL and find the object that way. But I don't actually know if this is going to fix it. So let's just put a debugger in there and see what's going on. Because this is just kind of like me guessing if this is going to work. Okay, let's try it again. Will this fix our bug? I don't know. We can click on a recipe. We didn't seem to hit our model hook. Okay, well that was working before. What about the thing that was broken? When we refreshed the page before, there was no object that was rendered in our view. What about if we refresh it now? Hit our model hook. And we open up the console. We can see exactly what's going on. We can see our function in action. We can see params coming in and we know what's gonna happen on the next line of code when it finds the object that we're looking for. So it seems like sometimes our route was calling the model hook and sometimes it wasn't. So do we need this or do we not? I can look at the guides and find out. I can find out what's different about how I'm entering my route. Well, the thing that's different between clicking on a recipe and navigating to it through its URL was that link to helper. Maybe we don't know how a link to helper really works or how it behaves. We can look at the documentation to find out. And the guides tell us that if we enter a route through a transition, for example, when we're using our link to helper, the model context is already provided. Our link to helper passes the object that we need. But if you just go to a route and you expect it to have a model and you get upset with it and when it doesn't have it, that's kind of on us, right? We never told our route how to get it. How would it know? Cool, so lesson learned. We won't repeat this mistake again. Well, we probably will a couple of times, just fine. Model hooks don't fire when we're using link to helpers. The way you enter a route is always really important and significant and worth considering when you're writing your code. We did some refactoring and we added a feature to our application because we decided that we need grocery lists. I need to know what I need to pack with me for Embercon for all the things I need to buy. So I'm gonna add a grocery list feature and then we hit bug number two. So when I click on one of my lists, for example, the list of things I wanna buy for Embercon, something really strange is happening. This is not the correct information. Actually, this is information from a different list altogether. How did it end up there? Kind of weird because it's kind of like this lagging state. Like a grocery list is like hanging around from the last time I went to this page. Well, kind of unacceptable. Let's figure out what's going on. Let's think about what our code has access to. Well, we are finding our model in our route. We learned our lesson last time and we're gonna trace it backwards. Our route is definitely finding the model. Where can we look next? How about our controller? There's some values from the model that we're pulling and setting and initializing on our controller just to be null. But clearly they're not null because they're coming from somewhere, but they're not coming from the right object at all. So let's look at those values again. They're coming from another model entirely. Maybe our controller doesn't know where those properties are supposed to come from. And I actually don't really remember telling it either. Poor controller. We should probably figure out what's happening inside of it. So when a controller comes into existence, where do things get set on it? Well, all of that has to happen inside of a route handler. And actually the docs tell us exactly what it is that we're looking for. We're looking for something called setup controller, which is going to let us set the model property and actually anything we want on our controller. So like let's write that and just see if it works. I don't know if it will, but we can try it. Inside of our route, we'll add a setup controller. Very, very important, we should call the default implementation by writing this dot super. And if we didn't do that, this top would be five hours because I have definitely lost a lot of time on that bug. So a whole other problem entirely. Once we call the default implementation, we can do any kind of fancy stuff we wanna do at the properties. Now we're actually telling our controller what it needs to do with the model that's being passed in. And no wonder it didn't have data that was up to date. Didn't know. I think this is a really good opportunity. Of course now our view works exactly the way we would expect it to. But I think this bug in particular is a really good opportunity and a hard lesson for me to learn was that controllers are singletons, which means that they're not recreated and any state that you pass on them is gonna persist. It's up to you as the developer to like set it up to reset it. But of course, with a ratable components, hopefully this is a bug, none of us will ever have to encounter again, unless you're using an older version of Ember. But because good things come in threes, we have to do one more bug. This one's a really fun one. We've refactored our application and now instead of just having a template, we have a recipe editor component. But something really strange is happening, which is that when I click on this delete button over here, no matter how many times I click on it, nothing happens. Which at this point, I'm just like two bugs in 20 minutes. I feel like a rock star. I should just give up and go home. But we can power through this together. So let's look at what data is coming into this component. What does this component know about? It doesn't know about everything that's happening in the app. It's pretty isolated. It's its own little thing. So what does this component know about? Well, we can see where it's being rendered that it knows about a recipe model that's being passed in and an action. So those should exist, right? Okay, well, where are those coming from? They're coming from our route. We're finding our model and we should be passing it straight into our component. And we have an action which we should also be passing right into our component. Theoretically. When I click that delete button, doesn't seem like anything's happening. So let's just look at the action on this button. Where does this delete recipe thing? Where is it defined? Because clearly it's very broken. It's not behaving the way it should. Well, if we look at our component, the action that is attached to that button lives in our component. And we're not doing anything super crazy. We're just finding the object, finding our recipe, asking the user if they wanna confirm and then destroying it and then calling the exact same function we passed it. But it's clearly not working. So let's try it again. Maybe we missed something. When we click on this delete button again, let's just be a little bit more observant. If we take a look at our JavaScript console, we'll notice that we did miss something. We have an error, my favorite. And it's really beautiful. I don't know what a lot of that means and that's okay. But there is one thing we can get from this error which is that something is not defined. Our after destroy method that we expect to exist isn't defined. We did define it, right? And we passed it in. We defined it in our route. We passed it to our component. Why is our component misbehaving? It has everything it needs, right? Why is this computer not listening? Okay, well, if it's not defined, maybe something about this component isn't hooked up right. This component doesn't seem to know about this action. So let's tell it. Let's look at what is happening in our delete recipe action which is what fires when we click delete after destroy is not defined. Well, I'm calling the function. I don't know what this machine wants from me. If I'm not defining it correctly here, maybe I should try a different way of defining it. We know after destroy is not gonna work because this code is very broken. We also know that this method is being passed in so we can't try something like this. It doesn't live in this component. This is definitely not gonna work. Well, we're passing that action down. It doesn't live in this component. Where does it live? It lives outside of the component. So maybe we need to send it back up and try something like send action. Send that action back to where it came from. Maybe, I don't know. Let's try it. We'll change our action to, instead of calling it in the context of our component, calling it in the context of where it's defined. So now, we passed that action down. We're sending it back up. What happens when we click delete? Let's try it again. This time, when we click delete, we hit our confirm step. And then from here, we'll transition to our recipes route, which is awesome, because that's what we wanted to happen. But it's also worth noting why it's happening like this. Because when you hit a bug or you hit an error, it's important to figure out what assumptions you made that caused you to get to that point in the first place. Again, the Ember guides do such a great job of explaining why. They tell us that components have a send action method that allows us to send actions back up when a component is used in a template. Which is really handy, but easy to forget when you're trying to learn how on earth actions work. Of course, you can do this a little bit differently and a bit more explicitly with the angle bracket way. In this case, when you pass an action down, it's far more obvious that you're calling something that's an attribute that's being passed down to a component. Cool. So now we know. Actions are fired on the current context. So we always need to think about where it's coming from and the context that we're currently in. Cool. So computers, right? God knows how they work, I have no idea. But frustrating, they're so frustrating and they make you feel like this all the time. Let's be honest. They aren't the only source of frustration. I think human beings are also pretty hard to decode too. It's hard to understand why people do things the way they do, why people write code the way they do. And if you think about it as a community and as an industry, we put so much emphasis on things like communication and collaboration and emotional intelligence. Teams with emotional intelligence are generally more productive. We know that these are things that are significant and worth considering. But what if all the things that we emphasize about interacting with human beings, we thought about with our machine? What if we tried to build empathy with it and tried to understand where it was coming from? I think the first step to seeing your code's point of view and seeing its perspective is recognizing that it does have a perspective. And all of this is to say that when I debug now, I think back to what my sixth grader told me those years ago. And I try to understand how someone else feels when I get frustrated with them. And in the same way, I try to understand how something else feels. When I get frustrated with it. And I think it's really, really easy to forget. Empathy for the machine is just as important as empathy for other people. Now, I just try to be a little bit kinder. And it's a good reminder that we could all afford to be a little bit kinder to the people that we work with, to the people who build frameworks that we use every day and make choices about code, to the developers that left the code base and maybe made some choices that we can't quite understand but we can try to empathize with to our machines and probably most important of all, especially when debugging, to be kinder to ourselves. And you guys have all been so kind to me. Thank you so much.