019 RR Book Club: Exceptional Ruby with Avdi Grimm
- Exceptional Ruby (from exceptionalruby.com or pragprog.com)
- Avdi wrote the book because he felt like he sucked at exceptions
- Avdi's Ruby on Ales talk
- The method method
- redefining warn to raise an exception for access to the backtrace
- Matching an exception based on the error message
- Custom exception matchers
- Make an error module and rescues the exceptions and tag them with that module.
- Nested Exceptions
- Bundling all exceptions raised during an import or unreliable process.
- Avdi asked about raising multiple exceptions.
- The checklist for raising an exception. "Are you ready to end the program?"
- rescue $!
- nil isn't very informative
- Special case object - something benign that represents the actual state of things
- begin is probably a code smell
- Putting bulkheads in your code
- This book should be required reading for gem authors.
- James pointed out that the book missed Thread#abort_on_exception
- Avdi outlines the process for writing the book
- Emacs org mode
CHUCK: Hey everybody and welcome back to another Ruby Rogues podcast. I'm your host, Charles Max Wood. And this week on our panel, we have… first I’d like to introduce our guest Rogues. We have Steven Ragnarok. I don’t know where he is calling from, but I´ll let him introduce himself and then we'll go on to the other members of the panel. STEVEN: I'm Steven, I do Ruby development. I'm based in San Francisco, but I live in the South Bay. And yeah, very new member of the community. CHUCK: All right. But he read the book, so. STEVEN: Yes. Twice, actually. CHUCK: All right, cool. We also have the author of the book we are going to be talking about today, Avdi Grimm. AVDI: Hey, this is Avdi. I write about software development at Avdi.org/devblog, and about distributed teams at wideteams.com. And I wrote Exceptional Ruby. CHUCK: All right, we also have James Edward Gray. JAMES: I'm jealous of Ragnarok’s last name. CHUCK: [Chuckles] Also, we have Josh Susser. JOSH: Hello from San Francisco. I blog occasionally these days at blog.hasmanythrough.com, @joshsusser on Twitter, and I'm one of the organizers of the Golden Gate Ruby Conference which will be happening in just a week or two, and I'm super excited. And I'm a self-entrepreneur. CHUCK: All right. And I'm Charles Max Wood. I just wanna point out that my wife just took my four year old to her first day of preschool, and didn’t wanna take the baby with her, so if you hear any sounds, he's in here and I'm trying to keep him happy and quiet, but we'll see how that works. JAMES: He's trying out for the position of mascot of the Ruby Rogues. CHUCK: There we go. He's two weeks old and he's a little noisy. [Chuckles] Anyway, today we are going to be talking about the Exceptional Ruby book written by Avdi. If you haven’t read it, you really ought to because it kind of makes you think about something that at least in my case, I haven’t thought a whole lot before. So you know, I highly recommend it. I'm going to go ahead and let the panel get it started, and let me see if I can calm my baby down real quick. [Chuckles] JAMES: So I thought I’d probably mention our bias, since people have already been haranguing me over Twitter about it. It was my idea to do the Exceptional Ruby book after I saw Avdi’s Exceptional Ruby talk, and realized how amazing it was. I went and read the Exceptional Ruby book, and was very impressed with it as well and I thought we should do it to open up. So some people had said, I'm already doing this to sell millions of copies of Avdi’s book. That which is totally correct, not because I want Avdi to make millions of dollars, but because I think everybody in the Ruby community should read this book. So that’s our bias. I’ve heard that it's okay to be bias If you stated it upfront. AVDI: Yes, and James we’ll discuss your kickbacks after the show. JAMES: That’s right. I do have a percentage that I'm expecting, and yeah. So anyways, Avdi why don’t you tell us what made you wanna write this book? AVDI: So… CHUCK: We're not going to make Josh define what a book is? [Laughter] JOSH: Well, I got to say, I love that Avdi starts the book off with definitions. CHUCK: [Chuckles] JAMES: [Chuckles] That’s a good point. JOSH: [Chuckles] No, I'm not defining a book definition. CHUCK: [Chuckles] Okay, Avdi go ahead. Sorry about that. AVDI: So I think the biggest reason that I did this was I felt like I sucked at exceptions. CHUCK: I didn’t know I did until I read your book. AVDI: [Chuckles] JAMES: Me too. That was the exact same thing. AVDI: I had been doing software for a while, and it seemed like every project that I did, I felt like I was kind of making the same decisions over and over again; making decisions about how to structure my exception hierarchy, and how to decide when to raise and exception or when to do something other than raising an exception. And a lot of stuff like that, I felt like I was kind of winging it every time, and maybe making different decisions every time to see who they worked out. And I felt like there were other things, there were a lot of other object-oriented design things where I felt like I had really good, solid rules and heuristics for making decisions about how to structure the code. And based on books that I've read or based on principles I discussed with other people or principles that I worked out on my own. But the whole failure handling category, I felt like I kept just sort of stumbling around in the dark over and over again. And I didn’t really feel like I could justify the decisions I've made other than, “Let’s try it this way this time.” So that was sort of increasingly bugging me more as time went on. And I've sort of realized that the best way to get good at a topic, is to propose a talk about it. Because if the talk is accepted, then you have to become an expert. So I proposed the talk about exceptions in Ruby, and I first did that in front of a large audience at MagicRuby in Florida. And in the process of putting that together, I realized that I just had a ton of material from the research that I've been doing, and from the notes I have been collecting, that I couldn’t possibly fit into a talk, and so I decided to expand it out into a book. And that’s how it was born. JOSH: Cool. I wanna point out that I saw that talk that you did Avdi on Ruby on Ales in April, and I thought it was a really good talk. And that talk just went up on the Confreaks site, so we can put that on the show notes, so people can actually check out the talk that you just mentioned. AVDI: Yeah, and you can watch me running out of time. [Laughter] JOSH: That was a pretty fast paced talk. AVDI: Which is kind of the reason that I decided, “Okay, I need to find a way to talk about this stuff where I'm not compressed into 30 minutes.” CHUCK: Yeah, well isn’t it interesting too, you get to 30 minutes and you start like mercilessly chopping stuff out, and you are like, “I didn’t wanna leave that out.” But you don’t have a choice. So I can see where you are coming from there. AVDI: Yeah, and I highly recommend that approach to people that are doing talks, because once you feel like you have somewhere else that all these ideas are, it becomes a lot easier to start cutting things out and making you talk better by making it shorter. JAMES: I general only write 30 minute talks, and then if they give me more than that, I just fill with jokes until it's as long as they gave me. [Laughter] CHUCK: All right, so why don’t we get into the book and talk about it at all bit. Josh mentioned the definitions at the beginning, and I thought that was really interesting. It kind of made me think about it from two different perspectives; one was just kind of redefining the terms, but the other was the idea of coding by contract, and how that plays into what an error is and what a failure is, and what an exception is. JAMES: I agree. I really liked it a as well. I have kind of a nitpick about the title. I was wondering did, “I Wanna Teach You Amazing Ruby Voodoo Veiled Inside of Exceptions,” not fit or what? AVDI: [Chuckles] Yeah, actually, that particular string causes an obscure error in the text formatting engine. JAMES: Oh of course, yeah. AVDI: So I'm waiting for my check from Dan. JAMES: No seriously, I really thought that was one of the great things about the book. I think everybody is going to look at this, look at the cover and think, “Oh, it's about exceptions. How freakin boring is that?” And leave it. AVDI: [Laughs] JAMES: And I got to admit, that was one of the initial reactions I had. I was like, “Really? About exceptions? Are we just going to talk about that?” But then when you read the book, you realize that it's actually a wonderful book about Ruby… I would say ‘strategy,’ actually. It's a book about strategy. We have this sub topic we are going to take, and that is exceptions, but let’s try to come up with a series of steps that makes sense, that we can do the right things when we are faced with this kind of code. And because of that, I felt like it really improves your thinking as Rubyists, and that was one of my big motivations for doing this book club on it, because I think it's really great that way. JOSH: I like that too. The thing that I like too is how comprehensive it is in terms of sort of low level to high level. There's certainly a lot of high level thinking about strategy, that is in the book and how to organize class hierarchies, dealing with polymorphism, inheritance. But there's also a lot of really low level stuff about like down to the magic constants in Ruby, and how they interact with different stack frames and interacting with things on the command line. Just a lot of really good detailed stuff, that is often glossed over in this kind of documentation, so congrats on that. AVDI: As somebody who pontificates a lot on my blog, I kind of have a horror of releasing something like that is full of high wavy platitudes about good design, without actually s_o_rt of marrying that to some really hard technical knowledge. And also, I'm a total language geek. I mean that’s why I got into Ruby the first place is that I just like fiddling with languages, so that just reflects one of my interests of getting down into the nitty gritty. JAMES: Yeah, I was actually going to say that’s another one of my favorite things in the book is it has a unashamed Rubyness to it, you know? I mean, uses some things you do not see very often like method, the method method, which actually lets you get a reference to a method. Module new, thread local variables, kernel array -- which is one of my favorite methods in all of Ruby -- or hash fetch. All kinds of things that are just, it's very unashamedly Ruby and I loved it for that. CHUCK: Yeah, one of the other things that really enjoyed was just the code samples in general. I mean, a lot of times, you get these code examples and they are like, this dummy code that you would never consider using. And in a lot of cases, you know, even though it is kind of dummy code, at the same time you know, it really gives you an example of, “Hey, this is something that you can do. And here's how you do it. Here's how you get the ball rolling with it.” And you know, it gets you into taking over things like raise or rescue or some of these other things, that you really wouldn’t think about because they are just kind of ingrained in Ruby. And so instead, you redefine warn. So that was one of my favorites is when you read fine to warn to actually raise an exception, to get the backtrace and everything else. I just really liked some of that… the things that you don’t think about being able to do with Ruby, you just kind of twist it around and make it do what you need it to do. AVDI: That’s why I love the language. Well, one of the reasons anyway. I love the language that will let you redefine it a fair amount. JAMES: Yeah, along those lines of what Chuck was saying, you always try to find the best way to do something, but you also weren’t afraid to admit when you couldn’t find it. Like the biggest example I could remember of that is there was a case where you actually matched an exception based on its error message, which comes out to be pretty ugly and gross, but you couldn’t find another way and that was how you did it. AVDI: Although there's another section which I probably should have put like a link from one to the other, where I talked about defining sort of a magical custom exception matchers. And you could use one of those to make that a bit cleaner, but it's still a bit hacky. [Chuckles] STEVEN: Yeah, I really enjoyed the fact that one of the things that I remember just from reading wise guys use what Ruby gives you. And you used every error handling facility that Ruby makes available, in ways that makes sense for those error handlers, as opposed to only sticking with raise and fail, or only sticking with throwing a catch or only doing one handling strategy as opposed to using the best of what Ruby gives you for the situation. And that’s something that I've tried to take back and bring to the projects that I work on. AVDI: Glad to hear it. JAMES: Speaking of that, has anybody used any tricks from the book? I've caught myself using two, already. STEVEN: Yeah. I built a… you have a background process and rather just running it like directly from rescue’s perform method, it's now wrapped in an object that caries all the state, and the error handling is based off of asking the object if there was a success or failure, and then retries or not based on... That’s the one that I use most recently. Last week, actually. CHUCK: What have you used, James? What are the two that you have done? JAMES: So I used the trick where Avdi makes an error module. CHUCK: What? You had Avdi writing your code? JAMES: Yeah, obviously. CHUCK: [Chuckles] That’s a neat trick. JAMES: I used the trick where he makes an error module, and then rescues the exceptions, and tags them with that module, so that you can raise normal IO errors and stuff like that, but you can rescue them as my library::error. But they are still the normal exceptions, so you basically get like two ways to recue them. JOSH: I got to say that is the slickest thing I have seen in print… I am laying in bed reading it on my iPad and got so excited about it, and sat like, “Oh, my god. This is so cool!” [Chuckles] it's because of the style where you were going and that’s where you went to it's like, “Yes! He nailed it!” AVDI: [Chuckles] JOSH: Now I know what sports fan feel like. [Laughter] AVDI: That’s a great quote. JAMES: Yeah, I used to always use one of his other strategies that he gives, where you basically wrap it in an exception and then you just put an attribute on it that holds the original, so you can still get at information. But oh man, that totally sucks, compared to just mixing the module into it. AVDI: You know, the more I've been looking at code since then, the more I've been wondering whether there are even cases in Ruby where nested exceptions are superior to that approach. JAMES: Yeah, I can't really think of one. AVDI: You know, I first kind of put it in as an alternative to nested exceptions, as maybe an interesting alternative. Actually, at first I wasn’t sure I was going to put it in. I was kind of rolling it around in my head, and I got to do a discussion with Jim Weirich at Ruby on Ales about it, and he thought it was a neat idea. And so I thought, “Well, if Jim Weirich thinks it's a good idea. I should probably put it in.” And I've been getting a lot of good feedbacks and I haven’t heard anybody say that, “Oh, there's a reason that it doesn’t work out well.” And so I'm really kind of moving towards just never using nested exceptions. Instead, if I need to like a dual role exception or something like that, just tag on a module. Because I mean, all I really show is using it as a tag, but you can also, I mean you can add a little bit of functionality if you need to, in that module as well. JAMES: I can think of one case where I did kind of used nested exceptions that maybe wouldn’t adapt well. I was going through and doing like a mass import, and I would rescue all the exceptions along the way, and then like bundle them up I would throw one exception, but then it had like a hierarchy and everything that went wrong, that might be the one case where I would prefer the nested exception approach. AVDI: That’s a really good point. And that’s actually something that somebody brought up at Rocky Mountain Ruby. That it would actually like to put in -- if and when I do -- a second edition. So the question is, you have you this retry functionality in Ruby, and you can retry something that went wrong. And if you have like a retry loop… or not a loop, but effectively a loop where you try something three times and you have a threshold and then you say, “We are just going to give up.” And so, you got three exceptions in a row. When you give up, the first exception you got, do you raise the last exception you got or do you bundle them up into some kind of meta exception and raise that? And I'm not sure what the answer is, because I can imagine a case where let’s say you are hitting a web service wrong, so the first exception you get is 40… heck if forget. But anyways, basically an exception saying you are calling this wrong. And then the next two exceptions you get are… stop hitting the service so fast, 503s or whatever. If you only raise that last exception, then when you are debugging the issues in the application, you'd be like, “Oh, we are failing because there are throttling us, or because their service is slow is having difficulty.” And you might completely miss the fact that the first exception was something different; the first exception was a… you called the service wrong. So that’s something I've been kind of rolling around in my head since then. JAMES: Using your own checklist, -- which by the way, I have found myself doing -- now when I'm raising an exception, I'm always hearing Avdi whispering in my ear, “Are you ready to end the program?” One of the things you do say in that list is are you throwing away vital information? And so for me, that means you have to keep the first exception in some form. AVDI: Right. But you know the implication if you do bundle that up somehow into like a new meta exception type is that you might break the expectations of calling code. Previously, the calling code was able to be unaware of the retry loop further down, because it has certain exceptions that it already knows to handles. But if you handle it up into a new kind of exception, then you are having to handle it in a new way. So I'm not really sure… I can imagine a few different approaches to handling that. CHUCK: I think a lot of it depends too for example, if I had a retry loop going and you know, I was just catching or rescuing and retrying on just the time out error, and so I got that three times and I was tapering off spending, waiting longer and then trying again and then finally giving up, I don’t think it's necessarily informative at that point, to have it basically tell you, “I tried four or five times and it timed out four or five times,” as opposed to just saying, “It just timed out and deal with it now because we've given up,” as opposed to some of these other things where yeah, you get an initial error that’s error exception that’s different from the subsequent ones. So I think it really depends on your context in the problem or situation you are in. AVDI: Yeah. The only hard and fast rule I can think of, not even hard and fast, but I think I would always put some kind of log statement in there every time an exception is rescued. CHUCK: Yeah, I think that’s useful. I definitely agree with that. JAMES: So can I say the other trick I've caught myself using? CHUCK: Please. JAMES: I love his rescue $! At the end of the line… AVDI: [Chuckles] JAMES: so that basically, you catch an exception at the end of the line and just throw the object back. So that the exception is what ends up getting assigned to your variable. So you can either carry away a success state in the variable, or an exception object which you can deal with layer. I love that trick. AVDI: Yeah, I was very, very happy when I found that. I was very close to the assumption that the rescue statement modifier was just a bad idea all the time. And then I realized that you could rescue error info and use that as an exception, as a raise to return value converter. And then I was very happy. CHUCK: I think it's interesting too that you made the point, and this goes with what we were talking about before, where you talked about how nil isn’t very informative. And that usually what we wind up assigning or passing back or whatever. And yeah, it isn’t very informative at all. It doesn't have to really identify what the problem is. So doing what James suggested, and having it assigned to that variable and then just doing a quick management of that, makes a lot more sense. JAMES: Yeah, what I think is cool about it is people usually rescue nil, and then a few lines down, they are sitting there checking, “If it's nil, do this. Otherwise do this,” which is like a special case. Alternately, you can rescue $!, still do the switch if you want. If it's still an exception object, do this but you still have the context of what went wrong, whereas nil gives you nothing. AVDI: Yeah, nils are the devil. CHUCK: [Chuckles] AVDI: If you've ever seen the other talk I've been doing a lot -- The Confident Code talk -- I talk a lot about getting rid of nils, because they don’t tell you anything. They mean so many different things and they don’t tell you anything about where they came from. And a lot of times, they are sort of an excuse to break out of object oriented land and to go back to the procedural land, instead of actually coming up with an object that represents the state the system is in. CHUCK: So nil literally means nothing? AVDI: Exactly. STEVEN: Yeah, I have had that problem with active record. Whenever you try to find an object and it's not there, you get back a nil instead of something useful like the record with this…. You know, I’d really like to know what ID of objects failed to be there, because obviously the system expected it to be. AVDI: Yeah. I'm a big fan of special case objects. I guess I do talk about that a little bit in Exceptional Ruby, some kind of special case, like a benign object that more or less supports the same. STEVEN: I think benign value that everybody uses without kind of about it is the empty collection. If you do something and you get back empty collection, your each method is not going to iterate over anything. AVDI: Right. And that’s not a bad pattern. STEVEN: No, it's brilliant. It's something that people have been using some kind of subconsciously, that when I read, “Oh hey look, I found that this is the thing that everybody is doing. It's just not recognized by the majority of people doing it.” AVDI: Yeah, I mean that's like the comparison I always use is jQuery, because jQuery has pretty much the concept of everything is always a collection. And the wonderful thing about collections is well, a singular object is either one or error, whereas a collection is zero or more. There isn’t an error case in there. JAMES: Right. And that’s actually the reason why kernel array is my favorite method in Ruby, because when I do run into some dumb methods that’s returning nils, I just wrap it in a call or array so I can treat it just like Steven says is an empty collection. STEVEN: That’s a good idea. JOSH: Yup, I've done that. Probably my least favorite method signature in all of Ruby is Active Record base find, which on failure, will either return nil, return an empty collection, or raise a record not found exception. JAMES: It's a lot of option, Josh. Come on. AVDI: [Chuckles] JOSH: [Chuckles] Yeah, well the call signature is also really crappy. It's like you can pass in an ID or a bunch of options, where you can first or all. AVDI: The unfortunate thing is that as far as I know, it does not support the fetch protocol. JAMES: Yes, that sucks. Fetch is one of my favorite method in Ruby. AVDI: Yeah, I mean, fetch is my thing. I find a way to score a fetch into every single talks I do, because it's such an important idiom; the idea of letting the caller decide how to handle the missing case. It is very Ruby because Ruby has blocks. JAMES: Exactly. AVDI: And yeah, actually I'm going to have to do that. I'm going to have to go write a quick little fetch for active record gem if nobody has done it. JOSH: Yeah, so in Smalltalk the syntax for blocks I think was slightly more lightweight than in Ruby, because you could pass multiple blocks to methods, the keyword arg made that really easy. And so there were a bunch of really good methods in Smalltalk, where you would pass in essentially the exception handling code, as a block. And that was a very common idiom in Smalltalk. And I think one of the reason for that is that style of coding came about before Smalltalk supported exceptions. But it was a very common thing; you'd say the equivalent of array.detect and if there wasn’t anything you'd say, if absent, pass in a block to evaluate if that thing wasn’t there, so that’s very much like fetching Ruby. But here's the block that you should deal with if the standard case didn’t succeed. That was a pretty common thing in Smalltalk. And if you look through the API for if absent in the collection protocol, shows up fairly often. And I think it will be nice to see more of that in Ruby, but I think that the syntax for blocks makes that a little bit harder in Ruby. JAMES: Right, because you can't easily give a case for if it succeeds or if it fails. AVDI: Right. I mean, it's getting a little bit more succinct. Love it or hate it. The stubby lambda is a bit more succinct for doing one off lambdas, so that makes it a little easier to have keyword arguments that take a callable... But you know, yeah, at the risk of drifting into another topic that’s sort of on the list for the Rogues, it's just a great example of using a classic OO design principle, “Tell, don’t ask.” Where you tell what to do in the case of a missing element, rather than asking whether the element is missing. JAMES: I loved one other thing that you really talked about in the book. You know, we've talked about the good Ruby stuff, like avoiding nil and things like that. This was one thing I have not really thought about until I saw your talk. And you said that basically begin is probably a code smell, in cases where you see the word ‘begin’ in Ruby. And then you go and show how if you are going to a begin rescue kind of thing, and then you just go ahead and just break it into a method, and use the built in nature of methods, which just lets you rescue anyway. And that’s sectioning off your exception code and stuff like that, which leads to better design. And I really liked that too. CHUCK: Yeah, I liked it too. And really, the thing that appealed to me was just that it's another OO principle of encapsulation. And so, you effectively encapsulate both the logic and the handling stuff and the same thing, which is more or less what James said. But anyway, it was something that I really liked too because I can just see my code being cleaner without that being in it. JOSH: So I have a question for you, Avdi. In doing all your research and in writing the book, you even mentioned a couple of places in the book in deficiencies in exception handling in Ruby. And you talk about, “Oh, I wish I could do this better, but I can't.” It seems like there were a couple of things that could have been better about exceptions in Ruby, maybe you can just talk about your favorite one to hate. AVDI: That’s a good question. Despite the talk of tag models, I think it would have been a lot of sense to have nested exceptions to be built in. So just exception have an original pointer that points to the original exception if it was raised while another exception is being rescued. I think that would have made a lot of debugging cases a lot easier, because you'd be able to see where that exception originated. I really like what I've seen of the lisp exception handling system. Ad there's a gem called Cond, that makes an effort to basically implement a lisp condition system in Ruby. And I really wanna have the time to play with that some more, and see if it's something that can really be applied to production code because I like the idea of not necessarily having to always unravel the stack if you know that there is a case where can continue on being able to just tell it to continue on. JOSH: Interesting. So one of the things that I think a little at odds with Ruby and exceptions, is the principle of ‘Least Surprise’. And in some sense, an exception is always a surprise. You know, it's not like Java, where API methods or every methods has to declare what exceptions it might return or raise. So is there some way you think that you can minimize the level of surprise, since we don’t have that kind of signature. AVDI: I don’t know. Do you mean like from the point of view of the client, it's calling some code or from the point of view of the code that’s being called? Because I mean, you can do stuff on both sides of that. JOSH: Yeah, I think the thing that I usually trip over is not when I'm calling a method, that the API documentation tells me it will raise an exception sometimes. And in Rails, a lot of those methods have a bang, an exclamation point on the end of the method, which is nice, although often times ambiguous and confusing. AVDI: Yes. JOSH: But when I'm using a method that itself calls a method, that might raise an exception, that level of interaction makes it difficult to plan for what exceptions you wanna be handling. AVDI: To me, I think that’s in line with Ruby, just in the same sense that an object doesn’t always know what method it is going to be receiving, just like we don’t have declared exceptions, we also don’t have static typing to say what protocol every object will or won't have to implement. You know, something that I… a few things that I talk about a little bit is putting bulk heads in your code. I mean, at the edges of your code, where you start calling out to external services or third party code, it's always a good idea to have some kind of bulk place in place that just captures any exception, and logs it. And depending on the coding in question, maybe re-raises it or maybe just captures it, or maybe just enter a degraded operating state, where that sub system is shut down or something. And sometimes that’s the best that you can do. From the library author’s point of view, I'm a really big fan of no raise APIs. I really like the idea of libraries that give the client code the option of whether to raise an exception or not. And so I like doing things like basically putting a guard on the outer methods of an API, that make sure that no exceptions escape. JOSH: I think this book should be a required reading for everybody who likes gem. JAMES: Yes, absolutely. STEVEN: I made my whole office read it. Everyone who writes Ruby code. I mean, there's only like… I think there’s only two of us at this point, but I made many coworkers who wants to get their hands wet in our Ruby code base has to read Avdi’s code first. JAMES: You know, it's awesome because once upon a time, I changed the API a little in FasterCSV and then there was a big fight over it. And I fought hard and lost, basically. And it was interesting because when I was reading Avdi’s book and I finally got into his check list of the things you have to do before you raise an exception, I realized that I was indeed in the wrong. So it was interesting that I violated one of those rules about, “Are you prepared to do this, if you are going to raise an exception.” AVDI: I'm curious which rule that was. JAMES: “Are you prepared to end the program?” AVDI: Right. I almost used a metaphor for that, which I wasn’t sure if I was going to use because some people are a little uncomfortable with the subject, but in families, in a lot of like in families where they have guns in the home, they have sort of this small … that they teach their kids about guns. And one of the items they sort of hammer into their heads is, besides for the gun is always loaded and stuff like that, is never point the gun at something that you are not prepared to destroy. [Chuckles] And I kind of think of that, every time I think about that rule is, “Never point the exception at a program you are not prepared to destroy.” [Laughter] JAMES: So okay, Josh talked about earlier how he now knows the joy of sports fans, because he saw that play coming and you get right into it and he put the ball right in his hands. I got to say Avdi, you fumbled in one place. AVDI: All right, hit me. JAMES: In the threading code, you talked about how exceptions are raised in a thread and you talked about it doesn’t actually get raised; when it happens, it won't really get raised until you get the value of that thread, etcetera. And I was reading that the whole time, and I was just like Josh, I know exactly where he was going, he was going to show off one of the great methods Thread#abort_on_exception -- and you did not do it. I was disappointed. CHUCK: Ohhhh. AVDI: Actually, that is bad, because I actually failed to talk about a method with a word ‘exception’ in it. I should have [inaudible] through the code base and look for every reference to exception. You know, that was time. I kind of wanted to do... I kind of wanted to talk about exception handling and threads more, but I also kind of wanted to get it out the door. JAMES: So for those who don’t know, just real quick, Thread#abort_on_exception is a life saver when you are debugging, you can just do a thread.abort on exception = true, and from that point on, if an exception is raised in a thread, instead of you hearing about it much later when you go to get the value of the thread, it just raises the exception immediately, all the way up including to ending your program. AVDI: So it raises it in the main thread, right? JAMES: Yes, yes. AVDI: Okay. So correct me if I'm wrong, that means it's going to basically obey the same rules as like an interrupt, well, probably it is an interrupt exception. So that’s going to come out of.. that could come out of absolutely anywhere in your main thread, right? JAMES: That’s correct, yes. So yeah because the problem is, if something goes wrong in a thread, you find out about it much later when you are nowhere near the problem, you know? And that’s what ends up being bad. So if you are debugging and you just turn that thread abort on exception true, then generally you find out about it where it actually matters. When it really happened. AVDI: That is a great tip, and that is going to the next edition. CHUCK: Awesome. JOSH: James, you made it to the acknowledgement section. [Laughter] JAMES: That was my whole goal with this episode. JOSH: Avdi, I got a quick question about… sort of a meta level question about publishing the book. It seems like this was a very quickly executed project for you. And I think many of us are writers, and I did a book many years ago on something that nobody would ever care about now, but I wanna hear you talk about publication process, and the ups and downs and doing it in multiple formats and supporting iPads and all that crazy stuff -- if you wanna a minute or two. AVDI: Okay. The trick is compressing it into a minute or two. As far as the writing process, the technicalities of that, I do all of my writing for pretty much anything; whether it's a talk or a book in org mode in Emacs, which is kind of like an outline or on crack, although that’s selling it kind of short. And one of the particularly interesting features it has for technical authoring, is you can embed code into the text, and you can basically edit that code live in the Emacs mode for that code. So you know, I'm editing the inline code samples in Ruby mode, despite the fact that the whole file is this org mode thing. But more interestingly, you can execute the code. So most of the book where you see the output listed after a code sample, that is actually generated by org mode as it is being published. So I basically just put some options in about how I want the output to be treated, and it runs it through Ruby, and puts the results in line. And it can even do things like evaluate the results semantically, so there's an appendix where there's a table of system error types. And that’s actually generated by the code that proceeds that, and work mode takes it and turns it into a table. So that was a huge help, because I didn’t have to do a lot of shifting between a code base, and copy and pasting between a code base and the book; I could just edit all the code samples in line, until I got it right. And then the other nice thing about org mode is that it's got some very nice features for exporting to HTML and to PDF. So that’s all done in org mode. And then for like the mobi and epub, I just take the HTML output and and feed that into caliber, with a few customizations. Caliber is like a eBook publishing and reading tool. And that produces those. And I don’t know what else do you wanna know. JAMES: So then the Prags came to you and offered to help distribute it? AVDI: It was kind of a happy meeting. I met Dave Thomas for the first time at MagicRuby when I first gave the talk to a big audience. And so I talked to him a little bit, and he seem to like the talk. And then when I decided to go ahead with the book, I sent it to a bunch of people that act as kind of technical reviewers and as an afterthought, I sent him a copy. And he sent me copious notes back, for which I'm forever grateful, and also pitched the idea of a collaboration. CHUCK: That’s awesome. JAMES: Self-publishing for the win, right? AVDI: Yeah, I would definitely recommend it. I mean, there's definitely a place for the traditional publishing model, but I think there's also for things where they might not have as long of a lifespan, I mean there's plenty of stuff in this book that will be out of date in ten years, or in five years even. Stuff that you just wanna get it out there. I think the economics of self-publishing make a lot of sense. JAMES: I think I would like to see more books like this, where they are small, compact and just tackle that one aspect, you know? Instead of what we typically publish, where we try to cast so far and wide. AVDI: Well that’s the other thing about it. I mean, I think it opens up the field to that kind of thing. Because there's sort of an expectation that if you are going to do a print book, a proper book, it's going to be 200 pages long or something. And so either you have to come up with a topic is that big, or you have to put in filler until it's that big. JOSH: No, this is great. I was very pleased with the brevity of the book, because it was really focused and I felt like every page had value. CHUCK: Yup. Well I'm going to wrap this up and get into the picks. For the people who are new to this, the picks are really just anything that’s interesting, that we like that kind of makes life easier and more enjoyable. It can be code related, but it isn’t always. So we are going to go ahead and start out with our guest. Go ahead Steven, what was your pick? STEVEN: I'm actually going to have to say it's the IO Programming Language. I've been fiddling a lot with a bunch of different languages. A couple of them are on Rubinius, iOS 8 prototype-based programming language. And unlike java, it doesn’t hide it's prototypeness [inaudible] constructor function, so you really just clone objects and extend them, and clone them some more. And it just kind of, if you are not really familiar with prototypal inheritance style, it blows your head apart and gives you this whole new way of thinking about programming. And there are certain aspects of Ruby, like playing with the eigenclass, where i was trying to fiddle and like duplicate this prototypal style, but was unsuccessful in doing so. Although, I still have some tricks that I wanna try. CHUCK: All right, that sounds interesting. I think that there are few of us that kind of like trying new languages,. So you know, it's always interesting to hear about new stuff, and why it's different and why it's kind of cool. We'll go ahead and let Josh share his picks. JOSH: Okay, cool. Both of my picks are wikis this week. My first pick is the original wiki wiki website. And I don’t know how many people have visit it, but the WardCunningham, the inventor of the wiki wiki built this website. And it was the knowledge repository for a groups of programmers that was [inaudible] repository, and it started as a way to document design patterns. And the Ward built the thing as a really simple database in a Perl script. And there was no versioning; if somebody came in and defaced the wiki, they will just restore it from back up, from the night before. And so there's a lot of really great stuff to look at on this website. At a couple of levels, one is just the wealth of information about design patterns, object-oriented programming, etcetera. There’s also a lot of history that’s been recorded there about the development of projects, anecdotes about people whose names we've all heard about, Allan Kay, and Kent Beck and various others luminaries in programming. But then there’s also the evolution of how a community developed to maintain itself, document itself, interact. So there's always conventions of communication. So it's stuff worth checking out. And if you are clever, you can actually find a little bit residue of my time spent contributing there, way back in the 90s. So my second pick, and I have to apologize to everyone for wasting huge amounts of your time with your pick is. So this is tvtropes.org. This is a wiki that is basically an incredible analysis of everything that is pop culture, in terms of writing in fiction. So it started off I think as recording stuff about television and all the tropes that are used in telling stories there, and it’s expanded to cover everything from comic books, movies, to professional wrestling. And it's like reading Wikipedia; you start reading one page, and suddenly, there's 15 or 20 tabs that are open in your browser, that are waiting for you to read, as soon as you get done with the article you are reading. And it's a huge waste of time, but it's a really great way to waste your time. CHUCK: That sounds awesome. And I just have to plug that original wiki wiki, because there is so much good stuff on there. I can't even begin to tell you how much great knowledge is stored in that thing. So, go check them out. JOSH: That’s it for me. CHUCK: All right, James. JAMES: Okay, so I'm going to go through four things here, but they are all kind of related. I started trying to edit this podcast, since that was one of the complains I've heard over and over again, “Would you please edit it and cut out all the times when you say, ‘No, you go.’ ‘No, no, you go.’” So I started doing that and I found several things helpful in that. The first was I found a great little slideshow on the conversation network about how to edit a podcast, and they gave several good tips that I ended up using and stuff. So that’s a great thing. And then it lead me to some of the tools that I'm using. The first is Audio Hijack Pro, which is how I'm getting the recording out of off Skype, and it's very easy to work with. You just have few settings, and it puts whoever is recording on one channel, and everybody else on one channel. So it's not perfect for a panel like this, where we end up eventually four of us on one channel, but it's still pretty good. That’s what I use to record. And the biggest thing this podcast needs is leveling out; some of us come off much quieter than others. And the conversation network has a tool for that called the Levelator. And I use it to level out the podcast. You just feed it a recording and it goes through and evens everything out, so we sound pretty closely the same. That’s a big help. And then finally for the editor that I'm using to actually cut pieces of the sound and stuff like that, I'm using Amadeus Pro for the Mac. And I really like it. I got about 50 million recommendations on Twitter, ranging all kind of things try. I really didn’t wanna spend $500 on an audio editor. I love you guys, but not that much. And I wanted to try something a little bit lower key. I like things like Audacity, which is an open source version, but it's not very Mac-like has kind of an awkward interface. So Amadeus Pro, is kind of the middle of the road in my opinion. It's got a nice Mac interface, and lets me just select parts of the sound wave. And it gives me a keyboard shortcut that I can hit, and it will play a little bit before my selection, and a little bit after my selection without playing the selection. So it lets you know, if you cut this chunk out, this is what it is going to sound like. And that’s very easy when most of what I'm doing here is just cutting stuff out. And it has some smart editing where it tries to match them up, when you try to place something in. So I really them. Those are the tools I've been using to edit the podcast, if you wanna try something similar. CHUCK: Awesome. Thanks, James. Avdi, go ahead. AVDI: So I think what I will pick is an article that I started reading the other day. It's an OOPSLA paper from I think 2004. And my power just went out, and so I don’t have easy access to the exact title, it's basically an experience report on using mock objects. And it's talking about how to use them effectively, and how to not use them badly. And I think it addresses… I've been thinking a lot about mocking in tests lately, and that paper seems to address a lot of the concerns that people have, and a lot of anti-patterns that people see with mock objects. So definitely worth the read. CHUCK: All right, super. I'm going to go ahead and do a couple of picks. So, my first pick is Binkies; that’s how I made it through this episode. The second pick is Google maps. And not just Google maps in general, but Google maps on my phone. It really made a huge difference when I was trying to find my way around some of the towns and things that I was driving through. When I drove out to Boulder for Rocky Mountain Ruby, I wound up going through Woodland Park to visit a friend of mine, and just finding my way through Boulder was kind of a hassle. And having that and just being able to basically use it as GPS turn by turn directions was really, really handy. And so those are my picks this week. Hopefully, I´ll have something a little technical next week. JAMES: Was the Binkie for you, or for the baby? CHUCK: Well you know, I had to try and not cry on my own. But anyway, I think that's it. So we'll go ahead and wrap this up. I wanna thank out panelists again for coming on to the show. JOSH: Did we wanna say something about picking a book for next book club? JAMES: Good idea. CHUCK: Yeah. JAMES: You got a suggestion going? JOSH: Well, David is not here, so in his honor, I'm just going to suggest Smalltalk Best Practice Patterns. Are people cool with that? CHUCK: Okay. JAMES: Smalltalk Best Practice Patterns, sure. JOSH: Yeah, it's not a Ruby book, but I think it's a great book for Rubyists to read -- by Kent Beck. AVDI: In my experience, it is one of the most recommended software engineering books of all time. So, it's about time I read it. JOSH: [Chuckles] JAMES: [Chuckles] Me too, I have not read it. CHUCK: Sounds good. Well we'll try and get it in the first or second week of next month. We'll put details up on the blog, so that people can get it at rubyrogues.com. And also, next week we are going to be talking with Jim Weirich. He mentioned to me at Rocky Mountain Ruby that a lot of Rails that developers don’t actually program in object-oriented manner. [Chuckles] So I told him, “Okay, why don’t you come on and talk about it?” So that’s what we are going to talk about next week, so don’t miss it. And anyway, so our panelists are in no particular order, James Edward Gray. JAMES: Bye, everybody. Thanks. CHUCK: Steven Ragnarok. STEVEN: Yeah, thank you guys for having me. It was a lot of fun. JAMES: Thanks, Steven for joining us. STEVEN: Yeah, thank you guys for having me. Thanks Avdi for writing a book that makes sense out of one of the more… what I treat as one of the more hideous parts of programming exceptions have always irked me, basically because people use them in non-exceptional cases. And you talk about that a lot. CHUCK: I took it in the other direction where I just ignore them. You know, I just don’t even bother using them, you know? STEVEN: Also net HTTP and it just throws exceptions willy nilly. Doesn’t concern itself with anything. Oh my god, what a head ache. I had a bulk head in front of net HTTP, just caught everything. AVDI: That’s all you have to do. STEVEN: Anyway, thank you guys. CHUCK: Avdi Grimm. AVDI: Thanks a lot. CHUCK: Josh Susser. JOSH: So long, folks. CHUCK: I'm Charles Max Wood. If you wanna get the show notes, you can get them at RubyRogues.com you can always find us in iTunes. And I would really appreciate it if you leave us a review, and tell us how good James is doing on the editing. And that’s about all we've got, so we'll go ahead and wrap this up and we will catch you next week! Oh, there is one thing I was going to mention that I just realized. We are actually behind a couple of episodes, that’s my fault since I'm the one that gets them up and we have a baby and I was at Rocky Mountain Ruby. And just anyway, things kind of just fell through, so you might get two or three episodes at once. [Chuckles] Just as fair warning. So if that’s the case, and you feel like you are behind, I apologize, but we wanna get the content out to you. So anyway, that’s pretty much all we’ve got. We'll catch you next week. Thanks for listening. JAMES: Bye everybody!