 A little more intimate. How's everybody doing? That's the only way I can tell how many people are in the room when you make sound. So I'm going to ask you to make sound for random reasons. I know Katie here is going to make sound because she's a really good heckler. But just learn from her, I guess. So first of all, there you go. Welcome. I hope the keynote was really nice. I was frenetically finishing my slides during that. So of course, I didn't see it. So if there's anything really serious I should know, someone scream it at some point. Like I don't know if type safety is a thing now or not a thing. Emojis? OK, cool. I can deal with that. That'll be OK. So the first thing I will ask of you is are there any humans in the room? I'd just like to point out that there are people not reacting at all to this thing. So there's probably aliens among us and they're probably next to you. I don't speak alien. And this talk is not for aliens. So you can translate to them if you want. Speaking of aliens, I'm actually an alien myself. I come from the planet of weird people that took Louisiana from its native people and then sold it back to you, Americans, if there are Americans in the room. Right. No, you don't have to clap. And when I say Louisiana, it's like that's Louisiana. That's the one that was sold. And there's like Denver in there. There's like really cool places too. And I feel like, damn it, I could have had like an easy vacation thing to go to if Napoleon wasn't like, oh, I don't need this anymore. My name is Olivier. This is how you pronounce it. You go, oh, li, vi, yay. And at the end, you feel like that. I am obviously French, which is like one of those things. Like this town that you're sitting on, by the way. So I'm sitting on French right now. I am so sorry. So my full name is this. I'm not going to pronounce it. You figure out how to say that. That's my internet name because that's what my mother named me. And it makes sense. For over five years, I've been developing, maintaining, and securing Codeschool.com, this thing, which is a place that brought you Rails for Zombies, the not so broken tri ruby, and a few too many jingles. Since I'm French, when I do, when I make mistakes, I often claim that it's on purpose. Air quarts are really hard with a mic, because you can't do this. Like that one time, I ordered the same dish as my fiancé at the Epcot Food and Wine Festival. I didn't understand, by which I mean I didn't listen, that she wanted to share her food with me. So when it was too late to cancel the order, I assured her that, no, I'm really hungry. I wanted to order that. And I was, but not enough to waste a bunch of money of our food budget on the exact same stuff as her. And all of this because I was afraid this very not scary person at all would realize I screwed up, just because of that. No other reason. So mistakes are made and it's really hard to admit them, but it's often harder to understand how you've managed to make one, how you ended up there, especially without feedback. So let's say you make an error, and you know that the path to recovery is this far away. Feedback is a thing that can help you up. It can help you get to recovery at some point. But there's something missing in between those two things, an animation perhaps. A cognitive step that can make this much more accessible with proper context. So if you have the context as a little step stool to get to recovery, it's that much easier. And that's sort of what I'm gonna try to talk to you about today, and funky animations. So the why is usually the first thing that people ask when there's an error. Why? Why did it happen to me? We don't understand why computers seem so easily displeased with us, and yet we are so easily displeased with users if they dare stray away from the happy path. Often the most interesting question to ask or not, why they're what or how or when or where? So that's what we're gonna talk about today. But first I have to do the AvD thing, which is to define what I'm talking about. So we're gonna talk about definitions and words and things. You've been warned for those who are following me on Twitter, I'm so sorry. So an error is a mistake. It could be a spelling error or an error of judgment. The broad definition is the state or condition of being wrong in conduct, so something you did, or in judgment something you decided. The specific one for us technical folks is a measure of the estimated difference between the observed or calculated value of a quantity and its true value. So simplified for people who don't like long things. Observed value, not equal true value. But the thing that I'm really, really excited about when I find words like that, and I tried to define them, is the etymology, like the origins of the words, like the DNA of that word and how it came to be. So you can tell that error comes from the middle English error. I don't know why in French we say ooh, with OU, so I really wanna say error, which is very unuseful because it happened to be error in Latin anyway. So why, I don't know. And the Latin is really cool. It's wondering about. So you're trying to go somewhere, and you're oh man, and you lost your way. And that's a perfect, I love that metaphor that just image of you wandering about trying to get to the thing that you're trying to do. So wandering is usually, I think it can be enjoyable if you have a friendly environment and lots of signposts to find your way back to the place that you want to get to, or you can end up finding really hostile people in a way that don't want you to help you or just are not really friendly. So we all want to stop making mistakes, but it's impossible, and we know that, but it's kinda like the grokking thing. We know it, but we don't grok it. We don't internalize the fact that we're always going to make mistakes and pushing them away is not really gonna help. And in moments like this, I like to think, kinda like to reframe at Go-to-Go, for instance, like a way to reframe is to go do support, and if you work for a product company like that, talk to people, humans, who are using the software that you use, so it's to find the target, the people that we're trying to build things for. And broadly speaking, for us, it's end users, which is a really weird phrase when you think about it, because it sounds like you're hatching a secret plan to eradicate all users and finally be free of real-world consequences and requirements, which is definitely not what we wanna do. So instead, I wanna talk about middle users, which is my neologism, wow, that's hard to say in English. So I'm guessing people in this room are actually end users of many things, but they're also middle users of a lot of other things, like the software that we build. We're not just the people using the finished product. So I'm gonna do a terribly awkward analogy that goes like this, from left to right, we have the start user or the robot or computer, and in the middle, we have the middle user, we go to conference, we spend time all day instead of eating inside all day, instead of eating po-boys and sipping coffee from the French coffee truck, go there, it's awesome, all day, that's really good. And then there's that little running rascal over there, that's our end user, like running away. He's running across the street without looking and clicking on things too fast. And he doesn't have a code on. So occasionally, the start user or robot, which could be the language or the operating systems that we use, decides to yell at our defenseless little end user, and when that happens, I said decide as if it decides, but really it's often because we dropped the ball and gave Papa Roomba over there a little too much power over people we don't really, who don't really understand what he's yammering on about error code 253 or something like that. So we intervene. We put on our fancy error handling badge and just to be sure, maybe a helmet, because those pinchers are a little scary over there, and then we thwack the start user with some justice hammer. I don't know what, yeah. So it's not just the end users who suffer from confusing error feedback and that either isn't appropriate or just plain hard to understand based on context. It's also middle users like us who build software for the end users. Instead of Windows and iOS or those new credit card chip readers that beep at you viciously, even though the transaction succeeded and they want you to take your card back, I'm like, meh, meh, meh. Like it's always that, why? I didn't fail. Instead we have Postgres, Ruby, SAS, the extensions that growle in our general direction once in a while for no obvious reason. So a few months or maybe years now because time just slides away. I started noticing occasionally strange exceptions popping up from the call sites for methods that had recently been refactored, which surprises no one. Let's say we have a method called explode which takes a single code argument and with that code argument, it just prints a string and it's not very useful. And when we call that method with no argument, we get an argument error that says wrong number of arguments given zero expected one. So it seems normal. The backtrist that follows the exception message points to the first line of the explode method definition and when we look at the first line of the explode method definition, we definitely said we wanted a code argument. So that's good. Everything's fine. So when you call the explode method again, this time providing the argument, it works just fine and everybody's happy. Now, let's say our team refactors this method to make its interface more explicit. So the code argument becomes a required keyword argument with that little colon that's really hard to notice. Very, very easy to, yeah, not see. And so the only change is a single character and then when we call with no argument, we get a very useful error that says argument error, different message this time, missing keyword code, cool, nice. I know what I'm supposed to supply. But what happens when we pass the original argument with no keyword? Does anybody have any idea what happens there? So missing keyword, expecting one argument, got one argument? No, both of you are wrong. I feel really good about that. That was Sandy and Shawn Griffin, just saying. So probably you didn't expect this, wrong number of arguments given one, expected zero. That does seem wrong, right? So it's clearly not true. We had definitely a keyword like required argument right there, so I had the same reaction that doesn't seem right. And then I asked a bunch of people who were smarter than me, which is the only way to get things done, really. And it turns out that it is a bug. So submitted that, what, nine months ago now? And as soon as you submit a thing on the Ruby bug tracker, it's no boot time. It's just, I spent way too much time on this, so I'm just gonna point out everything that's in there. All of these shaws you see at the end of his tentacles are actually his last commits, like from yesterday. Because that's literally when you're all sleeping and drinking and keynoting, he's doing that. So this is Nobu, he's amazing. I'd already talked about it, and a bunch of people have talked about how incredibly productive the patch monster, as he's called, is. And he just responded almost quick, like the second response to the thing was nine months ago, so probably the same week. How about this? It's a fix, that's it. That's all I had to do, I just had to ask a question. And so he made a really simple fix, and it's been merged, like four months ago. So that's it, end of the talk. So now when you use the old thing, the old method signature, and you send it, you still get a not super great error message. There's still work to be done there, because it is not about number of arguments, and it's not given one expected zero. It's given one expected one, like you said, Sean. But at least you get required keyword code. Like if you keep reading, and don't skip until that, then maybe you find useful help. And that's now included in Ruby 2.5.0 preview one that was released a few weeks ago, so you can already play with it if you want, and it should be in Ruby 2.5.0 on Christmas, which is cool. By the way, if you're curious about my amazing capability to ask a question and have other people do the work for me, this talk explains to you how to do that. So it's on YouTube somewhere. It's from an old RubyConf 2014. So yeah, and also there are lots of resources at this very conference you're sitting on at to help you help Ruby, so please do that. Or if you're excited after the conference, go ahead and try to find old Ruby bug tracker issues that were maybe not updated or something like that. All right, so now that that's out of the way. Let's talk about joy. I have a lot of joy right now. I'm way too excited to be here. And speaking of someone who just talked to you, Matt said, for me, the purpose of life is partly to have joy. Programmers often feel joy when they can concentrate on the creative side of programming. So Ruby is designed to make programmers happy. Right, and Ruby has inspired a ton of other languages and frameworks and things to kind of focus more on that side of the performance of the productivity. Things like Rust, which now have errors like this, could not find type Neuromancy, but did you mean Necromancy? Lixir, which gives you this amazing little essay to tell you like, well, you should try this other syntax because it's nicer and also, you know, it's super nice. And Elm, and I think that might be my favorite and we'll talk about it later and you'll see why. One, density of information, very well explained context and everything, so I'll explain everything later. For now, we'll talk about Ruby a little bit more. So Ruby also does this, by the way. So I don't know if you know, but since Ruby 2.3, the did you mean gem is included in Ruby? So all of these like very easy to fix errors that you would spend probably a week trying to figure out why, why is my calls to explode? They're all failing, I don't know why. Well, because you didn't spell it right. So now at least that's an easy fix and you get instant recovery from it, which is I think one of the easiest things you could do in a language or framework or library or anything that you're building is like, if there's an easy, cheap recovery to be had, then why not put a thing like that in? And you're not actually handling the error, by the way. You don't have to because this is a mistake that a lot of programmers like us make and a lot of users also make. So that can also apply to end users. But for a little quick minute, I want to talk about these little guys over there, little things that are in the line, the actual call to the thing that's not found. So I want to call this because we're in New Orleans. I want to call this contextual voodoo because magic, like everybody uses magic. So if you look at the exception classes, there's a lot of things that they give you, they give you a back trace, a cause, a message and things like that. And for now in Ruby, we get the line number, but we don't get that amount of detail. We don't really get the column and like the specific keyword token that actually caused the exception. It might be something, so I asked the question to Matt's, I think yesterday, and it might be something that's possible with AST to grab the column information from that or I think that I was trying to see through the code of that location class that actually gives you the line number for an exception. Anyway, there might be some hope there. If you're good at C and you want to do something that has obvious impact, you could look into that. And speaking of obvious impact, I found this thing that's two years old now. And I really thought it was like a few months ago, but Richard Schneemann basically did this. He just submitted that as a, oh, it'd be nice. So it's kind of like the same, like I don't think there was an implementation offered with it, but someone made an implementation that was just pure Ruby that just found the, I think it was the receiver of the call if there was no method error to say, this receiver. And the problem that it was fixing is these calls, when you have two calls to the same method on the same line that are causing an undefined method call and you don't know which one caused the undefined method call. So the problem is who did it and a little error could go a long way. And this is the proposed, I think, yeah, that's the proposed version that Richard was submitting. It's like, instead of saying undefined method call on nil class or something like that, it says the method call is undefined on receiver nil class, which first is giving you the context. So where that thing is happening, exactly, not just somewhat vaguely where it's happening. And then it's giving you the feedback. And I'm pressing the wrong key. There you go. And the difference between these two things I think is easier over understate. So this is the previous error message, undefined method call for nil class, which is correct. But kind of, it's just, I don't know, I've seen it so many times that I forget to even read it, I think. And this thing kind of hones in on what is the actual problem. So it's a message that takes a little bit more care and clarity and explaining exactly what's happening and what you might have missed, which I think matters. And I think that how you say matters. So I think we could find a way to, in our libraries and even the language itself, to find these places where something could be misconstrued or misinterpreted and just clarify it. So it hasn't been updated in two years, which is kind of sad. So if you want to help implement that, also you can try to do that. I think the issue tracker number was somewhere. I'll send it to you and just ask me. So I would like us as a community, it would be really cool, if we could try to make it so that we contextualize errors better. So we're pretty good at giving feedback in most scenarios, you get feedback. So you get the, something happened, cool. But we don't really get the context necessary to either understand really quickly what to do about it or just to know how did it come about? How did it, like in what scenario did this occur? And then I found this funny tweet about JavaScript, which I think applies pretty much to any language. And it's not a dig on JavaScript, honestly you could do that in Ruby too. And I think that it's a joke, but effectively that's what happened. We've offloaded the task of giving context to an error message to Stack Overflow, which could be good, it could be bad, but I think it might save everybody a lot of browsing and a lot of network calls if we, we could even call it directly, right? Like that. So that Elm error, let's look at it. It's gorgeous. I don't know if you can see, it's not very big, so we're gonna go line by line, almost. So the first thing that it tells you is what happened, which is an alias problem. And it's at the very top and it's very big. So it's super obvious what we're dealing with right there. So you get the context, the type of error, and then right after that you get where it happened because it tells you this is the file and this is even the code where that happened, which is amazing. It's not just telling you where it is in line number, it's showing you those lines in context in the error message. And then it tells you how it happened. It explains to you that this alias is recursive and that makes an infinite type and you should do this. And here's an example how to quickly fix this. It's, I think they call it a naive fix or something like that. Yeah, I suggested this naive fix. It doesn't mean that it's gonna work for you necessarily, but even if it doesn't work for you, it might be adaptable to your circumstance and you might find a way to recover from that thing really quickly. It's there. And I think the last thing at the bottom, it's even sending you to GitHub to I think a specific class to find more information about the context of this if the naive fix doesn't work for you. So 10. It's great. Let's look at a not so great one. I don't know if Sam, you don't have to read that. I don't know if Sam is here. Sam, Pippin? No, that's cool. I'm not trying to be mean about RSpec at all. I don't think this has anything to do with RSpec. It's actually more of a Rails RSpec intersection bug, which sucks. So the actual error is undefined method shall escape for path name lib, no method error. And so I can understand what happened here. There was an undefined method. Does it help me? And if I look at the back trace, the first line is this thing. Runner, I have no idea what that does. Load path, I guess that was an error with a path, so that sort of makes sense. But again, that doesn't really help me. And so what I end up having to do is go back to the huge stack trace that you saw at the beginning and just go line by line like, okay, what made you angry? Just like, slowly. And so I use tools like pry and I use cool little interactive debugger tools. You can even do that in the Rails web console. No, I don't, I think web console does that, but better errors is better, so use that. And you can literally click on a line in the stack trace and go back to that place so that you don't have to do that in the command line or to jump around your editor. So does it tell me where it happened? Not really, because it's telling me where it blew up, but not really the place in which I should have done something different, which ends up really hard to figure out. And does it tell me how it happened? Nope. Does it tell me how to recover? Nope. So it's a five, because half of the things that it could have done, it didn't do. And in the end, by the way, if you care to know, I used, I think somehow I used the string and I, instead of putting a path name class or something, no, I used the path name class and that wasn't okay in the load path. And Rails was fine with it. RSpec's like, no. That was hours of my life. So it was unclear and it was too late in the stack for me to know exactly, like to find the context to recover from it. Here's another one. That's a super common one with beginners through Ruby because they tried to install a gem and then they get an error like this, or even worse. They install a gem, it works, because they used sudo, but they didn't know that sudo is the thing. And then they try to update the gem and this happens. And they don't understand why. So again, you know what happens. You can't do this. You sort of know where it happens because it tells you the path. So it's kind of clear like, but you don't know what library Ruby 2.0 is. You don't know how it happened and you don't know how to recover. And so again, it's a five. It's not a context specific error. Well, there is some context, but it's not useful. So what's missing is a way forward to recover from this thing. Back to that little terrible animation that I showed you earlier. There's a few little stepstools that are missing to get there. Resolution hints, basically. And since he's here, I'm gonna quote him so it's gonna make him feel weird. But we were talking about this with Justin Searles and he said something that I think is very nice for this kind of context. As a library or application, not having a functional need to rescue a possible error doesn't grant us license to ignore how confusing the error might be for the person who ultimately sees it. So in the case of RSpec there, it's not really their fault that this path name just snuck through Rails to them and they didn't know how to handle it to load my test files. It's just, it's something that could happen. So I don't know who, I don't really wanna lay the blame on specifically libraries. And I would like both the library maintainers and users to be more aware of the kinds of context sensitive things that they could offer people. And so that they can provide more farm to table exceptions that are local. Thank you. I'm gonna let you, yeah, thank you. That was like 30 minutes ago too, so I'm super happy with this one. And then on the language side, so the language implementers and users which are everyone here, probably. There's another way to recover from these things or fix these things and that's turn-by-turn contextualization. So the Elm example was that it was basically like first do this. Well, we're here, we're starting here, this is where you are, just look around. And then we're going there and the way you can go there is you can take this step and then this step and then that step. That's amazing and it might seem like a lot of work to do, but there's a lot of easy targets. So if you ever download, don't do it on this wifi please. The Ruby source code, the trunk, Ruby trunk is a file called error.c That has all of the error classes and lots of error handling information and inside of it there's a comment that shows you all of the built-in subclasses of the exception class, which you should never rescue. By the way, that was a slide, I had to take it out. Please don't do that. Yeah, I had a funny slide, I'm gonna say it because that was a good, I think, yeah, rescuing exception is an error. Sorry. So that's our target, this thing, this list of exceptions, because every single one of them, I just went through argument error and showed you, in the context of keyword args, argument error can fail because probably because it was introduced as a new feature and some things slipped through and some test cases weren't tested for specific kinds of scenarios for exceptions, but there's tons of syntax error, is a great one, that could be helping a lot of beginners. So if we target those, if we target things like argument error and try to make them a little better, I think the impact of those improvements is seen by everybody really, really quickly, even if it takes a few months to get merged into the new release. So it's easy to forget that your job is to create the new and exciting errors of tomorrow, that these kinds of languages of library level issues can send people into a panic and hurt their productivity. So I mean, you can see users freaking out about a bug, but there's also lots of developers who are new to Ruby or not even new to Ruby and they just break down in front of one of those errors because the context is so intractable, so confusing. So I'm gonna use the definition that Avdi Grimrel lays an exceptional Ruby from Burton Meijer's object-oriented software construction. An error can cause a failure, which can cause an exception and the part that we're interested in, that I'm interested in, that I want us to work a little bit more on, naturally we as developers want to focus on the errors and prevent them from happening. We want to make test cases to progression tests and things so that the errors don't occur, but I'm actually interested in exceptions because there's always going to be errors. So it'd be nice if we made it a rule to take better care of our exceptions. Thank you.