RR Code Reading
- Published on:
AVDI: Now, we are just going to do a dramatic reading of this, right?
JOSH: That’s one way.
AVDI: I will take the part of assignment lines.
JAMES: [Chuckles] That’s awesome.
JAMES: Hey everybody, and welcome to the Ruby Rogues podcast. I'm James Edward Gray II. I´ll be your host today. You have no idea how hard we’ve struggled to bring you this episode.
JOSH: And hopefully, you never will.
JAMES: That’s right. Chuck was struck down the ill, which is why I'm hosting the show today. Sorry, Chuck. Get better soon. David Brady is in Los Angeles, and couldn’t join us. We had many audio/video difficulties today, that we think we have solved at this point. There was also some computer equipment damage during the setup for this, so this is the heroic episode. Joining me today is Josh Susser.
JOSH: Hey everybody. My computer is not broken, yay!
JAMES: But his headphones may be. Avdi Grimm is also with me.
AVDI: Hello again.
JAMES: And today, we thought we would talk about code reading. It's just three of us, so it's kind of a small, intimate crowd today. We thought we would talk about code reading, which is one of the suggestions that we got on our site. People wanted to know how we go about code reading. So we thought we would talk about it in general, and then do the stupidest thing we could possibly think of, and try to read code live on the show. So that’s what you have to look forward to today. This could be a scary episode. So code reading in general; what thoughts do we have on that?
JOSH: People should read code.
AVDI: I'm in favor.
JAMES: [Chuckles] All in favor?
JOSH: [Chuckles] So, Donald Knuth -- one of the god of computer science -- talked about when he was getting on his literate coding direction, he was talking about how practitioners in other areas often look at the product of other people’s work in a pleasurable way. If you are a painter, you can look at other people’s paintings; if you are an architect, you can look at buildings and appreciate them for their aesthetic value.
But he didn’t think that a lot of programmers read other people’s code, just to appreciate the aesthetics of it. I guess that was his point. And so he came up with this whole literate programming thing to try and make programs easier for people to read, and have a pleasurable experience from it. So that’s not what I'm talking about. [Chuckles]
I think reading code is an important educational thing. We’re programmers, we program a lot, and the way that you get better at programming I think is mainly is being exposed to other people’s programming. Because you can't write enough programming of your own to have it be useful for you to read it, to learn something.
JAMES: Yeah, I think I agree with that. I think when you are a young, junior programmer, I would say you need to be writing more than you are reading, because at that point, it's learning how to think like a computer and talk to a compiler -- all those really stupid things we have to learn in the beginning. In that case, I really feel like you just got to write and do it wrong fifty thousand times, so you can figure out why you'd never do it like that.
But as your experience grows up, in my opinion, it reverses. You should be writing less, and reading more as your experience grows, so that you can see code, you can see patterns, you can see how other people design things -- for good or bad -- that you learn as much from bad ideas, as you do from good ideas, I think.
JAMES: That’s my opinion on that. What do you think, Avdi?
AVDI: I think that that rings true. Yeah, I think it makes sense to start with more writing than reading. I mean the reading is definitely important, but it's really hard to follow something if you don’t have the context, and you need to… I think you need to write something badly before reading a really well-written version of the same thing, gives you the same AHA moment.
JAMES: The other thing about code reading, it's basically the way we communicate with each other, right? All our books and things like that… Or when people say, such and such project is great code, you know. It's worth going to check it out, so you can see why people say that’s great code. And generally, it's because it's very expressive and easy to understand -- hopefully. Usually that’s the case. Sometimes because it's kind of insane, like if you ever go read camping.
JOSH: So I'm going to try something here. I don’t know if it's going to work, but I wanna make an allusion to a German philosopher. So I'm talking about Wittgenstein’s ladder. Is anyone familiar with that, you guys?
JAMES: I'm not.
JOSH: So Wittgenstein was an important philosopher, and he created this conceptual construct called The Ladder. And the point of the ladder was you have a bunch of wrongs as you climb up the ladder, and you have to be standing on the nth wrong, to be able to reach the n+1 wrong. So his ladder was a philosophical conceptual construct, where you have to master a certain level of thinking, before you realize that level is inadequate to describe the world correctly. But it's the only way that you can get to the point where you can see the next wrong with the ladder. And I think that James, what you were talking about junior programmers, they just have to write a lot to get the foundation where they can start… where they can have the context to understand what's going on in that next level. I think that’s really important. So I was just trying to make an allusion to Wittgenstein's Ladder, which I think is acknowledged to be a fairly important conceptual piece. So if you get into that sort of thing.
JAMES: Yeah, makes sense.
JOSH: Let’s talk about tests in code reading.
JAMES: Okay, that’s a good point.
JOSH: So I think that tests are really great place to start when you are looking at new piece of code. But the conundrum is what happens when there aren’t enough tests -- or any tests.
JAMES: Right, right. Of course.
JOSH: What do you guys say about that?
JAMES: I do tend to look at the tests first. I do actually try to get them running pretty early on when I pull down a new project to try to just get through the setup. That’s usually a hurdle. It's getting better with things like Bundler and stuff, because usually, you can just do the bundle and get pretty close. And then, I try to get the test running.
We seem to be bad about documenting if the tests have unusual dependencies. If you have to have something running before the test will go. And so, I usually run into a problem or two, and have to figure that out. But once you get the test running, then it's nice because if they are passing, then you know that they’re probably a pretty good representation of the underlying code. So as you are looking at something, you can go to those particular test, and see how they use it.
JOSH: So the thing that you just said that I loved was you were talking about getting the tests running. And I think that that points to reading code as an interactive experience. It's not the same thing. Reading the code while it's running and playing with it, is a really different experience from reading it in a browser window, just looking through the code on the GitHub repo, or printing it out and reading it. I think poking around with it and playing with it… actively reading it is a very powerful technique.
AVDI: Yeah, I always think of Michael Feather’s talking about how to understand some legacy code that you've come into. And he talks about going into the code and reading in it, and just every time you see a point that you're not sure on, or you see a point that you think you know what it's doing, you put in an assertion, which will fail if your belief about what the code is doing is wrong. And you just decorate the whole… all the code you are reading with all these assertions. And then you run the code, and you validate your beliefs about what you’ve just read.
JOSH: Yeah, that was actually in the back of my brain as I was talking about this. I read that when he said that, “Oh, that’s nice.” One way that I've done that -- which is kind of like that -- is instead of putting all those assertions directly in the code -- which is actually kind of brilliant – is you write test cases.
JOSH: If you have to run tests, you can start writing your own tests, and put your assertions in there.
AVDI: Right. The issue I have with going in… with reading the test first with a lot of code bases is sometimes you don’t get a very good perspective from that, because sometimes you'll find code bases, where a sort of a trivial case was tested to death, and then some of the code that’s really the most central code in the system, and the hairiest code system, is not really tested at all. Maybe it was hard to test; maybe it was written in a hurry or something like that. And so you can sometimes get a skewed perspective, because you see like all these… you read all these tests for a piece of functionality that's actually isn’t that interesting.
JOSH: Right. And a lot of times, the core functionally thing that you may not bother testing because you think, “Oh, it will just get hit and tested as a side effect or second order effect of testing some piece of code that uses it.”
JOSH: That’s true. But I think that using test as an active way of reading, and being able to modify tests, or insert assertions right in the code itself, is a pretty powerful technique. I think IRB or Pry is also another nice way.
JAMES: Right. Especially for libraries like [unintelligible].
AVDI: Another question for James.
JAMES: Go for it.
AVDI: So you basically wrote a book about code reading.
JAMES: I did?
AVDI: The Ruby Quiz book.
AVDI: …is a book where you set these challenges, and then you read a great deal of code. And then you distilled it, and presented it. And I'm curious what you can tell us about just the process of doing that.
JAMES: So that's actually a neat question, because a lot of people think I ran the Ruby quiz for the community -- and that's not true at all. I don't care about you guys; I do it for me. So running Ruby Quiz was a way to improve my skills in a dramatic way, in that, every single week I would read all the submissions and write about them, so I can play with them, and stuff like that. I did learn a lot of things.
The reading of the code in the Ruby Quiz was very complicated, because we would get everything in, and I only had a little bit of time to write about as things are coming in. So I would try to get them working right off the bat. Like we were talking about earlier, if they had tests, I would play with those tests. If I ran in too much trouble in getting them working, I´ll generally set them aside, because there just wasn’t much time for me to debug a lot of that, and still have time to write the summary and stuff.
But I actually think that’s kind of a useful tip for dealing with libraries anyway. If I'm trying to figure it out, and it's a pain in the butt, and I can even get it running or it's too much trouble, then I´ll probably don’t wanna be using this library anyway, because if I have to go to contribute to it at some point or anything like that, then that’s going to be difficult. So I try not to do that if it's difficult.
Then once I have it working, I generally tried to throw different inputs at it and see what would happen. What happens when I do this, what happens when I do that. So, a lot about what Josh was talking about actively reading it. And then, I would try to work through the code as much as possible, to figure out the path of execution that was taken, and what were its core data structures. Oh, this one is using a stack to manipulate the data as it runs through or things like that. So that was probably how I learned to read code, was doing the Ruby Quiz.
JOSH: Oh, I have a reference. I don't know if there is a video of it online, and I don’t remember exactly what year it was, but there was a Rails Conf, I think it was one of the Rails Confs where Adam Key gave a talk on code reading. It may have been a Ruby Conf, I'm not sure. They all kind of blur together after a while. [Chuckles] But it was a pretty good talk on code reading. And a lot of it was actually advise on how not to write on readable code.
JAMES: That’s cool. There's a video online?
JOSH: I don’t know. I can take a peek and see if I can find it. And if so, we can put it on the show notes.
AVDI: I have kind of on a similar note. Again, I'm not sure. I think it was maybe a talk Dave Thomas did -- a talk or an interview or something where he was talking about code reading -- and I remember at one point, what stuck with me was that when he was first jumping into a code base, he'll take the entire code base, and he'll basically like put it all on a page.
JOSH: [unintelligible] from 10,000 feet.
AVDI: And zoom the whole thing out, so you can't really read all of it, but you can kind of see the shape of the code, and I actually think that’s a powerful way of approaching it.
JAMES: Yeah, it's surprising what you can tell like that. Like there's usually, this one module that just has a bunch of t tag methods, or usually utilities or something. And then there's usually one section where this one monster method, or at least a big chunk of code all kind of grouped together, and you can tell that’s like the beating heart of the thing.
JOSH: I wonder if there's a clever way to use git, to look at the metrics of which file has the most changes.
JAMES: That’s a good question. I don’t know.
AVDI: There's a tool for churn.
JOSH: Oh nice, okay. That would be something I think that could be helpful.
AVDI: That was one of the interesting problems that we were tackling when we were doing caliper was it’s easy enough to track like, “Oh, I'm going churn for project once you've kind of hooked into it.” But we were trying to go back into the history and get like a sampling of churn overtime. And you know, without running thousands of commits through it for the really big project, so that was kind of an interesting problem.
JAMES: I love having git… when I am reading code, because I can do things like make changes, screw with things, and then just throw it all away so easily, you know?
JOSH: Okay. So let’s get down to reading. Let’s try our skills out. So for those of you following along at home, the project that we are going to do our dramatic reading of is rubygems.org. [chuckles] So, this is up on the GitHub.
JAMES: We'll put a link in the show notes. And we did cheat by taking the 20 minutes or so it took for three of us to pull it down. We did that off camera.
JOSH: [Chuckles] So yeah, this is the rubygems/rubygems.org repo on GitHub. So this is the Rails application that is behind rubygems.org. So when you can go look at all the gems there, this is what's running. And I think that Avdi and I both have made small contributions to this code base.
JAMES: James has absolutely no [unintelligible].
AVDI: Very small.
JAMES: Okay. So the first thing I think all of us did is we cloned it locally, right? All of us.
JAMES: So that we could see it in our own editors, something I can't… I mean, I can look at little things on GitHub or something like that, but I can't really read code like I need to read code, unless I have it in my normal environment, which my normal syntax highlighting, my keyboard shortcuts to go where I wanna go or things like that. So I think we all made local copies of it. So Avdi and Josh, when you worked on the site, what did you work on?
AVDI: I don’t remember. [Chuckles]
JOSH: [Chuckles] Okay. I do. So if you go look a page for a particular gem, there's a little box that has a piece of code or command that you type to install the gem, and I added the bit that they gave a line that you can put in your gem file, that has the ~> the version number on it, because I wanted to encourage people to use the… I think it's the conservative operator… I forget what they call that thing in the Ruby gems.
JAMES: The ‘twiddle wakka’.
JOSH: Yeah, okay that thing. [Chuckles] So I was encouraging people not to put ‘>’ in their gem file. So that was the whole point of that. I wanted to give them good behavioral model.
JAMES: Gotcha. So, having never seen the project before now, I've been over here cheating a little bit as we've been talking. I've been kind of just browsing through it. The first thing I did was just open the app folder, and just kind of scan down there, because that gives you a good idea. You know, you are always going to see that in the Rails app, the model view and controller directories and such, but I did see some interesting things in there, like I saw the assets directory which made me think, “Oh, it's probably a Rails 3.1 app,” but I don’t think that’s true. I think it's actually Rails 3.0. I know, from different source.
Then I did see a jobs directory in there, which I assumed would be background jobs, and that got me kind of curious about what they were using for that. Instead of actually looking in there to figure that out though, I opened a gem file, and just kind of browse through the gem file. It's amazing what you can learn just looking through the gem file. For example, that’s where I saw the Rails 3.0.10, so I assume it's a Rails 3.0 app. I saw some gems in here about PostgreSQL, so I'm assuming this is a PostgreSQL app.
I saw Redis in here, so I'm betting it uses Redis for some things. And then I saw Delayed Job, so that I'm assuming is the background system. And of course, you can see what testing tools it's using, Capybara, Cucumber, Rails, Factory Girl, things like that. And then I also saw Sinatra in the gem file, which I just found that kind of interesting. I wonder how that’s being used.
JAMES: Those were some of the first steps I took, looking at the code.
AVDI: Well I just ran c tags over the app in lib directories, to compile a cross reference of classes and methods, which will hopefully help me navigate around a little bit better if I see it, referenced to a class, like navigate to its definition.
JAMES: Interesting. Good trick.
JOSH: Nice. I usually just rely on searching for regular expressions, searching for class names or methods names.
AVDI: Yeah, well I use a lot of act as well, but c tags can be handy. And actually, so I primarily used Emacs for writing code, but sometimes when I'm getting to a new code base, I´ll feed it into RubyMine, because one of the things that ruby mine is really good at is cross referencing a code base. And you can ask it things like, “What are the all the places this method is defined.” It's got a pretty decent static analysis in it.
JOSH: Yeah, I've been using RubyMine more lately. I've actually been appreciating that quite a bit. I'm a big fan of IDEs, I just don’t think that there’s a really great Ruby IDE yet. [Chuckles] I'm looking forward to that.
AVDI: I think when you are navigating a new code base, you really have to use every tool you can find to help you find your way around better.
JAMES: Yeah, that's a good point. I mean, just the amount of code that's involved, can be pretty daunting. I'm not sure exactly how big gem cutter is… if I can figure that out.
JOSH: I just ran rake stats, and [chuckles] which I think is a reasonable place to start when you are looking at a new code base. And so, there's about 500 or so lines of controller code, 150 lines of helper code, 930 lines of model code, 80 lines of library code. So this is a reasonably skinny controller - fat model, it looks like.
JAMES: Yeah, that’s really interesting. I really expected more code.
JOSH: Well, rake task isn’t super awesome about finding code everywhere in your project; it just knows the standard places to look. So if they have an atypical… there's a lot of mailers and middleware and jobs in here, that code might be hiding that rake task doesn’t know about. But the general cases, mostly model code.
JAMES: Okay, I glanced through the routes file real quick, and the interesting thing about this routes file is it's divided; it's got comments kind of showing the different sections, which I was grateful for because it kind of showed me that the app is divided into two main chunks. Basically the API, which I assume is what the Ruby gems clients uses to talk to the application, and then the UI chunk, with a couple other minor chunks, but those look like the two main chunks. So the UI I assume is like the gem pages that Josh was discussing earlier. Yeah, and I think that the way downloads happen is that there's a Sinatra app.
AVDI: I just wanna say there is a nice use of comments here, because the way that it was so quickly obvious that the UI and API were two separate sections with the routes file, is that somebody very nicely put in some big headers over those sections, saying API and UI.
JOSH: Right. Although even without the comments, there's that namespace API block that starts everything off, and I think that makes it fairly obvious that you are dealing with the API there. There is no scoping on the rest of it, so it's nice that there's that nice UI comment there.
JAMES: So, gem cutter is kind of a dual headed hydra in that, it has to communicate with humans who are searching it, or looking at gems and things like that. And then, it has to communicate with obviously the Ruby gems command line program that does things like installing gems and stuff.
JOSH: Yeah, and the UI routes seem to be pretty straightforward. You can get an idea what the resources are pretty quickly and they are searching profiles, stats, and then gems.
JAMES: So I went searching for what is the Sinatra portion of the app, and I found it in… it's in app middleware hostess. And there's a class… hostess that inherits from Sinatra base.
JAMES: So, I'm sorry, what did you say that was for, Josh?
JOSH: I believe that’s the thing that serves up the gems to the gem command.
JAMES: Interesting. So via S3, that’s kind of what it’s looking like.
JOSH: Yeah, so like in line 63 there, “Please upgrade your Ruby gems, it’s quite old.”
JAMES: Yeah, that’s just what I saw too, yeah.
JOSH: [Chuckles] So the query feedback here going on to the command line.
JAMES: So this is probably run as a middle ware to bypass a large portion of the Rails stack, and allow more efficient running of these API calls that don’t need a lot of Rails niceties. So that’s pretty interesting.
JOSH: I have not yet built an application that use Sinatra that way, but it's supposedly a pretty nice way to make simple requests much more efficient.
JAMES: Yeah, I've worked on applications that use it that way, and one of the things I like about it is, I do kind of just like having the separate apps, the server for the Sinatra in handling the API, and then the main Rails app, doing the main UI, just because you can rotate those out independently. If you need to update the API, then just take that one down, bring it back up… leave the UI.
JOSH: Although with this hostess running as middleware, you would have to redo the whole application framework…
JAMES: That’s true. It looks like you would.
JOSH: Okay. So the place that I like to go to after looking at the routes file is the schema.
JAMES: Schema? Very nice.
JOSH: Yeah, schema.rb, and that I think is a good place to zoom everything out, and look at it from ten thousand feet because it gives you a pretty good idea of how big things are and how big your tables are. And I noticed that if there's a really big table somewhere, then there’s often like a god object, there's that word again, Avdi…
JOSH: We were just talking about that offline. But yeah, it can show you a place where there is an object that has too much responsibility, or maybe just an object that has a lot of responsibility.
JAMES: Looking at this schema, the interesting things I see, obviously the user table is one of the bigger table that doesn’t surprise me at all -- it almost always is. But then the table below that in the schema is the versions table. And that looks like it's a pretty important piece of this architecture; it's got quite a few fields, and you can notice that there's some heavy indexing on it, right below the schema, there's several different indexes of various types, so I assume that it sees a lot of traffic.
JOSH: Yeah, and that makes sense. If you look at the Ruby gems table, it's actually quite small; all it has is a name and number of downloads [chuckles]. And so I think that most of the work that's going on is related to the particular version of a Ruby gem or a release.
JOSH: And then there's a few things in there like dependencies and delayed jobs, it's kind of interesting. It's nice. The schema is only about 150 lines long. It's not one of those monstrous 3,000 line schemas.
JAMES: Yeah, there's not really any table in there that’s ridiculously huge or anything like that.
JOSH: Yeah, the one that looks interesting is the links sets.
JAMES: Yeah, I wonder what that is. It's the link side of a gem specification, that because looking at the fields, you've got the wiki, the docs, the email, yeah, it's the links of a gem specification.
JOSH: Well probably just the has_one off of the gem, and I be I find that pretty easily. So I´ll go in to the rubygem.rb and in fact, it has one link set. Okay.
JAMES: So I'm guessing they have many versions, just looking at the schema, and yes, it looks like that’s confirmed.
JOSH: Yeah, so now that we've looked at the schema, where I usually go next is I look at the models and the associations.
JOSH: So get a feel for how they can put hooks together.
JAMES: Yeah, that’s a great way of the land technique, seeing how things hook together.
JOSH: Yeah, so looking at the app models directory, there's about a dozen or 15 or so models there.
JAMES: That’s not ridiculous.
JOSH: No, not ridiculous at all. For being a pretty sophisticated application, it's nice that this is not too huge. So I looked at this code about two years ago, and it's definitely improved a lot since then. So, kudos guys.
AVDI: Although a low number of classes is not always an indicator of not much code.
JOSH: [Chuckles] Can you say more about that, Avdi?
AVDI: [Laughs] So yeah, I mean sometimes you come into a big project that doesn’t have very many classes, and you go, “Oh, no,” because you have to find the class in there that’s like 2000 lines long.
JAMES: It looks like it holds pretty well in this case though. I've looked at the main objects, like Ruby gem and version, which I think are two of the primary models. Both of those, just 250 lines or so.
JOSH: So I did a wc/app/model/*…
AVDI: Ooh, good one
JOSH: Yeah, to see which ones are the big files. And Ruby gem is 250 lines, version is 274 lines, downloads is 150, dependency is 100. So you know, not too terrible. There's a couple really small ones that are in the order of 20 lines.
JAMES: That’s awesome. That was a great trick for just getting the general size of things too.
JOSH: Yeah, I do that every now and then. I kind of wish that my IDE or I had an IDE that showed me that sort of size, as I'm scanning over things. But it's not too hard to do it yourself, though.
JAMES: Or it could draw the icons larger and larger, you know. [Chuckles]
JOSH: [Chuckles] Yeah. By the way, if you wc | sort–n, it will sort everything by size.
JAMES: That's awesome.
JOSH: So I remember James, recently you are talking about your picks, the Unix command line, So you we are not using the Unix command line for code reading.
JAMES: Look at Josh, showing off his skills.
JOSH: [Chuckles] I just take my inspiration from you, man.
JAMES: [Chuckles] So yeah, just doing that wc trick, it also gives you the total -- which is kind of neat. So only 1154 total in the app model’s directory -- which is nice. So I'm kind of curious about how the controllers are laid out here, so I'm going to poke around. And I see an API sub directory, so that's good. So I'm assuming the main interface controllers are everything out of that API sub directory, and then in that API sub directory as well, we go define the specific actions that interact with the Ruby gems API.
JOSH: And doing my wc trick on that… we got to look at the V1 subdirectory.
JAMES: Right. There's a V1.
JOSH: Okay. So that’s not too bad. It's only about 250 lines of code for the V1 controller set, which is comparable to the UI. So the UI has about 260 lines total.
JAMES: Yeah, I've been looking through the controllers a little bit, they are very much skinny controllers, that just delegate to underlying methods.
JAMES: So I'm kind of curious how does Redis gets used in the system? Do you guys know?
JOSH: We’re using Redis.
JAMES: Oh sorry, the gem file?
JOSH: Well let’s see. Is it using resque… no it's using delayed job.
JAMES: No. It’s it's in config initializers, we can see some... I just did a global find on the project for the word “Redis” that can actually get setup in a config initializer. And then a couple of migrations about it, but that's actually all I'm seeing right now.
JOSH: There's a lot of stuff about Redis in the download model.
JAMES: Ah, the download counts, right?
JAMES: That would be my guess, just from its location. Let’s take a look.
JOSH: Yeah, it's doing a lot of increment stuff.
JAMES: Yeah, count key, Ruby gem version key. I bet it's counting the downloads.
AVDI: So this has nothing specific to do with Redis, but I just reminded myself of a code reading trick that I used, now that I'm thinking about it, which is git blame. Especially in connection with a good editor. So my editor, if I do the editor git blame command, it gives me basically two columns; on the left side are the commits, and who committed them. And on the right side is the code that’s been colorized according to commits. So basically, it got a list of all the commits relevant to this particular version of the file, and it assign the color to each commit.
And that’s really useful because, I have this view now of a file that shows me the related changes, like which methods were written at the same time. And as part of the same functionality, and which parts of the methods were then added later.
And the other nice thing is that it gives me some of these names next to it, so if I wanna ask somebody about what’s this all about, I actually have a good idea now who to go ask. But what I really like about this is just the color coding, where I can see related changes. It's kind of like a flat view of this is just everything, and it's not as clear what's related. I have an idea now of which things are part of a particular feature.
JAMES: And another great thing about that is if you are interested in a particular part of it, you can just take that and feed it to get show, and get that whole group together.
JOSH: So Avdi, what tool are you using to get the colorizing there?
AVDI: This is just the way Emacs handles, I think it's the standard Emacs git handling, vc it handles most version controllers the same way. And yeah, like James was saying, I can get a key, either to see… I can hit a key to see that commit, and the message associated with it. And then I can hit another key to see the entire diff of that commit. So it's a really handy technique.
So, if you are curious about a particular method, first you do a git blame, you see that it's part of a particular change, you go to that change, then you go to the entire diff for the change. You see everything that went with that particular change, and you get an idea of, “Okay, this was a unit of functionality that was added.” And this is how.
JAMES: By default, when I do git blame, I don’t see the color coding. There must be a setting for that, that I don’t have set. I have diff color for my diffs and stuff, but I don’t see it in the blame. I need to look at that.
AVDI: Is that on the command line?
JAMES: Yeah, I was doing it at the command line.
AVDI: Yeah, I don’t know if git will do that. This is just something that Emacs layers on top of it.
AVDI: And I assume other editors do as well.
JOSH: So, have you all set things up to be able to run the tests or anything?
JAMES: I think I'm close. I did bundle it.
AVDI: I think I'm missing a library.
JOSH: Well, you got to set up database yaml, by the way.
AVDI: Okay, right.
JOSH: Yay, it's using postgres.
JAMES: I know, hurray! Do you have the test running, Josh?
AVDI: Yeah, I don’t know if I can resolve my…
JOSH: I got to set up my database… okay, I'm running tests. Cool. And they are all passing, nice.
AVDI: I may or may not be able to… on this, I'm sorting out the bundle failure.
JOSH: Oh, what happened to your bundle?
AVDI: I'm just missing some postgres headers.
AVDI: SO, install the right package.
JOSH: Yeah, I learned a new thing about PostgreSQL on Lion, and that’s that Lion comes with PostgreSQL.
JAMES: Oh, really?
JOSH: Yes. However, it's not the version of PostgreSQL you wanna use. So if you do a brew install postgres -- which is what we did -- it works great. But if you've already bundled your Rails application, the pg gem, will have built itself using the Apple supplied PostgreSQL headers. So all you have to do is delete that gem and rebundle it, and then it's fine.
JAMES: Oh, “Connection refused. You got to have Redis running.”
JOSH: Oh, wow [Chuckles].
JAMES: Right, to run the tests..
JOSH: I must have been set up for that already. I only have one failure, and that was in one of the Cucumber features.
JAMES: Do they give a config for Redis by any chance?
JOSH: So I obviously have cheated here, because my machine is still set up from having done work on gem cutter or rubygems.org a few months ago, so I've already gone through the work to make all this run before.
JAMES: There it goes. I got it. I ran the test. And they all passed. 334 tests, 667 assertions in the models.
JOSH: Okay, if you just run rake, I got a bunch of stuff from Cucumber.
JAMES: Yes, it's doing… I'm working through the controllers now. So yeah, getting the test and that Redis gotcha, is what I've meant to mention earlier when I was saying, I always seem to run into some dependency that not quite well-explained -- and that’s there again. Until I have Redis going, it wouldn’t do anything. It looks like it has fair use sense of test suite.
JOSH: Yeah, that’s pretty cool.
JAMES: So the page you worked on Josh, was the page that shows an individual Ruby gem. I'm assuming that’s the Ruby gems controller, perhaps?
JOSH: That sounds familiar. And that would be on the show action. Oddly enough, the contribution that I made, or the patch that I've submitted, I guess was far enough out in their coding styles, that they probably decided it was easier for them to rewrite my contribution. So I don’t think my name actually shows up in the history anywhere. Yeah, I was very sad at that.
AVDI: I finally figured out what I did. I worked on webhost.
JAMES: Oh yeah, webhost. That unknown feature in Ruby gems.
JOSH: [Chuckles] What does the webhost do, Avdi?
AVDI: It was to enable Ruby gems to ping another site when a new gem was pushed. And this was when I was working on… we wanted to be able to note that somebody who is plugged in to caliber has pushed a new gem and that we would pull down the gem and run metrics on it.
JOSH: Okay. I just found the code that was inspired by my contribution. [Chuckles] So if you go to the show view for the Ruby gems controller, it starts at line 74.
AVDI: So my Rake is complaining that I don’t have a new [unintelligible].yml
JOSH: Yeah, you can ignore that.
AVDI: I see. Never mind.
JOSH: That doesn’t actually make any difference.
AVDI: I see.
JOSH: So, when you are reading code, I think that you can be reading code for a couple of reasons: one is just to look at the code base and learn from it, or have some esthetic appreciation of it. And then there's also reading code, because you have some objective, “Oh, I wanna add this feature.”
JOSH: And I think that you end up reading the code in different ways, when you have a particular objective or goal in mind.
AVDI: I think, fundamentally you usually learn more when you are actually doing it in service of a particular feature.
JAMES: I agree.
JOSH: I think that you can definitely learn more in a more focused way. When I made this change, I was very focused on making this change, and I didn’t learn a lot about things like Redis or Sinatra. So I was very focused on that.
JAMES: That’s what’s kind of nice about an app like this that’s divided out pretty well, it's basically two different pieces, you know? And you can go in to the API side and probably ignore most of the UI side, go into the UI side then ignore the API side.
JOSH: I ignored it completely. It was great. So have we learned anything?
JAMES: Yeah, what have we learned from spelunking in Ruby gems. Let’s go around the horn on that one. I've learned that the application was not as complex as I expected it to be. Just poking around it, I've been real pleased, and that I think it's a testament to the value of well-written code. The methods aren’t that huge, I was able to poke around and get it fairly decent, understanding what things were pretty much right off the bat. The division of it seems to make sense to me. I was able to understand where things are, hunt for certain things when I wanted to. So I was impressed with that.
AVDI: Major open source projects are always seem so much cleaner than the proprietary systems that I usually work on.
JOSH: [Chuckles] Isn’t that the truth. Well, you have to let other people look at your code, I think you care about how it looks more.
JAMES: Avdi, you are using your code it’ s sometimes messy.
JOSH: [Chuckles] So one thing we didn’t do is we didn’t look at the tests at all, even after all of our blah, blah, blah look at the tests…
JAMES: I have actually been coming through them a little bit. But it looks like they use that has shoulda…
JOSH: Yeah, it’s all Test::Unit and shoulda, I see some pretty standard Rails stuff. They don’t have any fixtures.
JAMES: They used Factory Girl.
JOSH: Yeah, there's factories right there.
JAMES: Most of them are in application.rb is where you'll find those factories.
JOSH: Yeah, it's not bad.
JAMES: Yeah, really clean.
JOSH: Okay, well we are kind of out of time, but it might be interesting to spend a little more time looking at the tests, and seeing what they are doing.
AVDI: Something else that I remember that I always do when I'm trying to figure out a code base, is if it is a Rails app, and if I am trying to figure out a particular feature so I can add to it, I´ll tale the log in some window, and then I´ll just step through the feature manually in the browser, and just look in the log at what’s touched. Look at what controllers are being hit, so I know like where to start, and I look at what tables are being hit. And a lot of times, there are surprises in there. Maybe there's a model that you are sure is involved because of its name, and then you look at the log, and you realize that model is actually deprecated or something like that. And it's actually something else that’s being used.
JAMES: I know it's actually bad in this code, as I was looking around, there was apparently an older version of the API, and that’s kind of sectioned off now, and it deprecated controller.
JOSH: So do either of you guys ever used a tool like Flog to do some code analysis… we were talking earlier about just simple tricks to see where the big code is, and where the complex code is. Do you ever use something like Flog?
JAMES: I haven’t used that. I've seen it used, but I've never done it myself.
JOSH: Yeah, I've never gotten to a point where it seemed like it would be worth spending the time figuring out how to make it work. It probably isn’t all that much, but…
AVDI: It's probably easier if you are in charge with the project. I usually find myself… big projects that don’t have the time to figure out how to make that work; how to make metric tools and stuff like that to work on their code. There's always something that comes up that’s like some file that it pukes on or something like that.
JOSH: Yeah, when we do the episode of metrics, maybe we should… at least I´ll take a little time to figure out how to use Flog right.
JAMES: Yeah, this app was pretty easy to get up and running, mainly because of Bundler, which installed all the needed dependencies, and then things like that. But one other things that I loved as soon as I see the end of the directory, there was a .rvmrc file, so I just switched me to the proper version of Ruby, to run it. I really love having that file, just because even if you don’t use RVM, at least you could open that file and look to see what version of Ruby it's expecting.
JOSH: Yeah, I think that’s become really valuable for open source projects, because there are so many versions of Ruby floating around now. It's interesting, this one runs on 1.9.3.
JOSH: Yeah, well it looks like it has the typical boiler plate files for doing Sprockets, but they haven’t been modified at all. You know the place that used to be really key to look, that nobody looks at anymore, and that’s the vendor plugins directory.
JAMES: Right. Yeah.
JOSH: [Chuckles] You'll look at it now, and there's two tiny things in there; there’s dynamic form and Heroku asset capture. So I think the gem file is totally taken the place of looking in vendor plugins.
JAMES: So that’s interesting. Does Ruby gem run on Heroku?
JOSH: Oh, yeah.
JAMES: I didn’t know that.
JOSH: You know where we didn’t look at all?
JAMES: What's that?
JOSH: That was the application readme.
JAMES: Kind of a good point. I think it has a fairly nice broken down, how to contribute…
JOSH: Yeah. So one little trick that I will offer to Textmate users, is that if you open the readme.textile file, and then you hit command option control p, it will preview the Textile and render it for you, so it's a lot easier to read. Or you can just read it on git hub.
JAMES: Yeah. [Chuckles] Which does the same thing.
AVDI: Command, Option, Control P… and people mock me for using Emacs.
JOSH: Well, Textmate is almost Emacs, in terms of…
JAMES: Yeah, it is.
JOSH: It's certainly mockable.
JAMES: [Chuckles] It's funny that us, developers has like totally side stepped the readme, you know?
JOSH: [Chuckles] Well, I think maybe that’s a cautionary tale. I think that a lot of readme’s are kind of useless. Rails generates a readme that is… the first thing you do when you generate a rails project is delete…
JAMES: Destroy the readme, right.
JOSH: Yeah. And public/index.html
JAMES: That’s what I was going to say, yeah.
JOSH: Why would they even generate that anymore.
JAMES: Stop doing that. [Chuckles]
JOSH: [Chuckles] Yeah. So any other last words? I guess I haven’t said anything about what we learned. I feel like I was less intimidated by this code base than I was when I was trying to work on it before.
JAMES: That’s right. Now Josh intimidates code bases -- or the other way around.
JOSH: [Chuckles] Look out…
JAMES: [Chuckles] All right, well we better get into the picks. It's time to do some picks. This week, we will start with Josh.
JOSH: Okay, I had a really busy week, so I don’t have much to say for picks this week, except I have a good shopping pick, since we come here to shopping season. I recently had to buy a Mac, and I used… I don’t know if people are aware, but Apple store just started doing BOPIS – Buy Online, Pickup In Store. And it was awesome. I went and bought something at Best Buy last week, and I did buy online pickup in store, and it was the worst shopping experience ever. Of course, it was Best Buy, so what will you expect? [Chuckles]
And then the next day, I was looking online at the Apple Store to buy an iMac, andthey have this pick up in store feature. So I did it, and I walked two blocks to the Apple store, walk in and said, “Hey, I'm picking up my iMac.” And I gave them my name, and they came out and had my system already, and I walked out of the store with it. [Chuckles] It's incredibly easy.
JAMES: That’s nice.
JOSH: This is apparently a brand new thing for the Apple store. And if you got to go buy something at the Apple store, just do it; it doesn’t cost anything and you don’t have to wait around, while they put your system together.
JAMES: Nice, so you can still do build the order configurations and stuff?
JOSH: No, you only get to do the stuff that’s right there in the store. I don’t know. Maybe you can do custom configurations, and they'll ship it to the store and you pick it up there. I haven’t investigated that. But if you have a standard configuration that’s definitely simple, it took them about ten minutes to get it ready for me to walk over and pick up.
JOSH: That’s it for me this week.
JAMES: Avdi, what do you got?
AVDI: So, at Ruby Midwest, we talked to Dave Copeland about his book, Build Awesome Command Line Applications in Ruby. So we've already kind of that a bit, but I have finished reading it -- or at least I've finished reading the beta -- and I recommend it. it's a good book on a topic, so if you wanna build command line applications, which have nice user-friendly UIs, definitely recommend it.
JOSH: I wanna check that up. Maybe we can do a book club on that at some point. But Dave Copeland spoke at GoGaRuCo earlier this year, and he did a talk on test driving command line applications in Ruby, and that is up on line. So I can put that on the show notes too. He's a good speaker, and it was a good talk.
AVDI: Yeah. And also, a few weeks ago, I picked up a Galaxy Tab 10.1 which is the tablet that Apple I think is suing Samsung over, because it really does look like a widescreen iPad. And I got it so that I can read all my technical eBooks, and so that I could do video conferencing on a separate device in my Google+ and Skype, and all that stuff. And it works for both of those tests perfectly. I've been very happy with it. So good device.
JAMES: Very cool. All right, like Josh, I had a kind of a busy week and haven’t looked into too much, but I do wanna plug Alfred. That’s what I use for like application launching, and stuff like that on the Mac. It's really hooked on quicksilver back in the day, and was very sad when it kind of slowly fell on to this repair. I believe it's actually been resurrected and is around now, but I left quicksilver doing that time period when I was not behaving well. And I tried launchbar for a while, I never really could enjoy launch bar after coming from quicksilver. And then, I finally moved to Alfred.
And I have to say, it was okay when I got there, but it's been getting better and better. And I just hit one [unintelligible] yesterday. And I've been playing around with some of the new features, and it's almost back to quicksilver. Great for me. And it does have some features that I didn’t even use in quicksilver, so I do recommend checking out Alfred. And spend a little time around fiddling with it. You might be surprised what's under the hood. I recommend picking up the power pack, and then digging in to the features a little. Some that I use all the time, in addition to this application launching, I use a calculator all the time, I dictionary to look up words and it will spell correct for you as it goes, which is awesome. And I use now in 1.0 the new things like global hotkeys, so now I just have a key that opens my terminal or my browser or my editor, and one that pause and plays iTunes for me -- those kinds of things.
And you can hook into Apple scripts with it, so I have one in the morning when I come in, I just trigger an Apple script and it opens the apps that I like to have open when I'm working and things like that. It's pretty well-rounded; it's not hard to figure out, and for me, it's pretty vital to using a Mac. I don’t use the dock at all; I just hide it.
JOSH: So I've been liking Alfred a lot too. I've been using that for like a year. I made the same that you did with quicksilver to launch bar to Alfred. Launch bar was great, except that it always have alike a one second pause.
JAMES: Right, yeah.
JOSH: That drove me nuts. So I wanna ask you about… [unintelligible] to my command space from the spotlight menu, to Alfred. Do you do the same thing?
JAMES: Yeah, same thing, Command+Space for me. So anyways, Alfred is definitely worth a look and I recommend people check it out if like application launchers; makes using your Mac much more convenient. One of the cool new features, I´ll mention one more. There's a new… you can set up a keystroke to open your browser and open like a whole bunch of tabs at once.
So if you have those five web pages you like to read every morning or something, you can set that up, and then just make one keystroke and it will fire up your browser and open all five of those tabs. And you can just read through all of them. So it's pretty neat. It's pretty robust in its feature set. It’s worth looking into.
All right, I think that’s everything. We've read code live on the air, we've injured equipment. That ought to be enough for one show. Don’t forget next week, we are doing the Eloquent Ruby episode. It's a good book. I finished it over thanks giving holiday. I was sick, so I just kind of crawled up and read it all weekend. It's a good book. Lots of good stuff in it, and we'll have plenty to talk about, so read along, and we will see you next week. Bye, everybody!
JOSH: Bye, guys.