For the past six months, I’ve been teaching a four-day course for new Groupon Engineering hires that covers Ruby, Rails, RSpec, Cucumber, Git, and some Groupon-specific workflow, modeling, and scale issues. In general, new technical hires go through the course even if they aren’t immediately starting work on the web application, which means that the attendees tend to have a wide range of background and technical experience.
That’s a lot of ground to cover, everybody is tired by the end.
We keep tweaking the course in response to student feedback, my own impressions each time through, and random whim.
Here are some things I think I’ve learned about teaching Ruby and Rails and stuff.
The order matters, but it matters differently
The two biggest questions about teaching a course like this one are a) what order to approach the material, and b) how to handle hands-on work.
Broadly speaking, the order question is whether you go top down, starting with a high-level web page and working down to Ruby details, or bottom-up, starting with Ruby details and building up to a Rails page.
Both approaches have problems. If you start with Rails, you are doing a lot “we’ll explain that later” kind of handwaving, and the danger is that the student never gets a deep understanding of the material. That said, you do tend to focus on issues relevant to creating Rails apps.
If you start with Ruby, then you are doing a lot of “trust me, this is important” handwaving. The danger is that the early material in Ruby is deeply without context and meaningless.
I’ve come to the conclusion that there’s no one path through this material that works best for everybody. In our course, we mostly go bottom up, starting with a tour of Ruby before looking at a Rails app. In part, this is because of who the students are – most of them have some experience in web programming and generally get what the context is. Another reason is that as an instructor, I’m more comfortable saying “you’ll see why this is important soon” than “you’ll see how this works soon”.
Is it the best way to go? Not sure – one weird thing about doing these courses is that it’s hard to generalize from one group to the rest. I do worry that it’s taking longer and longer to get to Rails. However, the way we do it now does let us teach BDD/RSpec outside of a Rails context, which I think is valuable.
The next big question is how much hands-on work to have in a course like this and how that should be structured. In general, people retain information better when they actually do something more active than listen to me talk. But it’s a slow process, and if it’s not structured correctly it can be very frustrating, especially if a student is struggling with some detail that isn’t necessarily the focus of the course. Which is not uncommon, since there are a lot of moving parts in any problem complicated enough to be interesting.
When we first started the course, we had the students start a Rails application all the way back from
rails .. And I still think there’s some value in that, in seeing what the framework does for you. We don’t do that any more, we start with a preexisting, but small application that the students add features to. There are a few reasons for the switch:
- Engineering management gently suggested that it would be rare for a new employee to actually start an application from scratch as part of their job.
- Starting from scratch is somewhat limiting in the sense that the students have to build up all the infrastructure needed to explore more interesting areas. As a result, it’s hard to keep people from getting tangled in the weeds.
- The desire to have the sample app be consistent with technology choices in the Groupon main app led to more and more setup, until it became easier to hand the application to the students with all the setup in place.
The last point was really what carried it. In particular, adding Haml to a Rails 2.x application, and converting the scaffolding to Haml wound up being a 20-minute march through arcane command line territory. That’s not a fun territory to be taking novices who, by definition, aren’t sure what’s important to remember. So we provide a skeleton with Haml, RSpec, Cucumber, authentication, jQuery, and some reasonable CSS defaults all set up. Probably a couple of other things too. Setup takes a lot less time, and since there’s a little bit the app already, the students can see some samples of say, a Cucumber feature, as examples.
I’m kind of perpetually dissatisfied with this part, though. Right now we do model stuff before view, which means it’s a very long time before the students make a significant visual change. Switching that order might be the next tweak. I also think there’s a perennial problem with making the problems sequence well, it always seems like there’s a big complexity gap between the initial interactions with the Rails app and the first – “here add a feature” problem.
It’s endlessly fascinating how reluctant students in this course are to pair on the exercises. I get it, I’d be reluctant to pair too – often the students don’t know each other, they don’t want to struggle in front of another person or they don’t want to be constrained by another person. Or maybe they just think there’s a fixed amount of learning in each exercise and pairing means they’ll only get half the learning. I need to insist more – you get much more out of a learning exercise if you are trying to explain what you are doing to another person. As an added bonus, it’s easier for the instructor to get a sense of the room when people are talking then when people are silently seething at their text editor. It’s easier for me to see where people might be stuck if they are already describing their situation out loud to the other pair.
There’s been a lot of discussion back and forth about how complicated Rails has become and what makes Rails complicated to teach. REST is a commonly noted culprit, and I think I’d say that the issue is not so much that REST a-la-Rails is that complicated. The issue is that it’s nearly impossible for a novice web developer to get exactly what problem REST is trying to solve or why it’s that much better than
controller/action. (That assumes that there is a general problem being solved, I guess…)
I think Rails 3 is an improvement here because both the routing language and the Arel/Active Record syntax are easier to manage than the Rails 2.x counterparts. Although, I have yet to meet anybody that I’m sure understands the Rails 3.1 asset pipeline, let alone is ready to teach it.
Beyond that, the biggest issues I see in teaching Rails:
- The sheer size of the framework and the way it bleeds into the standard Ruby library. There’s so many potential things to talk about, and there’s always confusion as to what Rails does, what Ruby does, and what’s actually part of the application.
- The ecosystem, which is awesome, but intimidating. Even in this four-day course we cover at least four distinct syntaxes (Ruby, Cucumber, Haml, Sass), plus RSpec, plus an authentication API. And that’s just to get off the ground.
Testing is a big part of what we try to get across in the class. We’ve made a lot of progress in the structure of the class to encourage BDD, and the last few times most of the exercises have been done using RSpec and Cucumber.
My experience is that it is much easier to make the value proposition for BDD/RSpec to a skeptical student then it is to make the value proposition for Cucumber. I’ve had surprisingly little resistance to test-first in general, though there is a frequent undercurrent of students who don’t take to RSpec’s syntax. (To overgeneralize, this is often people from a more Enterprisey Java background who don’t like the showy metaprogramming.)
I’d caution against making broad generalizations from that – part of the issue is definitely that I’m more confident presenting the value proposition for RSpec. Another part of the reason is clearly the amount of overhead needed to walk through your first Cuke. Actually, I think the now-deprecated Cucumber web_steps.rb file gets in the way even for beginners – walking somebody through the web_steps.rb and paths.rb file to resolve something like “the users page” to a URL quickly takes on the appearance of a practical joke.
- It continually surprises me how hard it is to explain Ruby symbols. A lot of languages don’t really have analogous structures. (Although a lot of languages don’t have Ranges either, and usually people get those pretty quickly). But I’ve struggled to get the concept clear a couple of times when students really struggled with how to think about them.
- In contrast, I generally don’t have troubles explaining blocks – even developers who have never worked in a language that has a similar construct can generally approach them as analogous to functions. (That said, nobody ever understands why Ruby has blocks, Procs, and lambdas. But that’s okay, I never quite got it either.)
- Personally, my favorite part of the class is always when we talk about the Ruby object model and metaprogramming. First off, I get to say things like “The instance representing the class Document is different from an instance of the class Document” and “class methods of the class are really instance methods of the instance representing the class”. And I show off the source for StringInquirer, which on one occasion caused an entire class to burst into laughter when they all figured it out more or less simultaneously.
- I think I’ve finally gotten to the point where I can confidently explain git rebase vs. merge. It has only taken four years.