JAMES:
Mandy, please schedule more episodes where I can throw hard programming questions at Avdi for one hour.[Chuckle]
[Hosting and bandwidth provided by the Blue Box Group. Check them out at BlueBox.net.]
[This podcast is sponsored by New Relic. To track and optimize your application performance, go to RubyRogues.com/NewRelic.]
[This episode is sponsored by Code Climate. Over 1,000 organizations trust Code Climate to help improve quality and security in their Ruby apps. Get 50% off your first three months for being a Rogues listener by starting a free trial this week. Go to RubyRogues.com/CodeClimate.]
[This episode is sponsored by SendGrid, the leader in transactional email and email deliverability. SendGrid helps eliminate the cost and complexity of owning and maintaining your own email infrastructure by handling ISP monitoring, DKIM, SPF, feedback loops, whitelabeling, link customization and more. If you’d rather focus on your business than on scaling your email infrastructure, then visit www.SendGrid.com.]
CHUCK:
Hey everybody and welcome to episode 128 of the Ruby Rogues podcast. This week on our panel, we have Avdi Grimm.
AVDI:
Hello. And since Josh has helped me achieve enlightenment, I will now be known as Baba Ram Dig Vim. [Laughter]
JAMES:
I’m not saying that throughout this entire episode.
CHUCK:
Josh Susser.
JOSH:
[Chuckles] Hi from San Francisco. And Avdi, it’s about time I was getting tired of calling you ‘Your Worship’.
AVDI:
[Laughs]
CHUCK:
David Brady.
DAVID:
My code has an inferior Ruby complex. Can we do something about that?
CHUCK:
Katrina Owen.
KATRINA:
Hello from Denver.
CHUCK:
James Edward Gray.
JAMES:
I got nothing. [Laughter]
CHUCK:
I’m Charles Max Wood from DevChat.TV. A quick reminder: go check out GoingRogueVideo.com for my video on how I went freelance. And we also have a special guest this week and that’s Avdi Grimm.
AVDI:
Baba Ram Dig Vim.
[Laughter]
DAVID:
Can I just call you Baba? There’s [inaudible] Mr. Vim.
JAMES:
I am for him correcting us for the entire episode. [Laughter]
JOSH:
I’m going to call him Baba Dig Vim. [Laughter]
AVDI:
Just to let everybody on the joke. Josh pointed out that Ram Dig Vim is an anagram of my name. And so apparently, according to my name, I have secret Vim tendencies. CHUCK: [Laughs]
JOSH:
What’s in a name?
JAMES:
Yeah. We always knew that. We knew before you knew, Avdi. Relax. [Laughter]
JOSH:
That’s always the case.
CHUCK:
Oh, no! This is going to be one of those episodes, isn’t it?
JOSH:
Yeah. So, what makes you think you could write a book?
I don’t know. [Laughs] It was a dumb idea.
JAMES:
I think this is only the second where we talked about [crosstalk].
AVDI:
Do you know how many words go into a book?
DAVID:
Lots, right?
JAMES:
Lots.
JOSH:
A couple.
AVDI:
It’s crazy.
CHUCK:
Way to quantify that, guys.
KATRINA:
[Inaudible] question is how many words got taken out of this book?
JAMES:
Yeah, good question.
AVDI:
Probably not enough.
JOSH:
So, Confident Ruby. Why did you write this book? What’s the point of this book, Avdi?
AVDI:
The point of this book is joy. It’s about coding joy. It’s about the joy that found in programming Ruby when I first came to the language, the way that things could be said really just straightforwardly in a way that was almost like pseudo-code. And it’s about rediscovering that joy even in the midst of not just toy problems, but really complex code; and doing that through patterns and idioms that emphasized code that tells a very coherent story rather than code that spends a lot of its time prominently dealing with edge cases. The history of this goes back pretty far. Back in the first year or two that I had an actual Ruby job, I was working with a codebase that was a bit of a mess. Actually, it was a huge mess. I think some of the first codebases I worked on are still some of the worst codebases I’ve worked on in Ruby. I started sort of taking some notes and writing some blog posts based on the anti-patterns that I was seeing in the code. I noticed a trend that a lot of the stuff that was just making it painful to work through this code was that the code was kind of unconfident, like it would constantly second guess itself. It was like, if this variable is set then if this variable is a hash and if this hash has key foo [laughs], and so on. Yeah, I started writing about this and then I talk about it and then eventually, I wrote a book about it. So, that’s the long answer. DAVID: So, what’s next after the book? [Crosstalk] [Laughter]
DAVID:
Okay. [Crosstalk]
CHUCK:
A screenplay.
DAVID:
Peter Jackson should be free in another year. [Laughter]
JAMES:
Yeah, right.
JOSH:
You need to have a trilogy before Jackson will do a movie.
DAVID:
Oh, Jackson will turn this into a trilogy. [Laughter]
JAMES:
[Inaudible] gets changed into one.
DAVID:
He’s going to spend the entire first movie just defining methods.
JAMES:
Avdi, going back to Confident Ruby because I actually read it kind of a long time ago and I was like, “Oh, I got to make sure this is in my head.” And this is something I noticed just kind of this weird thing. I’m really actually trying to learn JavaScript finally. I mean, like actually learn it, like how does it work and stuff, “JavaScript, what is it?” But as I'm doing that, I find myself doing a huge amount of defensive programming. I guess that’s the opposite of Confident Ruby, Defensive Ruby?
DAVID:
Paranoid Ruby.
JAMES:
Paranoid Ruby? Yeah. I was going to say [My Cocaine] Ruby.
AVDI:
Timid is a term that I sometimes use.
JAMES:
What did you say? Say it again please.
Timid is also a word I sometimes use.
DAVID:
Nice.
JOSH:
Sensitive Ruby.
AVDI:
There's not a problem with being sensitive. Being sensitive is okay.
JAMES:
I find myself doing more of that as I'm working with JavaScript. And I can't decide if it’s a JavaScript because I'm like scared to death of JavaScript ever automatically converting anything for me. So, I try to make sure I convert everything so that I never have to get to that. I can't decide if it’s that or if it’s because I'm so new that I don’t know what to trust there. And so, that’s what makes me do it or whatever that I find that I have that problem a lot more in JavaScript than I do in Ruby for some reason.
AVDI:
I think some languages that try to be more helpful wind up being less helpful. I was thinking about this the other day and it’s something I honestly feel like I should add a bit about this to the book is that Ruby in contrast to most of the other scripting languages and just other languages that came before it, really does very little automatic conversion, very, very little. For a long time, in a lot of languages, it was kind of considered standard. They would have all these different automatic conversions where I have a string but I use it as if in a context where I would normally expect the numbers so the language is going to do what I mean and convert that string into an integer. You see this in Perl, you see this in JavaScript. Actually, you see it C++ which is kind of weird. There are all these implicit coercions and things like that. It seems like a good idea. It seems like a super big convenience. But Ruby really went against the flow by saying, “No, if you want your string to become an integer, you’ve got to say .to_i,” if you’ve got to wrap the integer conversion function around it. And I think that was probably a choice that was driven by the messes that are often caused by all these implicit conversions.
JOSH:
And I think there was also a really good model for what Ruby adopted which was how Smalltalk did things.
AVDI:
Right.
JOSH:
Smalltalk had a very similar -- it’s like they had the string type coercions that we see in Ruby all over the place. But they also had the [inaudible] arithmetic conversion model that got adopted.
AVDI:
I think it’s very consistent with Ruby’s sort of hardcore object-oriented approach because I guess the underlying feeling in these other languages is the language knows a whole lot about all of its built-in types and it’s going to try to do convenient things for you based on its understanding of the built-in types. Whereas the Ruby point of view is everything is just an object that you send messages to and we’re never going to make assumptions about what those objects are or what you want them to become. You just need to send messages to them.
JOSH:
It’s dealing with things in terms of protocols.
AVDI:
Yeah.
JOSH:
The thing that I loved in your discussion of all this was that you really clearly made the distinction between the implicit and explicit type conversion methods. I thought that was the most succinct description of that I've seen. And I learned a lot reading that section.
AVDI:
I'm really glad to hear that because that was an explicit goal. It wasn’t the goal when I first started writing the book. I didn’t go into it thinking, “I'm going to write the definitive guide to conversions in Ruby.” But it started to really become a theme. And I think it’s because a lot of what goes into writing confident code is knowing what you have, being sure by the time you get into the meat of a method that the objects you have to work with, not necessarily that they're the right types, but they support the right protocols. They're the right shapes, so to speak. And so, one of the major ways of doing that is performing various conversions on them before you get into the meat of the method. And so, we have all these conversion methods like the to_i versus to_int and to_ary versus to_a. And so, I figured if we’re going to talk about conversions, we should really talk about it in-depth. I couldn’t find any book out there that had a really good complete coverage of all the different nuances of conversion in Ruby.
JAMES:
I actually have a theory about why that’s the [inaudible] section of this book. I agree with Josh, the section I really loved is the input in your book, dealing with inputs, the conversion methods but that’s also guard clauses and bouncers I think was this other one you kind of described. I thought that was the amazing section. I have a theory on you kind of divide things in the book from collecting input, performing work, handling failure, and delivering output, I think. So, handling failure was kind of covered by Exceptional Ruby and you actually say that at one point that you covered it a little but most of that’s there. Doing the work, you can't really help us with that much [inaudible].
And output, again, there may be some patterns there but it’s not as much.
AVDI:
Output is mostly about making it easier for the methods that consume your output to also be confident.
JAMES:
Right, exactly. But the input, it’s a big topic. Data is always coming into the methods and then you have to decide, “Okay, I got this but I need this. What are the good paths to get there?” So, I agree with Josh and that’s where this book really shines, I think.
JOSH:
If you look at Erlang or Elixir or Haskell, there's a bunch of these languages that use pattern matching to do what in Ruby we would think of as method lookup.
Right.
JOSH:
In Ruby, you send a message to an object that looks up the method and then runs the method. And some of these languages have these patterns where you can say, “Oh, instead of just picking a method based on the class of the receiving object, I'm going to pick it based on patterns of, did you pass me nil or did you pass me a string or did you pass me an integer or did you pass me two integers,” or what have you. That’s one way that you can remove conditionals from your code is by doing all these patterns. You're not actually taking conditionals out of the execution of the software at some level.
AVDI:
You're pushing them into the language.
JOSH:
Yeah. The language is special casing them for you in efficient ways that it can reason about. And I looked at a lot of the input processing stuff that you were looking at, the collecting input section which really dominates the book; it’s like two-thirds of the book. AVDI: Yeah. I think it’s the heart and soul of the book.
JOSH:
Yeah. And I look at that. And this book is sort of 300 pages about how to remove IF statements from your program. [Laughter]
AVDI:
I’d like to think of it as removing the extraneous IF statements.
JOSH:
Yeah. I mean, I think pretty much every pattern in here is, “Oh, you can get rid of an IF statement if you turn your code around to go like this.” And it seemed like that was somewhat reminiscent of what the pattern matching languages do where they take stuff where you have conditionals embedded in the body of your method or your function and pull that up to some place where it’s easier to deal with rather than in the [inaudible] of your method.
AVDI:
Right. The functional way of doing that is by pattern matching against types and against the shapes of structures. Then the OOA of doing that is to sort of turn things around and to push it into polymorphism. So, the long way of doing it is you decrease the number of IF statements by increasing the number of types you have. Not the only way, though.
JOSH:
Yeah. You demonstrated a few tricks on that. [Laughter]
JAMES:
So, you do this thing in the book, there's my new favorite thing. You do the introduction for the very first time which is you take this chunk of code, just this realistic chunk of code. I can't remember what you got; method Foo, I think actually. And you go through it with a highlighter and you highlight the lines that are about input and the lines that are about work and the lines that are about failure. In this particular example, it doesn’t have output. But I've seen you do that tooling like the accompanying video and stuff. But it’s so eye-opening because you're like, “Look, you're dealing with input [inaudible] like you should be.” Then you do half the method then you're dealing with input again. And just seeing those colors stacked on top of each other, really, just for some reason, that is just a super good aha moment for me about how these things are in the wrong ordering inner mix and stuff like that. I love that trick. AVDI: When I was doing the talk, that was what everyone remembered.
JOSH:
Yeah. Avdi, we’ve been talking about stuff in the book. And I know it’s a Book Club so we expect listeners to have read the book. But can you just say a little bit about this stuff so that if people haven't read the whole book, they can [crosstalk] better.
AVDI:
[Crosstalk] the writing stuff?
JOSH:
Just the breaking down of the method into input, work, output, failure.
AVDI:
Sure, yeah. The kind of the epiphany, such as it was, that resulted in the talk and the way the book is organized was I was looking at these functions or methods and codebases that felt really unconfident to me and I felt like I was having a really hard time waiting through is they're very hard to understand. And as a result of being hard to understand, they were hard to change. And I was trying to think, “What is the real issue here? How can I explain why my mind looks at this and just repels?” Eventually, I realized that just about any part of a method can be broken down into one of four parts. It’s accomplishing one of four roles, sometimes more than one at a time; the roles of collecting input, performing work, delivering results, and handling failure. Any given line is doing one of those. And where methods become confusing, at least for me, is when those are all mixed together. And so, I did this kind of visual aid in the talk where I would take a method that was really long and had all these things mixed together. And like James was saying, I would just mark it up in four different colors, showing which parts were collecting input, which parts were actually doing the work of the method, which parts were delivering results and which parts were dealing with failure and showing that it would just go back and forth. We’re collecting a little bit of input and then we’re doing a little bit of work on it and then, “Oh, there's this failure case that we have to account for.” So, there's going to be a three-line diversion where there's begin, rescue, or five-line begin, rescue, end, and showing how to deal with that failure. And then, we’re going to go back to doing some work. But then, there's the more input we need to collect that we didn’t bother to collect earlier. When I say collecting input, I sometimes mean going and finding input like organizing and pulling it out of the database or descending through a chain of methods. But I also sometimes mean getting input into the form that we need. So sometimes, that involves conversions as well. I feel like this mixture of parts of a method is what confuses things. A lot of what I'm going through in this book is sorting these out. So, a method starts out by collecting input, like there's a stanza where it’s collecting input. And by the end of that stanza, there's going to be no more code in the method that deals with collecting input. Everything you need is ready in a variable. And then, moves on to performing work and so on.
DAVID:
Do you think those parts still belong in the method or should they be extracted out, like is it a violation of the composed method pattern?
AVDI:
It really depends on the method. It depends on the context and how big those parts are. And certainly, if you have two different methods that have virtually the same stanza of collecting input, maybe they’re doing the same conversions or something on the input then that’s probably something that deserves to be extracted out. A lot of the stuff that I show here, especially when it comes to collecting input, is really intended to go at the border lands of your code. So, either code that’s kind of right at the top level of your application or code that’s in the API layer of your library where other folks…
DAVID:
Controller code.
AVDI:
Yeah, other folks are going to be calling into your library and these are the methods that are receiving the inputs from external code. A lot of this stuff is sort of guard the borders. One of the things I’m trying to do away with is repeating the same checks about data at every level. So, I really hate seeing codebases where they’re passing around these values and every single method from the top to the bottom is checking to see if it’s nil first before doing anything with it. No, just check once and deal with it there and be done.
DAVID:
Yeah.
JOSH:
Yes. I love the guard the borders metaphor that you used there. And that’s very often how I write my code. I think that’s good. I think that’s one of the things about object-oriented programming that’s really an effective trick, is that you create an object and in the initializer, you validate all of the inputs to the object state and then you can just rely on them from there on out. I’ll build classes where I do just that. It sets up the object and then you can make sure that all of the instance variables are set up right. And then you never need to check them again. And I pass state around in objects using instance variables pretty often because it’s so easy for me to do things that way. And I have these very small bottlenecks that control how things get written so that I can always be assured that the values will be in the same state.
AVDI:
Yeah.
JOSH:
And that seems so much easier to me than passing around a value through four or five levels of method and having to validate them all as they go. That’s just one of the things where the functional way of doing things I think is a little at odds with how you do things in an object world.
AVDI:
Yeah.
DAVID:
I think there’s also a paradigm shift here, at least popping for me, which is that I tend to look in the models directory of a Rails app and I tend to think of all of these objects as somebody could just grab one of these and instantiate it. That’s what my specs suite does. It just grabs it and instantiates it. So obviously, I need to guard my inputs. But if I’m guarding all my inputs up in the controller, then (a) the proper behavior for a nil violation down in the model should be to explode and throw a no method error on nil class; and (b) this is the epiphany for me, maybe I need to reconsider the fact that maybe not all of my objects should be always considered to be living on the border. Is there some way to say these classes are on the border and these classes are in the protected area where their inputs are already checked?
AVDI:
You know, it’s funny. I almost wish Ruby had Java’s package level of visibility. We have protected, which is pretty much useless, very close to useless. And I would gladly trade it for package, because all this protection is just advisory in Ruby but package would be an advisory level to say, if you try to instantiate one of these objects outside of the module that it’s defined in, Ruby would say, “Are you sure? Because I think that’s somebody’s private and internal class.”
JAMES:
I’m pretty sure we can write that in pure Ruby. We could use [caller] to get the location of where it was instantiated. [Chuckle]
AVDI:
And we could reduce our performance to a crawl.
JAMES:
Yeah.
JOSH:
Couldn’t we create a refinement to make that work?
AVDI:
Perhaps. [Chuckle]
JAMES:
Too soon, too soon.
JOSH:
Hey Avdi, speaking of language level support. I’m curious, you have this breakdown of input work result failure and Ruby has explicit support for the failure section of the method. And you talk about that as getting away from what the BRE.
AVDI:
Yeah, Begin, Rescue, End - BRE.
JOSH:
Yeah, getting away from the BRE and getting to the top level rescue clause on a method definition. So, Ruby has support for that in the language.
AVDI:
Yes.
JOSH:
I’m curious, are there other pieces of this breakdown that you think would be useful to have some more language support for?
AVDI:
There’s always the thought of, let’s add a little bit more to method declarations to enable us to be a little bit more declarative about what types of object we can accept. But it’s so easy there to just start going completely against the grain of Ruby because Ruby is not a manifestly-typed language. It is not the sort of language where we declare types everywhere. So, I’m not really sure how to do that in a way that would maintain the very dynamic nature.
JOSH:
Okay. So, maybe a different way of looking at this is how do you think the Ruby 2 keyword arguments would change how you talk about some of these patterns?
JAMES:
It does. It does change it. In the past, we used to say, “You need to put everything in hash and call fetch every time you needed that.”
AVDI:
Right.
JAMES:
And the keyword arguments are making that better. Now, I don’t think they got all the way there until Ruby 2.1, which is Ruby’s candidate now.
JOSH:
Yeah, required keyword arguments.
JAMES:
Right, because you couldn’t do one that was required but had no default. But now, you can in Ruby 2.1.
AVDI:
I’ll be honest. I don’t know if I’ve written a single serious program with keyword arguments. So, I feel like I need to dig into that some more. And it would be nice to release an update to the book that talked about keyword arguments a bit. I think the target version for this book was on 1.9.3. I might have talked a little bit about some 2.0 features.
JAMES:
Well, what I’ve found in converting some code to keyword arguments is that generally, the language level support is helping.
AVDI:
Good.
JAMES:
Because before, you had to declare the variable but took the hash and then you had, if you were pulling two or three things out of it, you had both two or three lines which Avdi calls collecting input where you’re, “Okay, fetch this, fetch this, fetch this. Here is the default.” And now, that just is part of the method signature, basically. But again, 2.1 is a necessary step getting to the point where you can make Ruby actually throw an exception if that thing is missing.
AVDI:
Yeah, and that’s really, really helpful. And just to be clear to listeners, when we say fetch, we’re specifically talking about the .fetch method on hashes, so using those in preference to the square bracket subscript operator.
JAMES:
So, you have another cool thing in this book. It’s not just a book. You gave us the Confident Ruby book and then you included a, I think it was about 30-minute video of you going into an actual codebase. It was Discourse. And going in and applying these techniques to Discourse. So literally, you would pause the video and then highlight the code in the various colors like I was talking about earlier. And then let’s see if we can clean this up. And then you would play around a little bit and do that. Also, you gave us a side book on a library built on the null object pattern. We can talk about that in a bit. But the video especially, one thing I noticed in there is that you have far better restraint than I do. [Chuckle]
JAMES:
So you go and you find a method and you’re like, “This is ripe for refactoring.” And then you do the one thing that makes 80% to 90% of the difference. And it looks dramatically better. But I would obsess over it. And I would have to do the other 20 things that make up the rest of the difference.
But you stopped there. And I’m wondering if I can do that.
AVDI:
[Chuckles] That was really to serve the goals of the video. The goals of the video were to specifically show refactorings derived from the book, refactorings that were about making the code more confident. Give me a chunk of code and I could probably refactor it infinitely long past the point of it making any difference. But for the video, I really just wanted to show stuff that was from the book, stuff that was about confidence. So, I did have to really restrain myself. I have to say that that was one nice thing about the video, is it did give me the opportunity to live demonstrate the marking up methods in terms of the different parts of a method. That process is actually painful coming up with one of those pictures for the book. I wanted to do more of them for the book but it was just this really tedious process. But the video process that I have makes it relatively easy.
CHUCK:
I was going to ask if there was a way to, I don’t know, mark these from a gem or something where it could actually give you that kind of readout or output where you could work through that.
AVDI:
I’ve been thinking about that for years. Not so much the code analysis part of it. I’m sure you could do the code analysis part of it although it strikes me as really, really painful trying to categorize code using analysis as input gathering, et cetera. I have thought about what it would take to do something that goes one better on the pygmentize tool where you could say, “Okay, from this line and column to this line and column, highlight code in pink,” and then output that in various image formats. It’s an interesting problem, but I think it’s not an easy one.
DAVID:
So James, for the refactoring problem, the trick is to realize that the first one just solves 80% and the next one solves 80% of the remaining 20.
[Laughter]
DAVID:
And the next one solves 80% of the remaining 4%. So, what I have learned is that I’ll do 80% and then I get up and I go wash my hands and then I do 80% and I go wash my hands. But I have a sign that says, “If you just got back from washing your hands, stop refactoring.” [Laughter]
JAMES:
Yeah, that’s it though, right? The one thing he does in the video, it’s like, “Ah yeah, that’s better.” Then I’m like, “Yeah, but we could do this thing.” But then if you compare the thing that I want to do with the thing he actually did, it’s like a 1% nothing changed. It’s so funny. But I really like the video. I thought it was great as far as just getting to see it in action kind of helps put the whole thing together. You had some really cool examples in there. The anonymous user, which is the, I can’t remember if it’s special case or null object, sorry.
AVDI:
Special case.
JAMES:
Special case, yeah.
JOSH:
Null object is a special case of special case.
JAMES:
Special case, right. [Laughter]
JAMES:
Nice. And then you get one with dynamic dispatch on an after save thing. There were these different after save handling three different things and you were so ruthlessly practical in that. You [inaudible] so good. You were like, “We could blow this up and do an entire tree of objects and select the right object and then call a method on it. But in this case, it just doesn’t buy you anything.” I thought that was really cool. You talked about the different options and how you could go too far with it. [Chuckle]
JAMES:
Let’s just do this simple thing that cleans up the code and pretty much handles this [inaudible].
AVDI:
I think that’s one of those things that’s the hardest to learn and it’s hard to teach. It’s one of those things that you just keep coding and you start to get a feel for when a solution is just right and when a solution is overkill. But it is one of the reasons that I like the video format so much. And obviously I like it because I do Ruby Tapas for a living. But I love the video format because I feel like for whatever reason, it really helps me just talk about when things are pragmatic versus when things are overkill. And I also really like doing recorded pair programming sessions like I did with Josh. And that’s up on YouTube. Because it just captures that thinking about, “This is too much,” or, “This is just right,” that you don’t see. When you’re just reading a pattern book, it’s easy to look at that and think, “Okay, should I just apply this everywhere?” When do I apply this versus when is it too much?
JOSH:
Avdi, I didn’t get to watch the video. I’m going to make sure I do that real soon now though, because it sounds cool. You didn’t talk in the book about how to apply these patterns in doing something like TDD. And I don’t know if you do that in the video or not. But do you want to take a moment to talk now about how does looking at things this way and the patterns in the book, how do you address all that using a TDD process?
AVDI:
Well, I feel like I wrote a lot of the patterns in the form of a refactoring. So a lot of them start with code A and then refactor it to use a pattern and end up with code B. So, in as much as they’re refactorings, they slot into the TDD process like any other refactoring. You write a test, you make the test pass, and then you refactor based on whether there’s duplication in the code or something else that’s making you feel funny about the code. So yeah, there’s that. Some of this stuff, when I’m writing the borders of my code, some of these checks I’ll throw in without actually TDD-ing the check. If an argument, dumb example, an argument should never ever, ever be nil. I may well throw in an assertion for that in the code without writing a test that says, “And this method should assert that this argument is never nil.” If it’s something that I need, I want my client coders to be immediately notified about, I’ll just put it in there. It’s not the kind of thing that I generally TDD.
JAMES:
You can go way too far down that rabbit hole, if you test every single guard clause or whatever. I know it’s supposed to all be tested and stuff, but then it can get to the point where you’re writing six tests per method you put in. it’s getting a little crazy.
DAVID:
And is it really valuable to document four of those tests? This is guaranteed to fail. Is it really valuable to document four of those six guard clauses that if you screw this up this way, it’s guaranteed to fail?
JAMES:
Right.
AVDI:
I do want to make it clear that I don’t, like I said before, I don’t litter my code with these redundant checks everywhere. It’s really a borders issue. And it’s a borders issue. It’s about making sure things, nils and things like that, don’t’ get too deep into the code and it’s about being kind to your callers and letting them know as soon as there’s an issue rather than letting them know the tertiary result. Somewhere deep in the code you get a no method error on nil and it turns out that that was actually the tertiary result of three nils back in a completely different part of the code.
JOSH:
Okay. Just to finish up the TDD stuff, the testing stuff, I’m curious if there are particular testing patterns you find yourself using more building software this way. Do you focus more on testing how objects get created and initialized? Do you mock things more or less?
AVDI:
That’s a good question. I’m not sure that this stuff puts particular pressure on the way I test. I have a way that I like to test and I hadn’t really thought about whether it was influenced one way or another by the style of coding. In general, more and more, I like to test based on the idea of roles. I want an object to play a particular role so I’m going to name that object after its role and I’m going to write a test. Often, I’ll write the test about what the object should do before the class exists or even the name for the class exists and I’ll be like, “Okay. Now, what would be a good thing to actually play this role?” But that’s standard, test first I guess.
JOSH:
I had one question about the code samples in the book. Sometimes, they felt long. [Laughter]
JOSH:
There’s some, it’s like I turn the page and, “Hey, this page is entirely a code sample.”
AVDI:
I tried to avoid that, but there are a few.
JOSH:
Yeah. I figured you were trying to avoid it. But there were ones where it was just like, “Okay, I’m putting a lot of stuff on this page.” And it took a little work to get through some of those.
AVDI:
I apologize for that. [Laughter]
JOSH:
Okay. Well, I’ll forgive you. But you’re so creative sometimes in the code samples that you provide and that’s definitely entertaining. But sometimes, when you get one of these big long samples, I have to deal with, “Why is it so long here? What’s going on here and why couldn’t this be broken down more?” And it wasn’t always obvious to me about that. So, it’s just something worth mentioning, because it kept coming up for me a lot.
AVDI:
Okay. That’s good feedback. And it’s good to know because I generally dislike the books with the really long code examples. So, I try to avoid it.
JAMES:
I thought that was a cool thing with the video, is that it gave you a chance to tackle real code.
AVDI:
Yeah.
JAMES:
So, it bridges the gap. With books we always use the dumbest example that you’ll never ever see in the real world.
JOSH:
Yeah.
AVDI:
Yeah. That’s the perpetual conundrum of writing about this stuff, is that if you want to just show a technique, you want to highlight a technique, you can’t surround it with a ton of extraneous code or the technique will get lost in the code. So, you strip it down and you strip it down and you strip it down until you’ve got something that will just highlight the technique. And you go through it and then somebody looks at it and says, “Well, that’s stupid. I would never write that much code just to refactor that tiny piece of code.” [Laughter]
DAVID:
Refactoring trivial code is always subject to the argument of, “I wouldn’t refactor this code. It’s trivial.” And that’s a tautology. [Laughter]
DAVID:
Bruce Lee said, “When a finger points at the moon, the idiot looks at the finger.” [Chuckle]
CHUCK:
I’ve never heard that before. [Laughter]
JOSH:
That’s great. And I got completely distracted by that because of elephants.
DAVID:
Sorry. [Laughter]
JOSH:
The thing I want to say about the long code samples though was it’s actually great to have all the context. I actually thought about it when I was looking at it saying, “Okay, this is a really big long chunk of code but it’s really nice not to have things that are obviously contrived examples.”
AVDI:
Yeah.
JOSH:
That don’t have enough context to actually appreciate what you’re doing and why you would do it.
CHUCK:
Well, that’s one thing that harks back to the whole thing about your code telling a story, is that you have to know where it fits. Because if you don’t have enough information, then the refactoring that seems obvious to the constrained piece of code may not be the right answer because that may not be its role in the story that’s being told.
AVDI:
Yeah. Some of this I think could be addressed by just better publishing techniques. Eventually I would like to have in my tool chain the ability to do a long code sample which is then marked up in such a way that you can see where the changes are easily. The change is highlighted and maybe have some numbered call outs or side-by-side explanation or something along those lines. I just haven’t got my publishing tool chain to that point.
DAVID:
Avdi, you keep saying that code should tell a story. Are there types of stories? Are there canonical stories that code should tell?
AVDI:
Once upon a time…
DAVID:
Yeah. [Laughter]
DAVID:
15 unsuspecting teenage objects camp at Lake Crystal…
JAMES:
He’s speaking of code versus environment.
AVDI:
What’s that?
JAMES:
Code versus environment, the story archetypes.
AVDI:
Right.
JAMES:
Man versus environment and man versus man, et cetera, which should be human versus human of course.
AVDI:
Yeah, it’s an interesting point. One of the things, one of the ideas that I left on the cutting room floor for this is something I’ve been thinking about for a while. It’s the idea that there are archetypal shapes for methods. And you can zoom out and actually see the shape. There’s the, I guess you could call it The Flying V shape where you have a number of nested contexts, like open an input file, do. And then inside the do, end, open an output file, do. And then inside there iterate over a list of things, do. So you’ve got this steadily indenting piece of code that if you look at it squinty-eyed, it looks a little bit like a flying V of geese. And I do feel like there are these sorts of archetypal method shapes. And I would love to catalog them sometime. Because one of the things I feel like is that if you can see the shape, if you can see one of these archetypal shapes, first of all you instantly get an idea of at least a vague idea of what’s going on here. Dave Thomas I know used to talk about the way he would first come to understand a brand new codebase is he would just dump it all into a Word document and then use Word features to just zoom the thing out until he was looking at it spread across, looking at the entire codebase or at least a whole long file or something zoomed out, just looking at the whole thing on one screen. And of course he couldn’t read any of it. It was barely little dots at that point. But he could see the general shape of it. And then he could zoom in on parts of it and the shape would actually tell him some things. And I do feel like if you can see one of these obvious archetypal shapes in a method, that’s usually a good sign. And if you can’t, if it’s just static, like white noise when it’s zoomed out, then that’s a bad sign. That’s a sign that there’s mixture of concerns. There’s mixture of the parts.
JAMES:
I find myself noticing in this book how much you were dealing with the shape. A lot of times it was just, we can move this out here and look, now half the method is not indented anymore.
AVDI:
Right, yeah. I’m a big fan of maintaining a cadence in code and paying attention to the cadence of code. Because I think when we have that, it highlights the things that are similar or it makes the things that are similar look similar. And it also highlights the things that are different and should stand apart.
JAMES:
So, what you’re saying is Code Climate needs to incorporate gem sing? [Laughter]
JAMES:
Do you remember that extension? You can install this gem plugin and then you can type gem sing and the name of the gem and it literally went through. And I think it was based on when it would run into M’s or maybe it was classes and def’s or whatever. But it basically made this song off of the cadence of your code, in a way. So it was interesting.
AVDI:
Yeah, that is cool. I never actually tried that, but that’s definitely the idea here, is paying attention to the cadence, paying attention to the sameness versus the differences.
CHUCK:
So, of all the things you talked about in the book, Avdi, what do you think is the most important?
AVDI:
What’s the most important?
DAVID:
Do you say kerning? [Laughter]
CHUCK:
If you say kerning, you missed the point of the question. [Laughter]
AVDI:
For me, the most important point is really the philosophy that underlies it. It’s the philosophy of not accepting the idea that because the real world is complicated, our code has to be a mess. I see this idea proposed regularly, the idea that once the real world starts getting into your code, once your code makes contact with the real world, you have to start adding all these special cases and you have to start doing these big tangents in the middle of your code to handle a possible error condition so that kind of code is unavoidable. And I really don’t feel like that’s the case, especially in Ruby. I feel like Ruby gives us not just the ability to build abstractions around stuff but to easily built abstractions about stuff, to quickly build abstractions around stuff. When the context has to be built up and then torn down, we can easily encapsulate that into a method that takes a block and then the method can worry about the context and whatever we put in the block can be the work that gets done within that context. We have these really good tools in Ruby. So, the underlying theme here is that joy that you feel when you first write a piece of simple code in Ruby, the first example that I use in the whole book is I was first learning Ruby and I encountered an example like3.times do puts “Hello world!” end,and that was the best way of saying “Hello world!” three times that I’ve ever seen. It said exactly what it was supposed to do. There was nofor (i = 0; i < 3; i++) There was none of that. It was just very succinct. And it also had this thing where even the number was an object so there was that consistency there where everything was an object. And I loved that. And I guess a lot of what I’m trying to say is don’t accept the idea that you have to get away from elegance, that you have to lose that kind of expressiveness. Instead, leverage the language. Use the tools of the language to make sure that as the complexity of your programs increases, as the complexity of the situations you have to handle increases, your abstractions and your idioms increase [fractally] so that any given part of that big complex system still looks just as beautiful as that 3.times loop.
DAVID:
This might be the same question, but was there any part of the book as you were writing that you were surprised and delighted by? That unexpectedly, as you were writing, you went, “Holy crap! This is a discovery that I made as I wrote this.”
AVDI:
So, we talked a little bit about how I spend a lot of time documenting Ruby’s conversions. And there’s a lot to be said about conversions in Ruby. There’s more to it than just, so there are the methods that are to_i and to_a and to_s, to_str and all those different methods. So those are the implicit and explicit conversion methods, or conversion protocols is another way of thinking of it. There are also things like the capital letter methods like the capital letter integer conversion function or capital string conversion function, stuff like that. But one thing that I discovered or that I learned more about is this patter than Ruby uses internally, particularly it uses it with implicit conversion methods. Implicit conversion method is usually one of the methods in Ruby that is to_ and then three letters, so to_str or to_ary. But you’ll also see some longer ones like to_path, to_path is an interesting example. to_path is used when Ruby internally, when there’s a Ruby method that needs a path, like it needs a path to a file, you’ll give that method a string and Ruby will try to call to_path on that string in order to convert it to a path. But a path is also a string. It’s just a string with the semantic assumption that this is a string representing a path. And the thing is, string itself, I don’t think, if I recall correctly, string does not support to_path. But what Ruby does is it says if this object will respond to to_path, then call to_path and use the result. But if it doesn’t respond to to_path, use it as is. And what this means is you have an extension point. so there’s this other class in the Ruby standard library called Pathname which is not a string but it’s an object specifically intended for representing paths and it has a whole bunch of extra tools on it that you can use to check to see if the file exists or if it’s a directory or write directly to it and all kinds of neat stuff like that. And it is not a string. But it supports the to_path method. So any of the methods in Ruby standard library that expect a path string, they will see that they will implicitly convert that to a path string by saying, “Do you support to_path?” And it’ll say, “Yes, I do support to_path.” And it’ll say, “Okay, give me to_path,” and it’ll use the result of to_path which is just the internal string that the Pathname object uses. And you can use that yourself. So, if you had your own, let’s say you had a ConfigFile class which represented the path to a config file on your system and then had some extra tools that hash to it, you could support to_path on that. And you could then pass one of those ConfigFile instances directly to an open call or any other method in Ruby that expects a path string and it would just work because it would see that you support to_path, it would call to_path, and it would get whatever string you return from that and it would work. So you’ve got this extension point where you can make your objects compatible with Ruby’s expectations for a path string even though that’s not what they are, and even though Ruby itself doesn’t know anything about your ConfigFile class. And this is a really neat pattern because you not only can you provide these conversions yourself, you can also mimic that pattern. You can have your own classes that will say, “Okay, if this object supports, I have an example of to_coords where you’re expecting a two-element array which represents x and y coordinates. If this class supports to_coords, then call to_coords and use the result. Otherwise, use the object as is or maybe otherwise use the object converted to an array.” Now you have this extension point where somebody else has a TreasurePosition class and it’s an object of class TreasurePosition. They can also implement to_coords on there and now their object is compatible with your code’s expectations. It’s a neat kind of pattern. One of the objections that I can see to it is that it violates the way we usually think about duck typing, because duck typing is all about just sending a message and not saying, “Hey, do you support these messages? Are you the right type? Do you support these messages?” But what I realized about it is that it’s subtly different from that kind of duck type violation. Because it’s not saying, “Are you a duck?” before telling it to quack. It’s saying, “Can you give me a duck?” and that’s all it’s saying. It’s very constrained. It’s not saying, “Do you support this method and this method and this method because I need all of those methods for you to work?” And it’s also not saying, “Are you this class?” or, “Do you include this module?” or anything like that. It’s saying, “Can you give me a duck?” If you can’t give me a duck, I’m just going to assume you are a duck and treat you that way. But if you specifically know how to give me a duck, then give me a duck. And now as I keep saying, now you have this extension point where other people can plug in their own things and have them just convert implicitly. So that was something that I became more familiar with and I think I got more comfortable with the power of that pattern as I wrote this.
DAVID:
I did a lot of stuff like that in Java, that same type of pattern, where I expected an inbound object to implement some interface that I had defined. You’re going to be coupled to this. And it’s not quite the same thing because you’re basically saying you’re expecting this inbound object to quack, but it’s not to quack, you’re expecting it to convert.
AVDI:
Right.
DAVID:
So, I like that. What would that be called? Egg typing? [Laughter]
DAVID:
Give me a duck.
AVDI:
Yeah, that’s a good name for it.
JAMES:
I hope that name catches on. [Laughter]
JOSH:
This is great. Do we have time for another quick topic?
CHUCK:
Yeah, go ahead.
JAMES:
Sure. I’ve got one more, too.
DAVID:
I have no picks today. So, sure.
JOSH:
Okay. So, I think one of the more interesting patterns in the book is using callbacks instead of returning status. I don’t know if I got the name right there. But what is it, callback instead of returning, number 4.2.
AVDI:
Right. And I guess lots of fancier versions of that.
JOSH:
Right, yeah. So, I love this pattern. Basically, it says if you send a message and it returns a status result, true or false or something, and then you do something with that result, saying, “No, no, don’t do it that way.” Pass a block along with whatever arguments you send to the method and then have it do the conditional within that method to figure out what to do, like whether it should run the block you passed in. And this is something that object-oriented programming has done ever since Smalltalk where you invent your own control structures. Functional programming has their own take on that, too. But it’s ways to compose behavior that is a really nice way of doing things. The thing that I don’t think is clear-looking, the level of granularity in the book I think is great for describing the technique but the impact on what that does on a codebase I think is really interesting. Can you talk about what happens to your codebase when you start pushing the conditionals down into the control structures in your block structured methods?
AVDI:
That’s a good question. What happens to the codebase? This is definitely a way of really embracing ‘Tell, don’t ask’ in your code. The example that I use in the section you’re talking about is where we’re importing purchase data from an old system into a new system. And you want to do something. There’s an action that you want to attach to that basically. If importing a purchase succeeds, then you want to send an invitation email with some new information out to the purchaser. So, there’s the version where you just have the import purchase method return a true or a false and then you can say if import purchase then send the book invitation. The alternative to this is yielding to a block when and only when that process succeeds. This has some interesting benefits. It eliminates an if statement. But what’s interesting about it is that it suddenly makes the code much easier to change to support batch operations.
JOSH:
Right, or async, which you don’t ever get into but you mention
AVDI:
Yeah, I never get into that. But this idea, if it’s just import purchase and it returns true or false, first of all true or false doesn’t say much. I have to go read the documentation to figure out that the true means that the import succeeded or that’s the indication the import succeeded. But if it’s an if import purchase then send book invitation, well if I want to only send the book invitations to the ones that succeeded and I’m converting it into a batch operation, well then what do I do? Do I return an array of trues and falses? Or how do I handle the fact that it’s now a batch? Whereas I can turn this method into import purchase instead of import purchase and if it’s taking a block that is called when the purchase import succeeds, well now we just call that block multiple times instead of calling it once per method call. That’s the only change. So, it certainly changes your style in that the arity or operations, whether an operation is a one or a many, becomes less important, or at least it becomes less glaringly obvious in the code. It becomes easier to change things so that it’s, “Do this when this happens.” It’s not, “If this special value comes out, then switch and do this,” it’s just, “Do this when this event occurs.” And that makes it easier to switch to batches and it also makes it easier to switch to fancier asynchronous stuff.
JOSH:
Okay. So, callbacks these days, everyone thinks of Node.js. And people look at Node code and say, “Ooh, callback soup.” So, how do you avoid having this technique devolve into callback soup? [Laughter]
JAMES:
That’s a good question.
AVDI:
That is a really good question. It’s not an issue that I’ve run into yet. And I guess I don’t know if it’s that I’m not using this stuff enough yet. I don’t know. That’s a good question.
DAVID:
Maybe that’s the answer. Do it, but not so much. [Laughter]
AVDI:
As yet, I haven’t done a ton of asynchronous programming using these patterns. I think there are definitely better patterns out there when it comes to asynchronous programming. As a general hand-wavy answer, I find things that do events in a pipeline interesting and sometimes easier to reason about. But that’s not something that I’m prepared to explain in code quite yet.
JOSH:
Yeah. So, the callback pattern I think is great. It’s a very generically structured pattern and you’re using blocks as a shorthand for things. I guess Java doesn’t really have closures exactly yet but they’re getting close. But in the early days of Java, people would build callbacks using inner classes and basically specially constructed classes that had a very narrow protocol that would be used for doing the callbacks. And the pattern of callbacks you’re doing is, “Okay, we’re just going to use blocks.” And that’s great, because we just have essentially one method that we’re implementing so we don’t need to create a new class and then tell the thing which message it should be sending. But is that something that you think about when you’re doing callbacks? I know you had one example where you had blocks within blocks. When you get to that point, do you start thinking about, do I need to actually build some kind of specialized class to handle the callbacks?
AVDI:
That’s a good question. You mean like having a class that maybe has various methods on this, on that, on the other?
JOSH:
Yeah.
AVDI:
I do think about that sometimes. I’ve used that in some of my designs. I don’t know. I think ideally, it would be neat to have some conventions where you could do one or the other. It’s something I think about, building a library around at some point where you can easily convert a method into a form that would take either various callbacks for various situations as lambdas or as blocks or it would accept a specialized object which supported various on_foo callback methods.
JOSH:
Yeah, an example of that would be validations in ActiveRecord in Rails where there are all sorts of ways to validate properties. You can just give it a symbol for a method to run, to do the validation. You can give it a block or a lambda right there. Or you can define a whole validator class and then use that to do the validation.
AVDI:
Yeah. I guess the big question is whether the collection, each collection of callbacks for a given call, are one-offs or not. If you find yourself wanting to handle, you always want to handle success by doing thing A, you always want to handle failure by doing thing B and you always want to handle timeout by doing thing C, then it starts to make sense to support some kind of callback object. Because then you can just instantiate one of your standard callback objects and throw it in there and not have to rewrite the blocks every time. So yeah, I guess that’s the turning point, is when you find yourself repeating a set of callback handlers more than once.
JOSH:
Yeah. I think that the point where it’s seriously obvious you have to do something along those lines is when you start having conditionals within your callbacks. And you can think, oh well I could use some polymorphism and suddenly I have a lot of different classes of callbacks.
AVDI:
Well, that’s another point, is that I’m definitely not a fan of having a lot of code within callbacks. I’ve got a later example in one of these later patterns where I say import purchase, date, title, user email, do, and then the block receives a result object. And the result object supports these different methods like on_success do and on_redundant do and on_error do, which I think is a really cool pattern. It’s decoupling the action from the representation of its result. But within each of those, on_success do, on_redundant do, those each are one-liners. I’ve got another method. If it needs to do more than just log a little bit of information, I’ve got another method that actually handles what you do in there. And what I definitely don’t like to see is a whole lot of code inside one of those callbacks. I like to see you delegate off to a method somewhere.
JOSH:
Okay. Effectively, it turns into something like routing.
AVDI:
Yeah, exactly.
JOSH:
It’s just connecting the events to the thing that handles it.
JAMES:
That’s a good point.
JOSH:
Okay. So, that’s enough on that topic for me.
JAMES:
Alright, one last aside. The third thing you throw in is a whole other book.
[Laughter]
JAMES:
Whole other book. It’s called ‘Much Ado About Naught’. Do you want to tell us what that is?
AVDI:
Yeah, that was a thing that just happened. One of the topics that I talk about a lot in ‘Confident Ruby’ is the null object pattern and I’m a big fan of null object pattern. I’ve been thinking about it for many years. As I’ve thought about it, I thought it would be really neat to just build a library that captured all the different variations that you can do on the null object pattern and let people play with it really easily. And so, I thought I’ll go head and since I’m writing this book that involves null objects, I’m going to go ahead and write that library. Then I thought since I’m going to write a library, I’m going to use Emacs and org mode to write it in literate programming style just for the heck of it. And what that means is that I basically wrote what I was going to do. So I wrote a little bit about what feature I wanted. And then I would inline write the test and then I would, what’s called tangling the code. In literate programming, you write prose and you write blocks of code and then you use your tool to tangle the code which means it puts the code into files and in the appropriate order to actually be run as opposed to be presented in book form. And the test would fail and then I’d write a little bit more in the book about how to implement that, including the code block that actually implemented it. And I would tangle the code and then the test would succeed, and so on. Basically, I wrote the library by writing a book. And the original source code since has diverged. But the original source code of the library was the book itself. And I would just hit the tangle command and it would all be taken out and put in the right order into files. Yeah, that was a neat experience doing it that way.
DAVID:
I want a screencast of you doing that. [Chuckle]
DAVID:
I want to watch. ‘Much Ado About Naught’ sounds cool but I want to read the making of ‘Much Ado About Naught’.
AVDI:
And then I got my mom to do these delightful illustrations in, I think it’s called Paint Shop on the Mac, one of these really simple paint programs. [Chuckle]
JAMES:
Yeah, it’s got tons of great pictures in it. The book is cool. It’s got a lot of humor in it, especially in the intro. It’s really funny. And then it’s this sneaky thing. I’d find myself reading it and I’m like, “Hey, what is this book about?” [Chuckle]
JAMES:
Is it about how to develop a library? Is it about the null object pattern? Is it about metaprogramming? And I think the answers are yes, yes, and yes.
AVDI:
Yeah, pretty much all yes. I think first and foremost it’s a book about meta-programming. It and the library were an excuse to use almost every trick in my meta-programming book and talk about each one in turn.
JAMES:
It’s cool. There are some neat moments where you refactor to command classes and stuff. It’s really neat. I enjoyed. It’s an add-on but it’s definitely its own thing and was really cool.
AVDI:
I’m glad you enjoyed it. I definitely had a lot of fun with that one. That one was just pure fun.
CHUCK:
Nothing like good, clean fun, huh?
AVDI:
Hmmm.
CHUCK:
Alright. Well, should we wrap up and do the picks? This is going to be another one of those long episodes that people complain about. [Laughter]
JOSH:
Okay, let’s wrap it up.
CHUCK:
Alright. Well, James, what are your picks?
JAMES:
Okay. I’m on a video kick recently. I have no idea why. But I’ve just been watching lots of cool videos on the net. So, a couple of those are related to programming. First, Changelog has this list of Rich Hickey’s greatest hits. It’s cool. Rich Hickey is the creator of Clojure so he takes a functional view of everything, which I find is good because it challenges my ideas about things and I like that. There are lots of great videos in here. I actually watched all of them. The language of the system, just to hear him talk about what he thinks a system is and how our idea of an application breaks down when we get to that point and stuff I found particularly enlightening. But a lot of them are really good. So, if you want to see something different, that’s my recommendation. Another video I was watching recently about programming was from Baruco and it’s called ‘Micro Service Architecture’. It was by Fred George. And this video is really cool. He’s talking about what he’s learned in building SOA systems through the years. And it’s some unusual stuff, breaking systems down to very small line counts like 100 to 500 lines, maybe, with 500 being really big. There are some radical concepts in here like throw away the unit tests for these services and instead track business metrics, just stuff like that. It was a bunch of interesting curveballs and then way I do my talk listening is I’ll put in on in the background when I’m doing something not too big and I’ll see if it hooks me. And this talk got in my head and I ended up having to go back and actually watch it, watch it the whole way through and see what it was about and stuff. There are some stuff in here that I think would be difficult to apply in every case but a lot of neat ideas in here, I think. So that’s another expand your brain kind of thing. And then finally for a less programming, more unusual pick. After doing the talk at GoGaRuCo, one of the cool things is that people talk to me about and send me interesting videos about relating to being disabled and programming or stuff like that. This particular video is somebody programming by voice command, which I thought is really interesting. I’ve seen videos about how terrible it is in the past and I’ve tried it myself and I always thought, “Yeah, if I was ever going to make this work, I’d almost have to invent a language to program in,” which is pretty much what this person did, is invent their own custom language of stuff so that they could move cursors around or select certain bits of text and stuff. Even if you’re not disabled, I bet you’ll find this pretty interesting. It’s just a different way of thinking about the things that we do. It’s cool stuff. So, there are some neat videos that I’ve seen recently. Those are my picks.
CHUCK:
Awesome. Josh, what are your picks?
JOSH:
Well, I’ve mostly been on vacation for the last week or so. So, I don’t really have any programming picks. But I have one fun, amusing pick and that’s this cool YouTube video of an animated optical illusion. So, it’s pretty damn trippy. [Laughter]
JOSH:
It’s just fun to watch. So, that’s all I got. I’ll have something useful next week.
CHUCK:
Alright. Dave, what are your picks?
DAVID:
As promised, nothing to report.
CHUCK:
Katrina, what are your picks?
KATRINA:
Today, I have an alarm clock. It’s on the iPhone. I don’t think there’s an Android app for it. It’s called i-Qi. I don’t know how to pronounce it. It’s i-Qi. And it basically starts 15 minutes before you set your alarm to go off. And it starts with one Zen meditation bowl ding and then it waits several minutes, does one more. And it uses the golden ratio to slowly increase the frequency of the dings that arrive. And then by the time you have to wake up, it’s [inaudible]. And it’s really, really nice. It’s a very gentle awakening.
AVDI:
If half an hour after it’s time to wake up, does it progress to banging on trash cans?
KATRINA:
I haven’t tried that yet. [Laughter]
JAMES:
That would be awesome.
JOSH:
Are those time periods adjustable?
KATRINA:
I believe so. I haven’t tried.
JOSH:
Because that’s often what we do when meditating, is you’ll do that for coming out of meditations. You’ll have an intro tone and then you’ll work up to, okay it’s time to…
AVDI:
I actually have an explicit app for that.
KATRINA:
So, I think technically this is a meditation timer except I don’t meditate, so there you go. [Laughter]
JOSH:
Oh, cool. Well, I can use it then. Great.
CHUCK:
Alright. Avdi, what are your picks?
AVDI:
So, let’s see. Things that made my life easier recently. I’ll pick Google Now. So, I’m on the Android ecosystem, I guess. And I’ve been noticing that Google Now has been getting really cool lately. It’s the thing that you see when you go into Google Search on your Android phone, if you’re not familiar with the Android ecosystem. Basically, they’ve started doing this thing where they throw various cards in there that are context-sensitive depending on what’s going on and where you are. If it notices that I’ve received an email about a package that’s on the way, it will throw a card in there that tracks the package. When I’ve been traveling and I noticed, the first two things that I wanted to go look up were what time it is back home and what is the conversion rate between dollars and euros. And I went into search and noticed that it already had cards there for what time it is back home and what is the conversion rate. The cards can be interactive, so there was a little card where I could punch in a number and it would show the conversion. And then just the other day, it notified me that one of my favorite bands has a new album out. So if you’re cool with Google knowing every single thing about you, [Chuckles] they actually do some pretty neat stuff with the information. So yeah, Google Now is neat.
CHUCK:
Very nice. I don’t have any picks today. It’s been a crazy week. So I’m just going to beg off. We do have another book club book selected. James, you want to announce that for us?
JAMES:
Yes. We have the vote on Parley and the title that came out, the winner is ‘Functional Programming for the Object-Oriented Programmer’ by Brian Marick. So I’ll put a link to that in the show notes. I don’t know yet when the episode will be. I’ll get in touch with Brian Marick and see if we can talk him into coming on the show and talking with us about it. But pick that up and start reading and I
will try and get us discount codes and stuff, too. So more information to come. But that’s the book, ‘Functional Programming for the Object-Oriented Programmer’.
CHUCK:
Awesome. Alright. Well, we’ll wrap up the show then. We’ll catch everybody next week.