DABlog

a dump/archive of David A. Black's original weblog

2006-2011

The articles are listed below, in chronological order. The first few are undated. I'm not sure why&emdash;maybe they're in twice?

Enjoy.

Training techniques and practices (Undated)

Training 1: Background and ramp-up (Undated)

Training 2: Handling mixed student levels (Undated)

Training 3: Hands-on, lectures, and demos (Undated)

Training 4: When things go wrong.... (Undated)

Corrected link to The Compleat Rubyist (Undated)

Training, part 1: Dealing with uneven levels of preparation (Undated)

Training: Introduction to a series of articles (Undated)

"Advancing with Rails" gets off to a fine start! (Undated)

Training, part 3: Advice on lecturing and topic presentation (Undated)

The night before (Tue Jun 20 21:32:00 2006)

Submit!! (a proposal for a RubyConf talk, that is) (Thu Jun 22 07:18:00 2006)

Modeling many-to-many: I guess I was right the first time.... (Sun Jun 25 08:20:00 2006)

The agony and the ectasy (of RubyConf proposals, that is) (Sat Jul 1 09:16:00 2006)

Why I am conservative about changes to Ruby (Sat Jul 1 12:18:00 2006)

10/10 review of Ruby for Rails on Slashdot (Wed Jul 12 17:35:00 2006)

The laptop stratum: thoughts from (half of) OSCON (Thu Jul 27 10:25:00 2006)

Regional Ruby Conference grants from Ruby Central (Fri Jul 28 13:09:00 2006)

Special offer for Ruby users groups, from Ruby Power and Light (Sat Jul 29 12:25:00 2006)

No more comments for the moment (Thu Aug 10 20:07:14 2006)

No, really: my book is Ruby for Rails!! (Sat Aug 12 12:14:46 2006)

Home from the Michigan Ruby Conference (Sun Aug 27 15:23:00 2006)

Free Rails workshop in Malmo, Sweden! (Mon Sep 11 10:29:00 2006)

RailsConf Europe and beyond.... (Mon Sep 18 05:08:00 2006)

Dinner for three (Sun Sep 24 12:03:33 2006)

Have fun (without me) at RubyConf! (Wed Sep 27 15:55:02 2006)

[Postponed] One-day Rails intro workshop in Toronto, December 15 (Sun Nov 19 16:34:22 2006)

More A than R: reconsidering the "new" AR object (Sat Dec 23 08:57:00 2006)

Enough already with freaking out over people's sex (Wed Jan 3 19:30:58 2007)

Will trade Ruby/Rails tutoring for website design work! (Wed Jan 3 20:35:39 2007)

Meta, shmeta: learning Ruby horizontally (Sun Jan 7 10:20:49 2007)

Emerging Tech conference coming up (Wed Feb 7 10:26:37 2007)

The Magic Pens of Ruby (Sun Feb 18 14:01:00 2007)

Sudoku solutions: who cares? (Sun Feb 25 23:47:00 2007)

DABlog now using Mephisto (Sun Feb 25 23:52:00 2007)

Rails training by Ruby Power and Light! (Tue Mar 27 14:43:00 2007)

The L in DSL: langue ou langage? (Tue Apr 17 18:19:00 2007)

Tough love from Verizon (Mon May 14 12:57:00 2007)

Boston Early Music Festival wrapup (Sat Jun 16 23:44:00 2007)

The Stupidity Tax (Wed Jul 4 12:47:00 2007)

Bang methods; or, Danger, Will Rubyist! (Wed Aug 15 11:35:00 2007)

Reflections on Wikipedia (Tue Sep 4 12:53:00 2007)

Upcoming Rails training in New Jersey! (Fri Sep 14 07:00:00 2007)

"Advancing with Rails" training in Berlin, Nov. 19-22 (Fri Oct 19 12:13:00 2007)

Upcoming Rails training, 2008! (Sat Mar 22 19:17:00 2008)

Splitting hairs over "resource": the case for the affirmative (Part 1) (Sun Mar 23 00:49:00 2008)

A short-circuit (||=) edge case (Tue Mar 25 15:11:00 2008)

Short-circuit (||=) post -- CORRECTION (Wed Mar 26 13:46:00 2008)

Getting out of Ruby's way: code beauty and/or greatness (Fri Mar 28 09:40:00 2008)

Splitting hairs over "resource": the case for the affirmative (Part 2) (Thu Apr 24 11:55:00 2008)

Death of a racehorse (Sun May 4 13:59:00 2008)

Slide words (if that's really what they're called) (Sat Jun 7 15:22:00 2008)

July 6-12 is "Link To Something Other Than Wikipedia" Week! (Sat Jul 5 01:27:00 2008)

Co-Training with Erik Kastner (Sun Jul 20 12:31:00 2008)

Pseudo-persuasion in online discourse (Wed Aug 6 11:57:00 2008)

Back from RailsConf Europe 2008 (Sat Sep 6 08:07:00 2008)

Tracks a-go-go at RubyConf 2008! (Sat Sep 13 10:00:00 2008)

Why I am suspicious of the bailout bill (Fri Oct 3 21:14:00 2008)

RESTful Rails for the restless (Mon Nov 24 12:18:00 2008)

Probative Programming: the physical unification of code and tests (Sun Nov 30 13:05:00 2008)

On the menu this season: Muslims and gays (Sun Dec 21 15:59:00 2008)

Cool wishlist management at WishSight! (Mon Dec 29 15:13:00 2008)

10 things to be aware of in moving to Ruby 1.9 (Wed Jan 14 19:21:00 2009)

Son of 10 things to be aware of in Ruby 1.9! (Fri Jan 16 14:20:00 2009)

RailsConf registration (and a hiatus year for RailsConf Europe) (Fri Jan 23 22:31:00 2009)

Why athletes thanking God for victories is stupid (Tue Feb 3 01:38:00 2009)

Ruby training in Atlanta, April 1-3! (Mon Feb 16 14:50:00 2009)

Did I mention Ruby training in Atlanta, April 1-3? (Sat Mar 14 14:21:00 2009)

Is this an early use of the slang "cool"? (Sat Mar 21 01:22:00 2009)

Envycasts featuring David A. Black: Ruby 1.9: What You Need To Know (Tue Apr 21 23:10:00 2009)

"The Well-Grounded Rubyist" now available in PDF! (Tue Apr 21 23:15:00 2009)

My new Ruby book is out! (Wed Jun 10 23:57:00 2009)

The wise Latina comment in historical perspective (Thu Jul 16 22:05:00 2009)

Ruby training: for the non-beginner? (Tue Jul 21 21:11:00 2009)

The Compleat Rubyist: what's it all about? (Sat Oct 17 14:57:00 2009)

Starting a new job in December (Fri Nov 13 13:23:00 2009)

AccrediDation (Wed Mar 24 01:07:00 2010)

Training: a series introduction (Mon Jan 24 22:52:00 2011)

Training, part 2: Handling mixed levels of student experience in a class (Thu Jan 27 12:51:00 2011)

Training, part 3: The lecturing component of presentation (Fri Feb 4 10:34:00 2011)

Training, part 4: Live code demos (Sat Feb 26 13:13:00 2011)

Training techniques and practices

Undated

This is the first in a four-part series of DABlog entries on the subject of training in Ruby and Rails. Who’s it for? If you are:

these articles might be of interest to you. In writing them, I’m envisioning a reader who’s a trainer. But that’s not a requirement, as long as you don’t mind my referring to “you” as if “you” were a trainer.

The four parts will be:

1) Teaching and/or training: some introductory notes and ideas
2) Accomodating different backgrounds and levels in the classroom
3) Hands-on vs. lecture: a delicate balance
4) When things go wrong; or, how to sharpen your wits and thicken your skin

I don’t have sections for comments, but I’d be glad to hear from you directly if you have any comments or questions.

Happy reading!

Back to top


Training 1: Background and ramp-up

Undated

For thirteen years, I made my living as a teacher. I was a member of the Department of Communication at Seton Hall University from 1992 to 2005. In the Fall of 2005, I was starting a year-long sabbatical. I took a long, hard look at where I was at in life, and I decided that instead of taking my sabbatical, I would resign and go full-time into Ruby and Rails consulting and training.

At the time, I was writing Ruby for Rails, so the first several months were more about writing than consulting and training. But then the book got done, and the other stuff started up in earnest. By February of 2006 I was traveling on Ruby and Rails business; and by the end of the year I had visited something like twenty-three cities in North America and Europe, almost all for Ruby/Rails purposes of one kind or another.

I’m in the wonderful position of having turned a hobby—albeit an already passionate, semi-professional one—into a career. But I’ve also turned a career into a career. A lot of what I do nowadays is training; which is to say, teaching. So there’s continuity with my previous career, as well as change.

I’m enjoying the training side of my career because, on the one hand, I’m completely at home in any classroom situation and, on the other hand, it’s really quite different from undergraduate teaching. For one thing, I don’t have to give grades. As my mother, a professor and former Ivy League Law School Dean, has put it, “Grading is the part they pay us for.” I don’t miss it.

Training engagements are also shorter term than college courses. They’re intense, but they typically last five days or less. The intensity is challenging, but I like it. Having fed the history of broadcasting to communication students forty-five minutes at a time, three times a week for thirteen years, I rather like being able to spend entire days on a topic.

Another difference between college teaching and professional training is that in the latter situation you’re not responsible for discipline or character development. I was a rather in-your-face college teacher. I would say things to students—and it wasn’t an act; I meant every syllable of it—like, “When you cheat on an exam, you’re sending me the message that what I have chosen to do with my life is a waste of time!” I was deeply invested in the process.

I still would be, if I were teaching college. And I still am… but not in that way. I’m passionate about the subject matter and the process of putting it across. But I’m not called upon (indeed, not invited) to participate in the moral and ethical blossoming of my students. It’s a relief not to be. To each his own; I think thirteen years of teaching in that milieu was enough for me (at least for the next thirteen years). Right now I’m very happy just being in a room with a bunch of adults who are generally motivated and attentive, and whom I do not have to reprimand when they’re not.

Now and then I used to get a college student who would tell me that they should have a better grade because they paid for the course. (No, really; I did have at least one who said that outright, and many who strongly implied it.) My stock response was: you don’t pay a doctor to tell you you’re well, but to tell you whether you’re well.

In the professional training world, there’s a little more substance to the “The client is always right” axiom. It’s a different situation; each course exists in the first place because a client arranged for it. But I see this as part of the scenery, not a big stumbling block in practice. By the time the course is delivered, there’s a very good chance that it’s what the client wants. In theory, if a client told me in mid-stream that everything had to be changed drastically, I’d have to take the request quite seriously. But it hasn’t happened yet. (I’m probably jinxing myself, but so be it.)

But enough about me. You get the picture: I’m a career teacher who’s shifted careers, and I’m also, for better or worse, someone who thinks a lot about the nature of the process of teaching.

In the upcoming articles in this series, I’ll be talking about specific aspects of training. The focus is on Ruby and Rails training. Some of my comments will, however, be general—because teaching, when you get right down to it, is teaching.

Back to top


Training 2: Handling mixed student levels

Undated

Let’s dive into the deep end. Without any doubt, the hardest thing about the kind of training I do-hardest for the trainer, that is-is accomodating people who come to the class at different skill levels and from different backgrounds.

This problem is not specific to professional training. As I said at the end of Part 1, teaching is teaching. And unless the teaching is one-on-one, you’re going to be dealing with people who differ at least somewhat in what they bring to the table.

It’s also not specific to Ruby and/or Rails. But Rails does tend to attract people from different backgrounds: the coders, the designers, the database people, the managers. Sometimes it’s because everyone wants to know what this new thing is that the company has decided to use. It’s also because Rails cuts a wide path across many layers-MVC, to start with-and at least parts of it are of interest to people who do very different things. That still leaves you, as a trainer, with a potential grab-bag of students, and the need to teach a cogent course.

The problem is often very acute. I’ve taught beginning Rails courses where one or two people out of perhaps five or ten already had Rails applications in production. I’ve had people raise their hands while I’m explaining how to assign a value to a variable in Ruby and ask me a question about reimplementing Capistrano. (Well, that’s a slight exaggeration, but only slight.) I’ve had classes with people in them who had never used a command line, and other people who could pinpoint topics in Rails books by chapter.

It’s not just that some people have read a couple of blog posts and the others haven’t. I’m talking about very different backgrounds. In these situations, you open your mouth to speak, and you realize that there is literally nothing, except perhaps, “It’s raining,” that you can say that can possibly address the needs of everyone in the room.

So you have to make choices. But it’s not all at the moment of opening your mouth. There are lots of things you can do.

1. Before the course

A. Make requirements clear

When you’re describing the course, and discussing the skill level required, you need to use tough love and be clear and firm about the requirements. It’s in everyone’s interest.

For a Rails course it’s important to be clear about the role of Ruby. You can teach Rails to people who know Ruby, or people who don’t-either is OK-but mixing the two is problematic. And for some reason it seems that people are more likely to assume that prior Ruby knowledge is not a factor in a Rails class than they would be to assume that, say, Java knowledge is not a factor in a Struts class. So it’s good to be specific.

B. Try to control the teacher/student ratio

To the extent that you can, keep the teacher/student ratio at 1/15 or higher. Beyond fifteen, in my experience, one starts to hit a critical mass where the amount of help needed expands beyond the confines of the available time.

This is ancient wisdom, of course; universities like to brag about their tiny class sizes and all of that. And with training classes (as with universities, incidentally), you can’t always control it. But if you’re presented with, say, the prospect of providing hands-on, closely coached Rails training for twenty-five or thirty people, see if you can find another instructor—or at least a lab assistant who can troubleshoot installation and other matters so that you’re not doing everything.

2. Have extra material in reserve; encourage extra projects.

When I perceive a major level gap in a class, and sometimes even when I don’t, I encourage students to come up with a Rails project of their own, above and beyond the ones in my workbook, so that they have something to do if they get through the exercises quickly. But it’s by no means just a way to pass the time. Working on a new project from scratch is a logical and beneficial next step for students who have worked through examples. Ideally, everyone would do it in every course. Things don’t tend to work out that way, time-wise; but it’s all to the good if some students do at least get a start on a project of their own.

(And it does help them pass the time!)

3. Enlist the help of the more advanced students.

I’m thinking of situations where, say, someone is clearly over-qualified for the exercises in the workbook, and someone else is struggling. It’s possible that the best course of action is for the over-qualified student to pair up with the struggling one and help them out.

This is a tricky strategy, though. It’s your job, not theirs, to do the teaching. The situation has to be really right before you ask students to teach each other.

But it often is really right. For one thing, teaching something really does help you learn it—so everybody wins. And some people would rather spend the time engaged in an activity with someone else than go off and work on what might be, in fact, just another Rails application out of many that they’ve written.

As the teacher, though, you have to make sure that the result is at least as great as the sum of its parts. You don’t want it to backfire and have both students think you’re trying to brush them aside.

4. Get good at not answering advanced questions.

One of the toughest things is when an advanced student asks questions that are over the heads of everyone else in the class. You don’t want to tell the person that they can’t ask questions, but you don’t want to alienate the rest of the class or make them anxious that the material is zooming by faster than they can grab hold of it.

There’s no hard and fast rule, but I tend to come down on the side of answering these questions very quickly. It’s always possible for the advanced person to ask you later; but you only have one shot at making the dynamics of the classroom work for everyone. I’ll often just tell the student that I don’t want to go into it in depth right now, but here’s a bit of info and let’s talk about it later.

5. Focus on stuff they probably don't really know, like Ruby.

I have a natural inclination to think that everyone else knows more than I do. Call it modesty, inferiority complex—whatever. Ironically, it sometimes makes me come across as sort of a knowledge snob; I’ll make references in conversation to things that I know about that other people don’t, because I assume that if I know about it, so does everyone else.

This quirk is relevant here because in order to become a teacher, I had to overcome it. I had to discover for myself that talking to someone who knows less than you do doesn’t mean you’re talking down to them. If you’re in a room full of undergraduates who have never heard of Jack Benny, then it’s appropriate and teacherly to explain Jack Benny to them. You’re not insulting their intelligence; you’re helping them.

When I ask people in a Rails class how much Ruby they know, it’s no problem getting them to answer accurately. The challenge for me is to act on the fact that I almost certainly know more than they do. And that’s as it should be—and I love explaining the language to them.

I can’t help thinking of one of my favorite undergraduate students ever, a wrestling champ (now a New Jersey State Trooper) who undertook to teach me how to use some of the weight machines at the gym. When he first suggested doing this (after listening to me grumbling about how little exercise I did), I demurred; I didn’t want to impose on him, didn’t want him to waste time, and so on.

His response, which I can still hear in my head, was:

“I’ve got knowledge. What am I gonna do, keep it to myself?”

6. Make it easy to move around the materials (e.g., staged code).

For the main do-as-you-go application in my workbook, I’ve got about 25 code stages. Each one represents the state of the application at a particular point in the book. If a student falls a bit behind, or wants to skip a section they already know about, they can move to a later chapter or section and swap the most recent code stage into their working code directory.

For that matter, if I want to skip over something, I can pick up from a particular code stage and keep going. I don’t normally do this, but sometimes I’ll compress something that was an exercise into a short demo (for time reasons), and having code stages enables me to do get us back on track, and in sync with the application code, easily.

7. Make a virtue of necessity; people might realize that they're
   not going to grasp everything.  Let, e.g., database people
   dwell on that stuff--or on the stuff they don't know, or
   whatever.

Back to top


Training 3: Hands-on, lectures, and demos

Undated

In general, students like the training to consist largely of hands-on exercises. I like it too; you can’t really learn something like Rails by hearing someone talk about it, any more than you can learn the cello by hearing someone describe how to play it.

At the same time, it doesn’t pay to get too obsessed with trimming the time you spend demonstrating and explaining things. Lecturing for a while doesn’t mean you’ve disserved the students—as long as your lecture segments are good.

When you’re dealing with a system, it’s hard to know where to stop. The controller instantiates an ActiveRecord object, which it tries to save, which it may or may succeed in doing because of validations… and if it does, then it gives it to the view, which uses special templating language to embed it, and that looks like this….

The art of not explaining things, at least until it’s really time to explain them, is as important as the art of explaining things. You may have to bite your tongue; it’s not easy, for example, to show people:

def update
  user = User.find(params[:id])
  user.update_attributes(params[:user])
  redirect_to user_url(user)
end

with no validation tests, if you’re used to doing a more full-blown version of updating. You feel like you’re concealing something, or even lying.

But take page from the book of Don Knuth. He warns you up front that he’s going to lie to you. The lying is in the service of the learning. There’s no point giving students a thick, complete account of what’s going on. It doesn’t work; they won’t learn anything.

My cello teacher used to characterize the relation between consecutive phrases with the word moreover. For example, the second Suite of Bach begins with three notes, rising:

Then comes the “moreover” part, leading even higher:

And if that didn’t convince you:

One thing builds on another. You cannot find too many opportunities to bring out this kind of structure, whether in music or teaching or any other art. Don’t just stockpile tips and tricks. Look for the joins, the connective tissue that lets you build one thing on top of another:

Ruby has attributes.

ActiveRecord objects have attributes too.

pause
And they work like all Ruby attributes, except...

... they come from the database column names, instead of names you
invent!

I’ve never been a slide person. I have a hard time creating good slides, and I find most slides in other people’s talks unhelpful. The nadir of slide usefulness must have been the years when my college students had discovered PowerPoint. If I’d kept teaching, I probably wouldn’t have prohibited it. Most of the time, what they did was to cut-and-paste material from the Internet, put it on the screen, and read it out loud to the class. (The cut-and-paste practices are another, fairly disturbing story unto themselves.)

I never use slides in professional training. I don’t even really know whether other people do or not. I don’t. But I do use the projector, mostly for live code demos.

Live code demos always involve a bit of risk. I’d venture to say that’s part of why they’re absorbing. Not that people are rooting for the code not to work—but a little danger adds spice.

Irb is a great tool for live code demos, both in its default form and in its capacity as the Rails application console.

There are certain things I don’t like doing from scratch live. Deployment with Capistrano is one of them. It never seems to go right all the way along. I’ll take the fall for this—I have no reason to assign blame to Capistrano—but I have to live with the fact that live Capistrano demos are, for me, too risky.

So I have a “canned” demo. It’s actually live, but I prepare a lot in advance (it’s the permission settings and passwords that always get me with Capistrano). And I have a list of steps that I consult while I’m doing the demo. Nor do I hide the list from the class; there’s no detrimental effect to their seeing it, and if they think my use of a script like this means that I’m inadequately skilled, then at least now they know!

On TV cooking shows, you often see the chef mixing the ingredients, but then there’s a kind of fast-forward to the finished product, especially with baking. The idea is that you don’t really want to wait in real time for the baking to happen, and even if the show isn’t broadcast live it’s probably being taped with a live audience, and they don’t want to wait either.

The cooking show approach can be very handy for in-class demos. It’s particularly suited to cases where you want to demonstrate how to do something relatively small, and then want to show how it fits into a finished application. Rather than have the students sit through the writing of the whole application, you can write the bit you’re talking about—a data validation directive in a model file, perhaps— and then run the whole application and show that it fails when the data is invalid.

Training isn’t as linear as baking, though. As a session progresses, you’ll keep going back to the “ingredients” level, and then back to the “cake” level. So you can’t always apply cooking show logic literally.

Still, it’s a helpful way to think about the pace of training, and also a reminder that while you’ll be teaching details, you don’t want to get bogged down in irrelevant details. It’s better to jump from a small example to a big application, than to try to fit everything in before you grant a glimpse of a finished product.

Back to top


Training 4: When things go wrong....

Undated

Back to top


Corrected link to The Compleat Rubyist

Undated

Like the space cadet I am, I mistyped a link (twice) in my last blog post. Thanks to Jim James for pointing out the error.

The correct link is… (drumroll)... The Compleat Rubyist.

And the article, with the link now corrected, is here.

Hoping to see many of you at The Compleat Rubyist in January!

Back to top


Training, part 1: Dealing with uneven levels of preparation

Undated

For me, the most challenging thing about training is accomodating people who come to a class from different backgrounds and at sometimes vastly different levels of knowledge.

I remember a Rails class whose members included a participant in that year’s “Rails Day” contest (i.e., a very experienced Rails developer), side-by-side with someone who had literally never written a computer program and never seen a command line. The latter person was a front-end designer, and I have every reason to think she was skilled and successful. But she did not belong in that class.

Given a room with that kind of diverse population, what you can say? I mean, literally, what can you say? What sentence can you formulate that makes sense to everyone in the room, and holds everyone’s attention?

It always comes down to the same dilemma: anything you say is either going to confuse the people who are less advanced, or bore the more advanced ones.

So what should you do? How can you minimize the difficulties going in, and handle them (whether minimal or not) once you’re there?

Here are some ideas.

Make the requirements clear in advance

When you’re describing the course to the client, and discussing the skill level required, show some tough love: be clear and firm about the prerequisites. It’s in everyone’s interest. Don’t try to be all things to all people. Use terms like “not suitable” or “too advanced” when discussing who from their team you think should not be in the course. Use them politely, but use them.

Prerequisites don’t have to be fine-grained, but they do have to be clear. “Everyone in the course should already be experienced with at least one object-oriented programming language” is an example of a reasonable pre-requisite. So is “The participants need to be at least somewhat comfortable in a Unix-like environment.” You don’t need to know whether they know all the command line options for xargs. You just need to establish the basic requirements.

If you’re teaching Rails, address the role of Ruby. You can teach Rails to people who know Ruby, or people who don’t—either is OK—but mixing Rubyists with non-Rubyists is problematic. It’s possible that potential participants won’t realize that Ruby knowledge is a factor, so it’s good to be clear.

As it is with the Ruby/Rails relationship, so it is with any case where you’ve got one technology built on another. Make sure you’re clear about the expected starting-point.

Stick with what got you there!

The starting point and frame of reference always has to be the curriculum you’ve promised to deliver. You can’t zoom ahead just because the material is familiar to someone who’s already done it, and you can’t spend more than a small amount of time on remedial instruction for those who aren’t prepared.

If the whole class is at the same level, and the level they’re at isn’t the level you were expecting, then of course you can make a big, overall adjustment. I remember doing that with a programming team who had much more experience than I’d expected. They were too polite to come out and say that they were too advanced for the curriculum, but it wasn’t hard to figure out. (When you set a challenge like implementing attr_accessor, and they all do it correctly in about two minutes, that’s a clue.) So we changed gears and spent the remaining days on more advanced topics and code critique.

But given the true mixed-level situation, you have to be guided primarily by what you have promised to deliver.

Try to control the teacher/student ratio

To the extent that you can, keep the teacher/student ratio at 1/15 or better. Beyond about fifteen (more or less, depending on the subject matter and pace), you hit critical mass: the amount of help needed by the students expands beyond the confines of the available time for one instructor, so you fall further and further behind. This is ancient wisdom, of course. Universities like to brag about their tiny class sizes and all of that. And with training classes (as with universities, incidentally), you can’t always control it. But if you’re presented with, say, the prospect of providing hands-on, closely coached Rails training for twenty-five or thirty people, see if you can find another instructor—or at least a lab assistant who can troubleshoot installation and other matters so that you’re not doing everything.

Have extra material in reserve

Try to have some ideas for extra projects up your sleeve, above and beyond any in your stated curriculum, particularly for students who are too advanced for the course. Bring a few books with you, and if someone isn’t feeling challenged enough, point them to a chapter that you think they can learn from. They won’t feel shunned; they’ll feel relieved. (Besides, the whole premise here is that the too-advanced person shouldn’t be there in the first place, so anything you do to help them not be bored is in their interest.) In the same vein, put up a webpage somewhere with some links for further study—and when you choose those links, try to choose ones likely to interest people who are somewhat too advanced for your curriculum.

Enlist the help of the more advanced students

I’m thinking of situations where, say, one student is clearly over-qualified for the exercises in the workbook, and another student is struggling. It’s possible that the best course of action is for the over-qualified student to pair up with the struggling one and help them out.

This is a tricky strategy, though. It’s your job, not theirs, to do the teaching. The situation has to be really right before you ask students to teach each other.

But it often is really right. For one thing, teaching something helps you consolidate your own knowledge—so everybody wins, including the student-teacher. And some people would rather spend the time engaged in an activity with someone else than go off and work on an application or read a book.

As the teacher, though, you have to make sure that the result is at least as great as the sum of its parts. You don’t want it to backfire and have both students think you’re trying to brush them aside. Be circumspect about this option, but keep it in mind for the right situation.

Master the art of not answering questions

Of course I intend that header as an attention-grabber. In general you want to answer questions. But what about questions from either the too-advanced or the inadequately-prepared students?

When I get a too-advanced question, I usually answer it quickly and, if need be, incompletely. I don’t want to digress too far from the curriculum—and, above all, I don’t want to make the less advanced students feel anxious because they can’t follow what I’m saying. You can always ask the advanced student to talk to you about their question later; but you only have one shot at making the dynamics of the classroom work for everyone. So answer the question quickly; offer to go into it privately later; don’t get into a lot of examples and demos based on the question (that can really make the other students feel abandoned); and move on.

Questions that reflect inadequate preparation are harder to deal with. In fact, it may be through such questions that you find out about the preparation-level problems in the first place. This may be a good time to consider a temporary ad hoc “buddy system,” where someone else in the class helps the person, assuming it’s something that can be communicated relatively quickly (like how to start Ruby from the commandline, creating a MySQL database from scratch, etc.).

Make it easy to move around the materials (e.g., staged code)

For the main do-as-you-go application in my workbook, I’ve got about twelve code snapshots. Each one represents the state of the application at a particular point in the book. If a student falls a bit behind, or wants to skip a section they already know about, they can move to a later chapter or section and swap the most recent code stage into their working code directory. For that matter, if I want to skip over something (if time is shorter than I’d planned), I can pick up from a particular code stage and keep going. I don’t normally do this, but sometimes I’ll compress something that was an exercise into a short demo (for time reasons), and having code stages enables me to do get us back on track, and in sync with the application code, easily.

Talk to the person in charge

You’ll probably have a discussion at the end of each day with the manager who set up the training. You should absolutely bring preparation-level issues to that person’s attention. Ninety-nine percent of the time, they’ll say, “Yeah, I was afraid of that. I just didn’t want to leave those people out”, or words to that effect. The manager knows the team. None of this is going to be a huge surprise.

Be sympathetic, though. They didn’t do this to make your life hard. At worst, they just didn’t think it through in terms of preparation and were eager to get the most value out of your skills. Everyone’s acting in good faith.

Sometimes, the manager will take someone out of the training after the first day. I always feel a pang of guilt at this—but I shouldn’t, and you shouldn’t. It’s a correction that will make things easier and more productive for everyone, including the person who shouldn’t have been in the training in the first place.

Summary

Handling the mixed-level classroom successfully is not easy. You need to stay alert and to keep applying energy to the situation to make it as good as it can be for everyone, while delivering what you promised to deliver. A mixed-level group requires agility and adaptability, but with structure.

Some of the training companies I subcontract with do Likert scale evaluations (“Strongly agree, Agree, Neutral…”—that kind of question). One of the questions is often about the pace of the class. In a mixed-level class, I don’t expect everyone to say the pace was perfect. I aim, though, for the best result possible. I want the curve to peak at “Perfect”. I want to look at it and conclude that if it were displaced to the right or the left, it wouldn’t be as good a result.

Then I know I’ve done my best.

Back to top


Training: Introduction to a series of articles

Undated

What follows this Introduction is the first in a series of instrutional articles about training: specifically, technical training and, even more specifically, training computer programmers.

I’ve been making most of my living as a Ruby and Ruby on Rails trainer for four years. Before that, I spent thirteen years on the faculty of the Department of Communication at Seton Hall University, teaching media history and research to undergraduates. So teaching, in one form or another, has been much of my life story in recent decades.

In 2005 I changed careers: I left the academic world and started to earn my living as a Ruby consultant, author, and trainer. I’d been programming computers since 1972 (with some gaps, but pretty steadily since 1990), and I’d become a Ruby and Ruby on Rails expert. I had a book contract (Ruby for Rails). By 2005, computer stuff was exerting a much greater pull on my attention and passion, by then, than my academic work was. I had a sabbatical leave coming up, and little enthusiasm for doing the kind of research that the university would have expected of me. So I resigned at the beginning of my leave, in Fall 2005, and moved on.

I figured I’d finish Ruby for Rails and then get a programming job. I did finish the book, but I never got that job. Instead, I set up a one-man consultancy, Ruby Power and Light, and started taking on short-term contracts—and a lot of training jobs. I trained and trained. In 2006, I traveled to something like twenty-three cities, from California to Sweden, training people in Ruby and Rails.

And it’s continued from there. It’s been an extraordinary four years, and I hope it keeps up.

In this series, I’ll be focusing on the professional/technical training side of things. Even if you’re not a Ruby/Rails trainer, you’ll find points of interest. All of the anecdotes and examples I adduce, however Ruby-specific, carry some kind of general message about the teaching process.

As you’ll learn if you read this series, I’m the kind of teacher who not only teaches but also thinks deeply and widely about the process of teaching, and who likes to share insights. And I don’t draw any kind of sharp line between “teaching” and “training.”

It’s all teaching.

Back to top


"Advancing with Rails" gets off to a fine start!

Undated

I’ve now taught my new course “Advancing with Rails” twice, once in New Jersey and once in Berlin, Germany. It’s gone very well; I think it hits a sweet spot.

The target audience are people who’ve done a good amount of Rails—written apps, read books, quite possibly have things in production—and who have one or more of the following goals:

That last one is subtle, but important. It’s one of the reasons I don’t call the course “Advanced Rails”. Part of the goal is to learn how to adapt to the fact that Rails is in development, growing, a moving target—however you want to put it. It’s not like learning, say, advanced TeX, where you can come up with an unchanging list of “advanced” topics and learn them. Both Rails and Ruby are growing, living things. That’s part of the fun, and part of the challenge.

Advancing with Rails has a definite curriculum, and a definite agenda. At the same time, I like to keep it a bit fluid. Rails courses attract people with very different backgrounds and different starting-points—and if that’s true even for beginner courses (which it is), it’s all the more true for intermediate and advanced ones. Everyone has different questions; everyone has differently developed “Rails muscles”.

As I’ve said at the beginning of both “Advancing” classes: At some point during the course, you’ll hear something that you already knew—but you’ll also hear a lot that you didn’t know, and you’ll get to work with an interesting group of like-minded developers with a lot in common as well as complementary backgrounds.

It certainly keeps it fun for me!

If you’re interested, look on http://www.rubypal.com for upcoming dates (or contact me about on-site training).

Back to top


Training, part 3: Advice on lecturing and topic presentation

Undated

lecture with a z-axis

Back to top


The night before

Tue Jun 20 21:32:00 2006

Tomorrow morning I’m off to Chicago for RailsConf, and from Chicago on to Toronto to do some Rails training. So it seemed like a great evening to inaugurate DABlog.

I’ve never been a fan of the term “blog”, so I’m doing an end run around it by naming this log after myself. Anyone who wants to think of it as “Da Blog” may do so, and I get to think of it as the log of David A. Black. So everyone is happy.

Ruby rules in my life, these days. I’m having a great time: training, programming, consulting, and enjoying the first months in the life of my new book, Ruby for Rails: Ruby techniques for Rails developers. And I’m as involved as ever (and then some) with Ruby Central, Inc., the non-profit Ruby support organization that produces RubyConf and RailsConf, and of which I am a founder and director.

It’s a great feeling to have such a full plate and to have it all be connected with something I love so much.

The Ruby/Rails convergence in Chicago this week promises to be great (other than the fact that the hotel doesn’t have a reservation for me, but whatever). Look for many reports, all over the place, as the event progresses!

Back to top


Submit!! (a proposal for a RubyConf talk, that is)

Thu Jun 22 07:18:00 2006

We (that’s “we” as in Ruby Central) have opened up the presentation proposal process for RubyConf 2006.

Now we need proposals!

You don’t need to be a Ruby core developer, author, guru, whatever…. We welcome proposals from anyone and everyone who has about 45-50 minutes worth of ideas, code, plans, experiences—anything Ruby-related. And part of that 45-50 minutes can (and even should) be questions and discussion.

So please propose a talk, or contact me if you have questions.

The deadline is June 30, 2006. (That may get flexed a little, but not much.)

Back to top


Modeling many-to-many: I guess I was right the first time....

Sun Jun 25 08:20:00 2006

Last night, David Heinemeier Hansson delivered the final keynote address at RailsConf 2006. He talked about the mapping of HTTP methods (get/post/put/delete) to CRUD operations, and gave us a guided tour of some of the facilities awaiting us in near-future Railses for layering the various CRUD-esque suites of names and actions on top of each other.

I won’t try to encapsulate the whole talk, which I’m sure will be made available (and I’ll make up for my laziness later by trying to find it…).

One thing of particular interest that David talked about was the modeling of many-to-many associations; that is, representing the associations themselves as models, rather than just as two-key records. This is familiar to users of recent Rails releases in the form of things like:

class Section < ActiveRecord::Base
  has_many :enrollments
  has_many :students, :through => "enrollments"

where you’ve also got:

class Enrollment < ActiveRecord;:Base
  belongs_to :student
  belongs_to :section

and Enrollment may have all sorts of attributes of its own, beyond the two foreign keys. David’s chief point about this was that having an actual model for the convergence of two other models makes it much easier not to overload the two original models with namespace functionality and asymmetrical, lop-sided operations.

So if you have an Enrollment entity, you don’t have to do things like:

class StudentController < ApplicationController
  def enroll_in

or

class SectionController < ApplicationController
  def enroll_student

Instead, you have:

class EnrollmentController < ApplicationController
  def create

In other words, you fall back on vanilla CRUD. In fact, the way David presented it was almost the other way around: by sticking to the tenet that (almost) everything you want to do can be represented by CRUD operations, and experimenting with keeping that principle as an invariant, you’re forced to come up with new ways of doing things that are actually better than what you might have done before.

But wait…. Are these ways so new?

My first Rails application was a simple message-board tool, for private student/teacher communication. I had to grapple with the question of how to model messages. To whom did a message belong? Sender? Receiver? Student? Teacher? Which controller should deal with creating and updating messages?

The solution I hit on was very similar to the kinds of things DHH was talking about last night: a Correspondence model. A Correspondence belongs to a sender and a receiver. It also has many messages, and has (or has room for) as much further embellishment as one wants.

I didn’t have :through, of course (this was in 2004), but it wasn’t too hard to navigate through the tables and find what I needed. Nor did this solve all the design problems…. There was still the matter of mapping the sender/receiver roles to the teacher/student roles, and dealing with certain asymmetries in that realm while trying to make everyone a User object.

In any case, it’s kind of gratifying to see Rails conventions moving in something very like the direction I took on my first Rails app. Mind you, Rails was perfectly capable of accomodating this model from day 1; it’s not that I came up with some non-Railsy way of modeling that Rails later realized was OK. Still—it’s nice to see it all becoming more and more established and doable.

Back to top


The agony and the ectasy (of RubyConf proposals, that is)

Sat Jul 1 09:16:00 2006

Wearing my Ruby Central director’s hat:

We’ve received a record-smashing 73 talk proposals for RubyConf 2006. That’s more than twice the number we got last year—and last year was about double the previous high.

It’s absolutely great to see all the interesting work that’s being done. I’m feeling buzzed and inspired in a way I usual am after RubyConf.

It’s also agonizing to have to select not much more than a handful of talks. We’ll do it, and the program will be great, but it’s not easy.

RubyConf is a gem of a conference: small (not tiny, but small compared to many), one-track, intense, fun, collegial, coherent, unified. We want it to stay that way; it’s an event many people look forward to and treasure.

The fact that we’ve received 73 proposals doesn’t change that—but it does set us the challenge, as an organization, of looking for more and more ways to get the community together and to let people know what others are doing.

Back to top


Why I am conservative about changes to Ruby

Sat Jul 1 12:18:00 2006

I have a probably well-deserved reputation for being conservative about changes to Ruby. I’ve even been accused of wanting to kill Ruby (or thinking it should be dead, or some other subtle variant of the charge) because I’ve opposed this or that idea.

I am conservative about changes to Ruby—not because I think Ruby in five years should be exactly the same as Ruby today, but because I think the number of changes Ruby needs is tiny, compared with the number of suggestions that are made.

The biggest question I have about future versions of Ruby is…

Have we reached the non-line-noise saturation point?


I estimate that 95% of all changes suggested for Ruby (counting RCRs and also casual discussion on ruby-talk and elsewhere) involve adding new punctuation. Many of them make Ruby look noisy and punctuation-heavy. Taken together, they are (or would be) a full-blown concession to line noise.

Why is this? Didn’t a lot of us take to Ruby in large part because it didn’t $look(&:like) -> @@this;; ?

I’ve started wondering whether maybe Ruby has reached a saturation point, where all that can be done without excessive line noise has been done. Maybe if we want Ruby to stay clean, we simply can’t have every imaginable possible nuance of scope, namespace, symbolic reference, and and left-to-right logic forking. Maybe it’s a choice.

That’s fine with me. I’m not big on looking at Ruby as a “Swiss-army chainsaw”, the way people look at Perl. I’m happy looking at it as the kind of blender that master chefs like to use: three or four speeds, rather than fifteen or twenty. You can do anything with it, if you know what you’re doing.

I trust Matz not to turn Ruby into a bunch of uppercase numbers. (The -> lambda arrow has been dropped from the development branch, which is great news.) Assuming he doesn’t, I think it will be because he doesn’t introduce a lot of the changes being contemplated, not because they don’t use punctuation. A lot of them do. I think that may be a sign of the saturation point I’m talking about.

If I’m right, I hope we’ll just live without some of the language-level special-case handling.

Back to top


10/10 review of Ruby for Rails on Slashdot

Wed Jul 12 17:35:00 2006

My book Ruby for Rails was very favorably reviewed today on Slashdot. The review ends:

This is a great book, that’s very easy and enjoyable to read. It’s a stunningly well written explanation of real-world Ruby skills for Rails development

The reviewer, Simon P. Chappell, really gets the fact that this is a Ruby-skills book for Rails practitioners—as opposed to a full-blown Rails guide or a full Ruby reference work. When I conceived and wrote the book, I knew I was creating a whole book category, not just writing a book in a category. And it’s great to see that effort understood and appreciated.

I believe this review will help spread the word about what the book is trying to do. And, in turn, it will be more widely read, and its goal of raising the level of Ruby mastery among Rails developers will be increasingly met! Win-win!

Back to top


The laptop stratum: thoughts from (half of) OSCON

Thu Jul 27 10:25:00 2006

I’ve been here in Portland since Saturday, which means I got here early for OSCON (happened to be traveling in this part of the country anyway), and I’m leaving today, which is a couple of days early (have to do stuff back home and then come back to the West Coast next week).

It’s been interesting and fun. I’ve hung out a lot with many of my fellow Rubyists, including Pat Eyler, Jim Weirich, the Prags, and Phil Tomson; surreptitiously (or otherwise) watched people leaf through my book at the Powell’s Bookstore table in the conference venue; had dinner on Saturday with conference organizer Nat Torkington and a couple of his friends; went to FOSCON last night; and generally had a great time.

Jim Weirich and I were talking yesterday about the culture(s) of the event, and of the various communities that make it up. There’s certainly a lot of potential interest to social scientists and analysts.

One thing I find particularly intriguing is the undercurrent of laptop use, especially during the presentations themselves. This isn’t school, so I’m not out to stop people from doing it (as I was during my professorial days; I didn’t allow laptops in the classroom at all). What interests me about it is wondering what’s actually getting done. People talk at OSCON and other conferences about synergy, networking, and all the rest of it—and I have a suspicion that a lot of this goes on in laptop sessions during talks. But when it takes that form, it’s not celebrated. It’s accepted (or at least tolerated) as a corollary of the existence of laptops. But it’s actually a bit taboo, I think, to make too much of it.

I wonder…. I remember starting to learn Rails by sitting at a conference talk and conducting a private chat session with David Heinemeier Hansson, who was sitting one row behind me and coaching me through the rudiments of the MVC architecture. That was a real and substantive moment in my development as a developer. I wonder what else is going on. I have a feeling the laptop stratum is at least as rich as the “BOF” sessions and acts of hallway networking, when it comes to personal and community growth.

Back to top


Regional Ruby Conference grants from Ruby Central

Fri Jul 28 13:09:00 2006

Ruby Central, Inc., parent organization of RubyConf and RailsConf, has announced the 2006 Regional Conference Grant Program. Ruby users groups can get grants of up to $1500 for expenses connected with putting on a regional conference.

It’s a timely program (if I say so myself, being one of the people behind it). RubyConf is a gem of a conference, and we want to keep it that way—but that also means it can’t be all conference-related things to all conference-going people.

We’re aiming to become Ruby Centrifugal. (Not literally, but metaphorically.) A distributed effort makes sense.

So if you’re involved in a Ruby users group - or even if you’re not, but feel motivated to try to put on an event - have a look at the guidelines (link above) and let me know what you think (dblack@rubypal.com).

Back to top


Special offer for Ruby users groups, from Ruby Power and Light

Sat Jul 29 12:25:00 2006

My consultancy, Ruby Power and Light, LLC, has an offer going, whereby a local Ruby users group can fly me in, have me talk at their meeting, and arrange a Ruby and/or Rails workshop (non-free) to be taught by me, to offset the expenses.

Details at Ruby Power and Light.

Back to top


No more comments for the moment

Thu Aug 10 20:07:14 2006

Sigh—I have to suspend comments, at least for now, because of spam. If it becomes possible to resume them at some point, I will.

Back to top


No, really: my book is Ruby for Rails!!

Sat Aug 12 12:14:46 2006

I got the weirdest review over on Amazon.

The reviewer gave my book one star out of five—which I can live with (though I was fond of the half star in my four-and-a-half, and now I’m down to just four). Along with the one star was a review, the gist of which was that the reviewer had only read a few chapters, because he (or she; I’ll say he) realized my book wasn’t what he’d been looking for.

Specifically, my book bums this person out because it isn’t a step-by-step guide to Rails application development for people already familiar with other MVC frameworks. That’s what this reader had hoped it would be - based on what, I can’t say (he says he didn’t read the earlier Amazon reviews, and apparently didn’t read the title either…) - and apparently his having been wrong about the content of my book is, in his view, grounds for giving the book one star.

It’s weird when someone gets mad at you because you didn’t write a particular book. It would actually be easier to deal with disgruntlement at what my book is, rather than what it isn’t.

The reviewer does take the time to say that the book is verbose and rambling. The main example of this is my discussion of command-line switches for the Ruby interpreter.

But I want to talk at some length about command-line switches. If I had written the hypothetical Rails instruction manual that this person thinks I should have written, then perhaps that section would not have pulled its weight. But in my book - my book, not some imaginary replacement for my book - it actually makes sense to include it.

The bottom line is:

If you are involved in Rails development and want to learn more about the Ruby programming language - principally, but not exclusively, to help you understand Rails better and write better Rails applications - read my book! If you’re not sure, you can get some sample chapters at the book’s website at Manning.

And it’s been said that Ruby for Rails is a great Ruby intro, whether you’re interested in Rails or not. Far be it from me to take exception to people’s judgments….

Back to top


Home from the Michigan Ruby Conference

Sun Aug 27 15:23:00 2006

“Home” is an exaggeration; I’m actually in the Grand Rapids airport.

The Michigan conference was very successful. There were about 65 people there. It was a one-track event, with three talks in the morning and six in the afternoon—a demanding but very rewarding day.

Congrats to Zach Dennis and the rest of the organizers for putting together an exemplary regional ruby conference!

Which reminds me….

You (dear reader) should consider putting together a regional Ruby conference where you live, and apply for a Ruby Central Regional Conference Grant to help with expenses. I won’t say it isn’t a lot of work to put on even a small conference, but it’s definite doable, and it’s a way to do something really cool and constructive.

Keep in mind that the Regional Conference Grants are only intended to offset out-of-pocket net expenses for the organizers. That means that if you get sponsorship, the maximum possible amount of the grant goes down, possibly to zero. Still—if a conference takes place, that can’t be bad!

Back to top


Free Rails workshop in Malmo, Sweden!

Mon Sep 11 10:29:00 2006

I’m going to be conducting a free (but limited enrollment) Ruby on Rails workshop in Malmo, Sweden, on September 17th.

Details the Polar Rose website.

Back to top


RailsConf Europe and beyond....

Mon Sep 18 05:08:00 2006

As you may already know, the first RailsConf Europe was a big success. Ruby Central had the easy job: we were in on the planning at a fairly general level, and we chose the talks. Credit for actually arranging and running the even goes to Wendy Devolder and her team at Skills Matter, the London-based training company that teamed up with us for this event.

I didn’t go to as many talks as I would have liked to, as I was doing event-related things much of the time; but I went to all the keynotes and enough sessions to be very impressed. I was also taking mental notes on the fact that the keynotes, which were attended by about 300 people, didn’t feel like they were mobbed or overcrowded. This has a bearing on my thoughts about the upcoming RubyConf 2006, which is going to have upward of 300 people in attendance and one track.

I’m now in Copenhagen, having given a Rails workshop in Malmo, Sweden, yesterday. The workshop, hosted by Polar Rose, went very well. Afterwards I checked into my hotel in Copenhagen; and as I was getting in to the elevator, I heard a voice call, “David!” Usually it’s safe to ignore that, in cities where you don’t know anyone, since it probably isn’t you—but in this case it was me, and the person calling me was David Heinemeier Hansson. He’s staying at the same hotel, it turned out.

And I, and I think also DHH, will be going to tomorrow evening’s meeting of the Copenhagen Ruby Brigade, which I’m looking forward to a lot.

Back to top


Dinner for three

Sun Sep 24 12:03:33 2006

Now this was fun.

In London, the past Wednesday evening, I had dinner with two old friends: writer and critic Nicolette Jones and literature scholar-turned-banker Gurdon Wattles.

I met Nicolette in 1981, when I was a senior at Yale and she had come over to do a year at Yale as part of her graduate work in English at Oxford. So we’ve known each other for about 25 years. Nicolette and her family are among the friends I spend the most time with in London; indeed, I’ve spent more time with them over the years than with any number of my friends who live in, say, New York, less than fifty miles from me.

Gurdon I’ve known for forty years. We met when we were seven. My family was living in Cambridge, England, for several months, and I was going to school there. Gurdon and I became best mates at school. Over the years we’ve seen each other, either with our families or on our own, only three or four times, the most recent being in 1988. It’s only in the past few weeks that we’d been back in touch at all.

Here’s the funny thing, though: Nicolette and Gurdon, quite independently of me, have been good friends since their university days back in the late seventies or so. How did we figure out that we all knew each other? It was back in 1982, in the Spring of the year that Nicolette spent at Yale. She and I were sitting across from each other at a table in a student dining hall, and she was writing a postcard. Postcards are fair game, right? So I glanced at it, and saw that it was addressed to my old friend from Cambridge, Gurdon Wattles. That broke the ice, you may be sure.

Now it’s 2006, and the three of us were together in one place for the first time. And it was really fun. A long time in the making, and an absolute delight. More of the same to follow, I hope!

Back to top


Have fun (without me) at RubyConf!

Wed Sep 27 15:55:02 2006

I’m going to miss RubyConf, for the first time ever.

This is happening for two reasons. The second reason erases the first—that is, it would be sufficient in itself.

The first reason is, or was, that I accidentally scheduled a training course in conflict with the first day of RubyConf. That was just dumb—though I’m happy to be doing the course, which is a 4-day Ruby/Rails intro in Alexandria, VA>

The second reason is that a dear friend of mine is having her 80th birthday party on October 21, the second day of RubyCOnf. So that pretty much takes me out of the picture.

It feels weird to miss a RubyConf. I’m one of only seven people who have been to all of them. Even Matz has missed one. (He had a good excuse: his wife was about to have a baby.)

But it’s definitely in a good cause. And you’ll all be very well looked after, as always, by Chad, Rich, and the hotel staff.

Back to top


[Postponed] One-day Rails intro workshop in Toronto, December 15

Sun Nov 19 16:34:22 2006

[This event got postponed, hopefully to take place in Spring 2007.]

I’m going to be conducting a one-day Rails workshop in Toronto on December 15. It will be an introduction to Ruby language essentials and the Ruby on Rails framework.

Topics will include:

The cost is $375 (Canadian). More information and registration here..

Back to top


More A than R: reconsidering the "new" AR object

Sat Dec 23 08:57:00 2006

I’ve been noticing that this is becoming a common controller idiom:

def new
  @person = Person.new
end

Of course it’s for the sake of the view—specifically, for the benefit of simply_helpful, which lets you do:

<% form_for(@person) ... %>

and will create the right form for you, with the right HTTP method, based on whether @person is a new record or an existing one.

That “new” method, though, bothered me the first time I saw it, and it still does. What I don’t like about it is that it creates a new Person object, while having no intention whatever of saving that object.

Of course there’s no rule that says you have to save AR instances. But doing Person.new just so that you have an object that can answer a couple of questions about itself is overkill. Seeing that code gives me the same feeling I get when I see global variables (or even instance variables) used where a local variable would do. It works, but it’s a loose fit.

It reminds me of, say, walking into a health club and buying a membership so that you can go inside and use their bathroom once. The membership system is in place, and it will serve that purpose, but it wasn’t put in place for that purpose and it’s manifestly a kind of better-than-nothing solution to the problem being solved.

What we’ve got, I think, is the tail (the view) wagging the dog (the controller) a bit too much. I have no problem with the underlying idea of having the form creation be intelligent, but I’m not comfortable with this idiom for doing it.

I’m also willing to bet that someone—a lot of people, I would guess—see this:

@person = Person.new

and have trouble getting a handle on the fact that this has nothing whatever to do with the fact that, at the end of the whole process (new plus create), a new Person will have been created. It’s almost like this new Person is pretending to be THE new Person.

So, what are some alternatives?

I started out by thinking about flipping the whole thing so that the instance variable was no longer at the heart of it. (The docs for form_for do say, after all, “The big news is that form_for allows us to more easily escape the instance variable convention” :-) I ended up kind of reinventing what already exists. Also, Dave Goodlad pointed out that a benefit of querying an actual Person object, even a new one, is that you can pick up default values for attributes (at least those defined via overrides in the model).

My next thought—and this is what I currently favor—is to add a “proto” constructor to ActiveRecord. So instead of Person.new, you would do:

@person = Person.proto

The proto-person would essentially be an unsaveable Person object. Its reason for existence would be exactly the use to which you’re going to put it. When I see Person.new in this context, I always think: this is here because there’s no good way to do this, and creating a new instance is the closest thing available. My reaction to that is: if we’re going to be using a lot of AR objects that are more A than R, let’s design that into the system. The “proto” constructor would be a way to do that.

I also consider it more in keeping with the somewhat anomalous position of the “new” action in the RESTful context. new serves as a kind of table-setter for create. The main event hasn’t started yet; this is just a preliminary step. Viewing it in that context, I think the somewhat anomalous nature of the proto-Person is in fact exactly right.

Criticisms include:

I disagree with all of them, obviously, but I thought I’d list them just to indicate I’m aware of them.

Back to top


Enough already with freaking out over people's sex

Wed Jan 3 19:30:58 2007

Just spotted on the on-screen program guide for Cablevision: “When a female Secret Service agent is killed, detectives investigate clients of her husband, a well-connected lobbyist.”

Years ago, there was a kind of riddle or puzzle in circulation—something to the effect of:

A father and son are in a car crash. They’re taken to the hospital. The doctor comes into the room, looks at the boy in the bed, and exclaims, “My son!” How can this happen?

I’d like to think that that riddle is obsolete. But I wonder. Apparently television blurb writers still feel the need to specify that a character is a female Secret Service agent, not just a Secret Service agent, even though reference is made to “her husband” in the same sentence.

I can understand alluding to a character’s sex—or ethnicity, age, sexual preference—if it’s materially relevant to the plot. The dramas of our culture involve these things, and there’s no reason that dramatic representations can or should be expected not to revolve around them. If an episode of a show is about child pornographers, I don’t expect the description not to mention children. If it’s about a serial murderer of gays, I don’t expect the description to be poker-faced on the matter of who the victims are.

So there are cases where the issue is the message, so to speak.

I don’t know, because I haven’t seen it, but I suspect the “female Secret Service agent” episode isn’t one of them. But just for the sake of argument, let’s say it is. That still leaves the question: what the hell could the “her” in “her husband” mean, except that the agent is female? Even if the plot does hinge specifically on the femaleness of the agent, “her” conveys that femaleness completely and unambiguously. There is literally no possible reason for the presence of the word “female” in that blurb.

I dislike the implication that it’s unacceptable to keep the femaleness of a Secret Service agent unrevealed even for a handful of words. That’s no good. If people find themselves thinking it must be a man and then revising their view later in the sentence, so be it. They should have to do that, if they assume that “Secret Service agent” means male agent, or that “teacher” means white teacher, or that “man” means heterosexual man.

Enough already with these regressive habits.

Back to top


Will trade Ruby/Rails tutoring for website design work!

Wed Jan 3 20:35:39 2007

Update

I’ve come to an agreement with someone. Thanks to those of you who offered your services. I hope I’ll meet up with many of you around Ruby/Rails-space.


(Old announcement)

My company website needs a bit of, shall we say, a facelift. It basically conveys the info I want it to, but it’s pretty non-descript and somewhat inconsistent across sections.

I’d like to trade hours of Ruby/Rails tutoring, at any level, for hours of website design work, on a 1-to-1 hour ratio. I’m envisioning something in the 3-5 hour range on both sides.

If you’re interested, let me know. I do have some requirements and expectations (like that all pages will validate—I’m not sure my current ones do, but if they don’t that’s something I want to fix and not be complacent about—and that things are visually interesting but not oversaturated and all info is as accessible as possible). But I’m also ready to look at real designs and not just impose my own somewhat limited design imagination on the project.

Please email me at dblack at wobblini dot net if interested in chatting about the possibility.

Back to top


Meta, shmeta: learning Ruby horizontally

Sun Jan 7 10:20:49 2007

One of the great accomplishments of Ruby is that its object and class model bring about a wonderful unity and simplicity. Even things that might seem like they should be hard or obscure are actually very transparent, once you have the hang of how the model works.

Unfortunately, there’s a trend toward drawing an increasingly sharp line between regular programming and “metaprogramming” in Ruby discussions, where metaprogramming is understood to mean… well, I’m not sure what it’s understood to mean, the way it’s getting used in connection with Ruby, and that’s the problem.

There’s no natural separation between programming and metaprogramming in Ruby, and no reason to make life harder by breaking them apart. The thrust of Ruby’s design is to dissolve complexities, so that even things that appear to be “wizardly” or full of “dark magic” actually make perfect sense in terms of a relative small number of underlying language principles.

I’m not saying it’s all a snap to learn. But I do consider it counterproductive to posit some kind of special barrier or fortification surrounding a particular set of Ruby programming techniques. Learning Ruby isn’t like scaling a mountain. It’s more like exploring a plain, with interesting features and a distant but very attractive horizon. One thing leads to another, but not in a way that requires you to fight gravity to get there.

Horizontal learning: class_eval and class

You can get a feel for this horizontal, energy-efficient way of learning Ruby by looking at pairs of closely-related techniques, where one is the kind of thing you learn on the first day of studying Ruby and the other…isn’t.

A good example of such a pair is the class keyword and the class_eval method. class_eval often comes up as an example of a metaprogramming technique, and therefore as something obscure and difficult and wizardly. It isn’t. Let’s probe it systematically, and in context.

We’ll start with the class keyword, one of the bread-and-butter techniques of Ruby—the basic:

  class MyClass
    # stuff
  end

Certain things happen when you start a class definition block:

All of this is easily visible and verifiable. Here’s a little testbed:

  # Just for demo, we'll create a local variable in the
  # outer scope.
  x = 1

  # Now the class definition block.
  class Teacher

  # Examine the value of self
    puts self

  # Try to examine the local variable x -- but it will
  # raise an exception, because we're in a new local scope
  # (so we rescue the exception).
    puts x rescue puts "x is from a different scope!" 

  # Define some instance methods.
    def initialize(name)
      @name = name
    end
    def name
      @name
    end
  end

  # Run some demo code.
  t = Teacher.new("David")
  puts t.name

The output from this little program is:

  Teacher
  x is from a different scope!
  David

Everything works as expected.

Now, let’s look at class_eval.

class_eval is a method, rather than a keyword. You don’t do this:

  class_eval Teacher   # No!

Rather, you call it as a method, and give it a code block:

  Teacher.class_eval do
    # code block!
  end

Now, rather than get all panicked about how this is “metaprogramming”, let’s look at what’s actually happening, and why.

As we’ve seen, the class keyword (class Teacher) brings about certain conditions involving self, scope, and the effect of defining methods. So let’s use the same criteria to examine what happens with class_eval:

  y = 1
  Teacher.class_eval do
    puts self
    puts y rescue "y is from a different scope!" 

    def subject
      "History" 
    end
  end

  t = Teacher.new("David")
  puts "#{t.name} teaches #{t.subject}." 

(We’ve got all teachers teaching history, but we’ll live with that for the sake of the demo.)

When you run this code, you get:

  Teacher
  1
  David teaches History.

What does this tell us? It tells us that when you use class_eval:

Consequently, you now know that if you want to add instance methods to a class while still retaining access to local variables in the outer scope, you should use class_eval. If you don’t need those local variables, you can use the class keyword.

There’s a little more to it….

There are of course more differences between class and class_eval (including the fact that class_eval can operate on a string as well as a code block, and that it’s very handy for anonymous classes). But note that as we study class_eval, we’re not in a different universe, or higher up a mountain and running out of air. We’re actually still playing in the same ballpark we were playing in when we looked at the class keyword.

The relation between class and class_eval, from the point of view of someone interested in using them, is a horizontal, lateral relation. You hold one technique in one hand, and the other in the other hand, and you heft them and compare them and decide what you want to do. Nothing is gained by putting class_eval on a pedestal and getting all worked up about how “meta” it is. All you have to do is study it a little and then use it when it’s the correct choice for accomplishing what you’re trying to accomplish.

Back to top


Emerging Tech conference coming up

Wed Feb 7 10:26:37 2007

I’m going to be speaking at the Emerging Technologies conference in Philadelphia. The conference is being held March 28-29, at Drexel University, and is produced by Chariot Solutions.

I’ll be speaking on Rails routing, a topic that’s becoming dear to my heart as I”m working on some materials on it for publication, and also giving a tutorial on it at RailsConf 2007.

Back to top


The Magic Pens of Ruby

Sun Feb 18 14:01:00 2007

I’ve recently found myself describing single objects yielded by iterators as “magic pens.” Though it may sound more psychodelic than technical, it’s actually proven to be a good way to explain these objects and give people a feel for why an iterator would only yield one object in the first place.

I don’t mean cases where you iterate through a collection that happens to have only one element. I mean methods that, by design, yield one and only one object, every time they’re run.

The very word “iteration” evokes collections, and it’s not surprising that I’ve seen puzzlement over iterator constructs like this one:

  create_table do |t|
    t.column :first_name, :string
    t.column :last_name, :string
  end

The create_table method is being supplied with a block, so it’s an iterator. (Ask any method: iterator? and it will tell you true if you’ve given it a block, even if it never yields to it.) But what is it iterating over, or through? How many times? Once? Why bother iterating, then? Why not just call a method and use the return value?

  t = create_table
  t.column :first_name, :string
  t.column :last_name, :string

The answer—the admittedly very high-level answer, but the one I’ve found most effective in nailing into place exactly what’s going on—is that create_table works by handing you a magic pen. The pen has magic only for the duration of the code block. While you have the magic pen, you use it to do things you wouldn’t normally do, like bring about changes in your database tables and columns. (Not the records (though those too, if you wish): the tables and columns themselves.)

The magic pen idiom is very elegant, for at least two reasons.

First, it throws the spotlight on what you’re doing. The delimitation of the code block, during which you have the pen, puts the specialness of the process in high relief. You have to get the pen to do what it needs to, all in one place and time. (You might say that the code block is itself a magic “pen”—that is, a magic enclosure….)

Second, the magic pen idiom saves you trouble. Think about the method that hands you the pen. At some point, it has to yield to your code block. But before and after it yields, it can do any amount of set up and tear down—which, consequently, you don’t have to worry about.

Let’s look at an illustration of this second point up close.

Inside a magic pen

The magic pen you get from create_table is actually an instance of the class TableDefinition. You can see exactly how create_table hands you the magic pen if you look at the source code for the first segment of the method create_table, which is in schema_statements.rb (comments added):

  def create_table(name, options = {})
    table_definition = TableDefinition.new(self)
    table_definition.primary_key(options[:primary_key] || "id")
    unless options[:id] == false

    yield table_definition    # You get the magic pen!

The yield triggers execution of your code block, and the local variable t is assigned to the TableDefinition object that’s been yielded. You need this object because it’s the one that has a “column” method. And it’s your magic pen.

The magic itself (the process of changing the database) happens back in create_table, after your code block ends. Here’s the rest of create_table:

    if options[:force]
      drop_table(name, options) rescue nil
    end

    create_sql = "CREATE#{' TEMPORARY' if options[:temporary]} TABLE " 
    create_sql << "#{name} (" 
    create_sql << table_definition.to_sql
    create_sql << ") #{options[:options]}" 
    execute create_sql
  end

The routing magic pen

While we’re on the subject of magic pens in Rails: you also get a magic pen to help you write your application’s routing rules. Here’s the default config/routes.rb file, minus comments:

  ActionController::Routing::Routes.draw do |map|
    map.connect ':controller/service.wsdl', :action => 'wsdl'
    map.connect ':controller/:action/:id.:format'
    map.connect ':controller/:action/:id'
  end

The magic pen is “map”, which is a Mapper object. It’s by handling this object that you bring about changes in the routing tables. Like the migration magic pen, the routing magic pen is yours only for a time. But during that time, it gives you a lot of power. When you write named routes and resource routes, you see even more of the power:

  # Create a method called profile_url that generates a URL
  # of the form profile/id which is bound to the user/show
  # action:

  map.profile 'profile/:id',
            :controller => "user",
            :action => "show" 

  # Generate a full complement of RESTful routes and associated
  # URL generation methods for the accounts resource:

  map.resources :accounts

This magic pen has a lot of ink in it.

Last but not least, let’s look at the extremely useful filehandle magic pen in Ruby.

Ruby’s filehandle magic pen

You can, if you wish, deal with file-writing procedurally, like this:

  fh = File.open("myfile", "w")
  fh.puts "Content of file!" 
  fh.close

And in this scenario, you do indeed get a magic pen. But it’s not very dignified for the magician to have to sweep the stage after the show—as in fh.close. Doing it the magic pen way has the effect of making Ruby do the housekeeping:

  File.open("myfile", "w") do |fh|
    fh.puts "Content of file!" 
  end

The open method yields a filehandle. Then, after the code block finishes, control returns to the method, where the filehandle gets closed for you. You don’t have to worry about it.

The magic pen idiom distills the magic into the pen, by offloading the housekeeping onto the method that yields the pen in the first place (create_table, draw, open). Conversely, the fact that Ruby makes this kind of offloading so easy is what makes magic pen scenarios so easy.

So when you see an iterator, don’t assume it’s handling a collection. It may just be setting up a magic pen experience for you.

Back to top


Sudoku solutions: who cares?

Sun Feb 25 23:47:00 2007

I’m a sort of mediocre good sudoku solver—flashes of brilliance, too lazy to bother writing in all the possible values of each field so not in the running to solve a lot of the harder puzzles. But I enjoy them, and I go through phases of doing them quite a bit.

I also do crosswords—specifically, British-style cryptic crosswords. I’m quite good at those. I rarely finish one completely, but I still consider myself good at them because I often come within, say, two or three clues of finishing. And if the answer is something I’ve never heard of, I give myself partial credit, so to speak.

It’s actually the answers that I’ve been thinking about: the answers to crossword clues, and the answers to Sudoku.

When you work on a crossword clue, there’s a very specific goal for that clue. Clues can be fun, even in isolation. You can work on a crossword puzzle with someone else, even someone who can’t see the puzzle; you just give them a clue, and tell them how many letters you’ve already got, and they can work on it.

Sudoku are different. You can’t really say to your friend, “I’ve got a square that’s missing 2,8, and 9. The blank boxes are the center, the top right, and the middle left” and expect your friend to come up with a solution.

And after you’ve worked on a crossword puzzle – more to the point, after you’ve given up – you want to see the solution. When you see the answers to the clues you didn’t get, you may feel stupid or you may feel vindicated (if you decide the clue was bad, or the answer was something you truly never would have been able to come up with).

That’s where I wonder about Sudoku. You always get the solutions in the back of Sudoku books, or published the next day in the newspaper. But why, exactly? I can’t imagine working on a Sudoku, failing to complete it, and then looking at the third box from the left in the middle row of squares and saying, “Oh, of course! Seven!” The individual squares just don’t have the same relation to their answers that crossword clues have to theirs.

Another kind of weird thing about the solutions to Sudoku is that, at least if you put yourself in the right frame of mind, seeing them doesn’t matter. If I set out to solve a Sudoku rigorously – with no guessing, never filling in a box until I’m sure about it – having access to the solution doesn’t really make my job any easier.

What all of this amounts to is, I think, that the culture of puzzle publication dictates that solutions accompany puzzles, but not too closely (at the back of the book, or a day later), even though this way of doing it is a rather odd fit, in some respects, for Sudoku. No harm done, of course. I just find it kind of funny.

Back to top


DABlog now using Mephisto

Sun Feb 25 23:52:00 2007

I’ve switched DABlog over to Mephisto, a publishing system that’s become a very popular blog engine. Mephisto is by Rick Olson and Justin Palmer.

The switch is smooth so far (thanks for the help on IRC, Rick :-) and I’ve also added a FeedBurner feed. Today is also the day I started using gmail, having been a Pine aficianado for years and years. A big transition day.

Back to top


Rails training by Ruby Power and Light!

Tue Mar 27 14:43:00 2007

My training/consulting company, Ruby Power and Light, is offering its first open-enrollment Ruby on Rails training class, May 8-11, in Edison, NJ. Details and signup at rubypal.com -- click on the announcement.

Back to top


The L in DSL: langue ou langage?

Tue Apr 17 18:19:00 2007

In 1964, the great film theorist Christian Metz published a seminal essay called, “Le Cinéma: langue ou langage?” The basic idea was this. Movies obviously communicate something. So they’re evidently tapping into the human capacity for understanding symbolic representation—essentially, language. But does that mean that there is a film language, with its own precise rules, the way there is English or French? Or does it mean, rather, that film participates in the process of communicating in a language-like way, but not according to one particular set of rules?

Metz’s view was that it was the latter. Film communicates through language-like means (symbolic representation, piecing shots and scenes together like phrases to create meaning), but there’s no one-and-only language called Film. Different films can do it differently, and different audiences (depending on when and where they learn to become “film literate”) have different ways of interpreting the content and editing patterns of films.

Thus one may say that film is langage (language-like communication), but it is not une langue (a particular language).

It strikes me that this goes to the heart of the L in DSL.

DSLs a-go-go

The concept of the Domain Specific Language (DSL) has been in heavy rotation in recent times in the Ruby and Rails worlds, and for good reason. Ruby provides a very hospitable environment for little idiom sets that, with little effort, can be coaxed into looking like pseudo-code or configuration syntax, and therefore can help greatly in allowing non-programmers to understand what’s going on.

Thus, for example, you might come up with something that allows you to do this:

with Employee "123-45-6789" do
  dock_salary 1000
  warn_about :misconduct
end

and you can be fairly optimistic that, with minimal coaching, you can get most people to understand it.

This kind of thing is extremely useful. I wonder, though, whether it always deserves to be called a Domain Specific Language. It seems to me that the term DSL has become a bit over-burdened. It sometimes feels like any snippet of code that uses a block and includes one or more well-named methods ends up getting called a DSL.

In the grand scheme of things it doesn’t really matter if someone happens to call a snippet of code a language, domain specific or otherwise. But I do think that the horizon of DSL expectation in Ruby has shrunk a little bit. If DSL means having a method called warn_about that doesn’t need an explicit receiver (and, by the way, I myself dislike the magic instance_eval trick that allows this; but that’s another story), then we don’t really have a name for full-blown, semantically rich, domain-specific languages written in Ruby.

What the ‘ell?

It’s a bit curmudgeonly, though, to lobby for people to stop using a term they find appropriate for their code. So I haven’t. But this morning I thought of another way to see the whole thing.

This:

with Employee "123-45-6789" do
  dock_salary 1000
  warn_about :misconduct
end

is not a domain specific language. It is, rather, domain specific language. Note the lack of the “a”. It’s domain specific, and it uses language-like constructs. But it isn’t a language. It’s Ruby, using expressive method names and cushy semantics and therefore facilitating the use of domain specific idioms.

In other words, I suggest that when people say they have created a DSL, they might more precisely say that they have used DSL. They have not created une langue, but they have made use of a particular aspect of langage.

Anyway, that’s how I’ve come to see it. I hope the late, great Metz would have approved.

Back to top


Tough love from Verizon

Mon May 14 12:57:00 2007

I don’t think you have to be a language snob to wince (and laugh) at the way advertisers misuse English. They’re protected, of course, by the myths that surround their profession. If they get their grammar wrong, or misuse an idiom, they must have some ingenious marketing reason for doing so—or so people are willing to asusme. In fact, I think what’s happening is that the lousiness of the American educational system is trickling up into the ranks of copy writers and copy editors and basically everyone in the chain of custody of commercials.

The one that got me writing this post is a Verizon radio ad, specifically an ad for Verizon’s phone/cable/Internet triple package. It features the usual fake testimonial sound-bites from actors pretending to be customers. That’s par for the course, until one of them says (and the stuff in square brackets is a paraphrase; the rest is verbatim):

“[Verizon gives you a great deal,] providing all three services and not pulling any punches.

I love the image of a Verizon repair person coming to my door and slugging me in the jaw, as hard as he or she can. (I’d rather it not happen, but I love the image.) It is, of course, completely clear that the person who wrote that line has no idea what the expression “pulling a punch” actually means, and neither do the executives who paid to have the ad written. I surmise that they think it means “pulling a stunt”, so that not pulling any punches means you’re entirely honest. Or something. Who knows?

I suppose that if Coors can actually bring to market a product called “Artic [sic] Ice”, then Verizon can sleepwalk through the process of producing radio commercials. In fact, it doesn’t surprise me any more. I no longer expect the ostensible gatekeepers to know what they’re doing. They probably never did, but I do think it’s gotten worse. And funnier.

Back to top


Boston Early Music Festival wrapup

Sat Jun 16 23:44:00 2007

I’m in Boston, having just spent four days at the Boston Early Music Festival. My brother Gavin, director of the Princeton Early Keyboard Center, rented an exhibitor’s room—basically a hotel room from which the beds have been removed—where he displayed his oldest harpsichords (one made in London in 1785, one made in Italy in the late 17th century). Visitors to the room were encouraged to play on the instruments, and many did.

It wasn’t just a display, though. Gavin also produced something like fifteen half-hour musical recitals, involving himself, me, and various musical colleagues and friends. The result was that Room 921 at the Radisson was a hot-spot of wonderful performances and presentations. Highlights included:

And there was more. Room 921 was, as Gavin and I said to each other almost simultaneously when we were discussing it afterwards, a festival within a festival. Congratulations to Gavin for producing these four days of music, and thanks to everyone who participated and everyone who came to hear us.

I also spent a lot of time looking at the exhibit halls, where there were lots of instrument makers and sheet music sellers. There were not as many cellos as I would have liked; in fact, I only saw three. Viols seem to rule at this event, and the violin family is mainly represented by the smaller instruments. I guess it’s understandable, since the makers have to lug the instruments to the festival… but I still would have liked to have seem more baroque cellos. There were a lot of bowmakers on hand, though, and that was interesting.

Back to top


The Stupidity Tax

Wed Jul 4 12:47:00 2007

As of this morning, I can't find my London cell phone. Yes I know it sounds pretentious for an American even to have one... but I go to London usually two or three times a year, and you really can't have any kind of social life over there without one. Anyway, I'm at home in the U.S., and I can't find the phone.

That means I will almost certainly have to buy another one, solely because I'm too stupid to have put it away properly last time I got back from London.

I consider the price of the new phone to be a Stupidity Tax payment. I pay several hundred dollars a year in Stupidity Tax. I forget to cancel hotels; I neglect to send in rebate forms; I lose things. I have to say, the losing things thing is very deep-rooted; there's more to that syndrome than stupidity. Still, to the extent that I lose expensive things that should be simple to keep track of, their replacement is Stupidity Tax.

Thinking of all of this as Stupidity Tax actually makes it a little easier to deal with. It's just part of the cost of living. Of course I'd like to reduce it as much as possible. But it's unlikely I'll ever reduce it to zero. Life is too much of a sieve to hope for that. At least I can keep things interesting by rotating the reasons for the tax: a lost item here, a forgotten bill there. I'd like it not to get too interesting... but the Stupidity Tax is here to stay, so I might as well try to adapt to it.

Back to top


Bang methods; or, Danger, Will Rubyist!

Wed Aug 15 11:35:00 2007

In Ruby, you can write methods whose names end in ! (exclamation point or “bang”). There’s a lot of confusion surrounding the matter of when, and why, you would want to do so.

What ! does (and does not) mean

The ! in method names that end with ! means, “This method is dangerous”—or, more precisely, this method is the “dangerous” version of an otherwise equivalent method, with the same name minus the !. “Danger” is relative; the ! doesn’t mean anything at all unless the method name it’s in corresponds to a similar but bang-less method name.

So, for example, gsub! is the dangerous version of gsub. exit! is the dangerous version of exit. flatten! is the dangerous version of flatten. And so forth.

The ! does not mean “This method changes its receiver.” A lot of “dangerous” methods do change their receivers. But some don’t. I repeat: ! does not mean that the method changes its receiver.

Don’t overuse the !

Not every !-method changes its receiver, and not every receiver-changing method ends with !. There’s Array#pop/push/shift/unshift/concat/clear, and lots of others.

Don’t add ! to your destructive (receiver-changing) methods’ names, unless you consider the changing to be “dangerous” and you have a “non-dangerous” equivalent method without the !. If some arbitrary subset of destructive methods end with !, then the whole point of ! gets distorted and diluted, and ! ceases to convey any information whatsoever.

If you want to write a destructive method and you don’t think the name conveys destruction, you might be tempted to add a ! to make it clear. That’s not a good idea. If the name of a destructive method, without a !, does not connote destruction, then the name is wrong and cannot be repaired by slapping a ! on it.

In such a case, you should create the traditional pair of methods: a non-bang method and a bang method. It’s conventional to define the non-bang method in terms of the bang one. Here’s an example involving a simplistic version of an Array#flatten_once method (it doesn’t handle nested objects other than arrays very well, but it makes the bang-point):

  class Array
    def flatten_once!
      res = []
      each do |e|
        [*e].each {|f| res << f }
      end
      replace(res)
    end

    def flatten_once
      dup.flatten_once!
    end
  end
 

The non-bang method is defined in terms of the bang method. You wouldn’t want to write an isolated method called flatten_once! without the matching non-bang version, since there’s no way to measure the “danger” except in relation to the non-dangerous method.

[Aug. 16, comment in response to IRC question from apeiros: you can also define the bang method in terms of the non-bang method, but in the Ruby source code it’s usually done in the direction I’ve done it, and I’ve followed that practice here.]

Danger takes many forms

Sometimes you get more than one kind of “danger” even within one bang method. Take String#gsub!. This method changes its receiver:

  str = "David" 
  str.gsub!(/$/, " Black")
  str                        # David Black
  

It also differs from gsub (non-bang) in that if the string does not change, gsub returns a copy of the unchanged string but gsub! returns nil:

  str.gsub(/xyz/, "blah")    # David Black
  str.gsub!(/xyz/, "blah")   # nil
  str                        # David Black
  

The ! in gsub! gives you a heads-up: it warns you of danger, and that means that before you use the method, you should find out exactly how it behaves. (A simple “ri String#gsub!” should do it.)

Forget “intuitive”

It may not be easy or, to use a heavily overworked term, “intuitive” to think of ! as meaning “dangerous”, or to craft your method names so that the !’s make sense in that context. It’s worth it, though. Give Ruby (and Matz) the benefit of the doubt. This use of ! probably does not occur in other languages you’ve used. But it works really well. If you let go of the notion that ! means destructive, and if you think through the naming and pairing of dangerous and non-dangerous methods, you’ll see how valuable a flag the ! can be.

Back to top


Reflections on Wikipedia

Tue Sep 4 12:53:00 2007

I love reading Wikipedia, and I’ve learned a lot from doing so. I’m not, in other words, rabidly anti-Wikipedia. But I do have a few serious concerns about it.

It seems to me that Wikipedia is, in effect whether or not in intent, pushing the Web in exactly the direction it isn’t best suited for: namely, centralization of information. Mailing list posts and IRC channels are full of links to Wikipedia articles, on everything from… well, on lots of things. It seems that the standard way of saying, “If you’re not familiar with the term I just used, here’s how to learn about it” is to provide a Wikipedia link.

I strongly suspect that this is automatic on the part of the people doing it—automatic, that is, rather than based on a thorough search of all the resources available on a given topic and a reasoned decision about which is best-written and/or most informative. That’s the thing: Wikipedia provides something close to one-stop shopping. You’ll find something on almost anything.

Furthermore, Wikipedia itself seems to buy into and cultivate the image of itself as a centralized, objective source of information about everything. One symptom of this is the fact that links within Wikipedia articles are always, or very nearly always, links to other Wikipedia articles. In spite of how open it is, in terms of contributions, it’s ultimately a closed system.

Yes, external sources are indicated at the bottom of articles. But the providing of sources, while important in terms of academic honesty and paper-trailing, never stopped scholarly publications from taking something very close to a “voice of God” position with regard to their subject matter. And it doesn’t stop Wikipedia from doing the same thing. How often have you bothered to go look up all the books and articles listed at the bottom of a Wikipedia article, and carefully analyzed how the information was gleaned and pieced together?

The editorial emphasis on balance and completeness and objectivity is another troubling sign. What’s wrong with balance? What’s wrong with it is that it’s a mirage. Any undergraduate who’s taken a reasonably decent mass communication course knows that what the news media call “balance” is simply an editorial or presentational style. And it requires constant reinforcement. “We report; you decide,” says Fox. “We’ll give you the world,” says at least one radio station (or conglomerate, probably, at this point). The idea is that the discouse provides a perfect substitute for the reality, so you can consider yourself to have been served the reality when you consume the discourse.

Wikipedia operates, I believe, in exponentially greater faith than the news media. But the philosophy of representation is the same, and it’s very old-school. An article is a simulacrum of a discrete, finite reality, and an article’s suitability for publication can be measured by how closely it has cloned that reality. While there’s often room for improvement, every article has the noble goal of achieving a perfect fit with its subject matter, and the potential to do so.

The fact, however, is that it’s not in the nature of written discourse to be a perfect fit with some arbitrary slice of reality. It doesn’t work that way. There’s no shame in acknowledging this, but Wikipedia battles against it.

What troubles me is not just that it’s child’s play to debunk the “voice of God” philosophy of discourse, but that I’d thought the Web was doing a pretty good job teaching people that reality and discourse actually map to each other sloppily, crazily, contradictorily, and ironically. Measured both by its editorial policies and by its wide, eager adoption as a centralized authority, Wikipedia unfortunately pushes against this more intriguing and, I would argue, more balanced take on things.

Back to top


Upcoming Rails training in New Jersey!

Fri Sep 14 07:00:00 2007

My Ruby/Rails consultancy, Ruby Power and Light, LLC, is offering two Ruby on Rails training courses this Fall, both hosted by Exceed Education in Edison, New Jersey:

I will be the instructor for both.

You can get more information on the courses, and on signing up, at Ruby Power and Light—just follow the links in the banner box.

Back to top


"Advancing with Rails" training in Berlin, Nov. 19-22

Fri Oct 19 12:13:00 2007

I suspect it won’t appeal to the Thanksgiving-inclined, but I’ll be teaching my “Advancing With Rails” course, for intermediate Rails developers, in Berlin, Germany, November 19-22.

Advancing With Rails is designed for people who have done some Rails… read a couple of books… and want to keep going and get better at it. I’ll be covering Ruby language topics as well as Rails techniques and best practices.

The course will be conducted in English, though I speak German and can field questions in either language.

More info here.

Back to top


Upcoming Rails training, 2008!

Sat Mar 22 19:17:00 2008

Long time, no blog. But now I'm out of hibernation.

I've got some Rails training courses coming up, including:

See Ruby Power and Light for details.

The Berlin courses are being taught in English. The info about them on the Web might only be in German... but you can always contact me for more info if you're interested. Berlin is a very cool place -- I highly recommend it!

Back to top


Splitting hairs over "resource": the case for the affirmative (Part 1)

Sun Mar 23 00:49:00 2008

I’ve commented on the main Rails mailing list and elsewhere about some concerns I have about the way the term “resource” has been adopted into Rails practice and discussions. I’d like to explain those concerns in a little more detail.

In this post, I’ll talk about the definition of a resource and why it’s a good idea not to overpaint the original definition with a redefinition based on the specifics of Rails. In the next, follow-up post, I’ll comment on several closely related issues, including the usefulness of model-less resources, why it’s better (though not perfect) to identify a controller with a resource than to identify a model with a resource, the relation between CRUD and resources, and the role of the “representation”—an important and concept often overlooked in discussions of REST in Rails.

Controller + model: what a resource isn’t

The problem, in a nutshell, is that the term “resource” has come to be understood widely as meaning “ActiveRecord model” or, perhaps more commonly, “controller-model stack.” People say that they’ve “created an item resource” when what they mean is that they’ve generated a item model and an items controller. There’s no reason for there not to be a short, concise term for “name-matched controller-model stack.” But that word should not be “resource.”

Equating “resource” with controller-model stack has the unfortunate effect of leaving us without a term to refer to what Roy Fielding originally meant by “resource”—which is definitely not “controller-model stack” or anything like it. (More on what a resource is presently.) Fielding’s description of a resource is deeply interesting, and worth protecting from terminological drift. Moreover, there’s no loss involved. In fact, by teasing apart the threads of what’s a resource and what isn’t, we can actually get more out of the RESTful tools available in Rails.

Defining “resource” as controller + model severely limits imaginative thought about how a resource, in the original sense, might play out in Rails. By imaginative, I do not mean improvisatory or chaotic. The Rails REST conventions are very powerful and tremendously useful, and I’m fine with being conservative about deviating from them ad hoc. But I wince when I see people agonizing because they’ve manipulated Model A in Controller B, and think that they’ve violated RESTful principles because they’re crossing resource lines. That’s not how it works; that’s not how the concept of resource maps to Rails technology.

Obviously Rails uses controllers and models, so whatever a resource is, somewhere along the line it’s likely to involve those things in a Rails application. The wrong turn, though, is in assuming that a resource is a controller and/or model.

I tend to think that much of this way of viewing the matter comes from the so-called resource scaffolding. It’s easy to understand why Rails developers, presented with a tool that generates a controller-model chain and calls it a “resource,” would either not see the need to question the terminology, or would be reluctant to do so. But there is a need to question it. The term “resource,” as used very commonly in Rails discussions, bears much more resemblance to how it’s used in the context of Rails scaffolding than how it’s used by Fielding. That doesn’t benefit anyone.

Scaffolding or not, something has led people to think that a resource consists of a controller and a matching model. It doesn’t.

What a resource is

Rails is database-intensive, so the temptation exists to conclude that the word “resource” has something to do with database tables and persistence. Fielding could hardly state the case against this perspective more strongly:

The resource is not the storage object. The resource is not a mechanism that the server uses to handle the storage object.

Already one has to wonder how the generation of an ActiveRecord model and migration ever came to be viewed as part of creating a resource per se (as it is in the scaffolding). Anyway—Fielding goes on to define what a resource is:

The resource is a conceptual mapping — the server receives the identifier (which identifies the mapping) and applies it to its current mapping implementation (usually a combination of collection-specific deep tree traversal and/or hash tables) to find the currently responsible handler implementation and the handler implementation then selects the appropriate action+response based on the request content.

This sentence is a bit more complex than the first two, and it’s worth breaking it down for the sake of seeing how it might map to Rails.

The key idea is that a resource is a conceptual mapping. You send a resource identifier to a server. The server sends back a response (a “representation” of the resource, as we learn elsewhere). In between, the server does what it has to in order to generate the response.

The response is a representation, not a resource. And the mechanisms by which the representation is generated are not, themselves, the resource. In Rails, those mechanisms typically include the routing system (which I would roughly identify with what Fielding calls “the current mapping implementation”) and the controller objects with their actions (the “responsible handler implementation”). Again, these mechanisms are not the resource. And the model layer, which lies yet further away in the architecture, is really not the resource.

The benefit of splitting hairs over the terminology is that it points the way to recovering Fielding’s original concept of a resource, of which I don’t get very many glimpses in the typical discussion of RESTful support in Rails. To the extent that you are setting up models and controllers and RESTful routing, you are putting in place the wiring that will allow your system to fulfill its contract as a provider of representations of certain resources. To the extent that you are determining what resources your system is responsible for, you’re performing a task that has no dependency on Rails or any other specific software tools.

The robustness of resources

Part of the problem with using “resource” to refer directly to parts of the Rails application itself is that it introduces a fragility into the concept of resource, and the identity of specific resources, that really shouldn’t be there. If you declare that your system is responsible for the Resource N, then it shouldn’t matter how many controllers, actions, models, and database tables you use. I don’t mean that it doesn’t matter in terms of software design. I mean that Resource N should be above the fray. It should be robust enough not to depend for its identity as a resource on the specifics of the way you handle the mapping of identifiers to representations.

It’s instructive in this context to consider how the concept of “resource” plays out when you’re serving a static HTML page. The way it plays out is the same as the way it plays out when you’re generating a dynamic response. In other words, whether or not something is a resource has nothing to do with the question of whether or not its representations are generated dynamically, nor with the question of whether a database has been queried or a template rendered in the process of the production of a representation.

This is just terminological common sense. Imagine if you were publishing information about resources available through your system, and you had to explain that sometimes they weren’t really “resources” because they didn’t hit a Rails controller and database table. That would be ludicrous. Obviously a resource is a resource, not because of how its representation is generated behind the scenes but because a representation is returned, however it’s generated, based on a mapping of identifiers to request handlers.

So if you start thinking of controllers and models as actually being resources, you’ve painted yourself into a corner where you have no term that describes a resource in a higher-level sense—no way to identify the “conceptual mapping” that Fielding stipulates. Controllers and models are part of the handling and response mechanism. They are not resources.

But once you decouple the notion of resource from the specifics of how Rails applications generate representations of resources, a lot of other things fall into place. In the second half of this essay, I’ll be looking at several REST-related topics that I think benefit directly from the liberating and sense-making effect of observing the distinctions among resource, representation, and handler mechanisms.

References

Fielding, Roy Thomas. Architectural Styles and the Design of Network-based Software Architectures. Doctoral dissertation, University of California, Irvine, 2000

Back to top


A short-circuit (||=) edge case

Tue Mar 25 15:11:00 2008

In Ruby, you can conditionally set a variable like this:

  x ||= 1

If x is not initialized—or if it is set to nil or false—it will be assigned 1. If it’s already set to a Booleanly true value (i.e., anything other than nil or false), it will remain unchanged.

Most descriptions of this idiom, including mine, have said that it expands to this:

  x = x || 1

Last year, though, an edge case came to light on the ruby-talk mailing list. It involves hashes with default values.

Trouble in ||=-land

Here’s an irb session illustrating the case. First, we’ll create a hash with a default value of 1.

  >> h = Hash.new(1)
  => {}

Remember that the default value is what the hash returns for non-existent keys. There are no assignment implications; referring to a non-existent key does not result in setting that key in the hash.

  >> h[:x]
  => 1
  >> h
  => {}        # still empty!

Now let’s try the ||= idiom.

  >> h[:x] ||= 2
  => 1

Once again, no assignment has taken place:

  >> h
  => {}

This struck a number of us on the mailing list as weird. It certainly means that ||= does not expand the way we had assumed it did. Here’s the proof: try the expanded version, and you’ll see that it does assign to the hash, as you’d expect.

  >> h[:x] = h[:x] || 2
  => 1
  >> h
  => {:x=>1}

So there we have proof that x ||= y and x = x || y are not interchangeable.

That raises two questions: first, what does x ||= y expand to, and second, do we like it?

The true expansion of ||=

At RubyConf 2007, I was running a “Ruby Clinic”, where people could come and go and ask questions about Ruby. Matz stopped by for a while, and the ||= topic came up. He explained that the real expansion is:

  x or x = y

Note (a day later): It’s been pointed out to me that expansion as x || x = y is more accurate. I believe that’s right, though my examples here didn’t flush it out.

Sure enough, expanding it this way produces parallel results in the hash case. Continuing the same irb session:

  >> h
  => {:x=>1}
  >> h[:y] ||= 3
  => 1

After that conditional assignment, the hash has not changed.

  >> h
  => {:x=>1}

And expanding it in the “or” style also does not change the hash:

See “Note”, above.

  >> h[:y] or h[:y] = 3
  => 1
  >> h
  => {:x=>1}

That clears that up. But do we like the way this plays out with hash defaults?

Editorial comments

I have mixed feelings about it. I can see that it makes sense. On the other hand, I can’t help thinking that when you write this:

  hash[:x] ||= 2

you’re really expecting the hash to end up with an :x key. In other words, my gut feeling is that it should mean:

  hash[:x] = 2 unless hash.has_key?(:x)

However, I understand that having it mean that would involve special-casing the hash case, and in the long run, I’m not in favor of that.

So what it comes down to is: heads up a bit with ||=. It works fine, but you need to know the real expansion.

Back to top


Short-circuit (||=) post -- CORRECTION

Wed Mar 26 13:46:00 2008

There was a response to my post from yesterday on Procnew.com, which pointed out that when you’ve got this:

x ||= y

it doesn’t expand to this:

x or x = y

(which is what I said in my last post) but rather to this:

x || x = y

I believe that’s right. It’s kind of hidden until you do:

a = x ||= y

and you start to see that it behaves like the || expansion, not the or expansion.

The example on Procnew.com has one glitch, which is that on line 9 of the irb session, it’s using a value that’s already set (h[:y]), so it’s never going to jump over the || anyway. Still, I believe the point is right.

Pending other edge-case edge-cases, anyway…. :-)

Back to top


Getting out of Ruby's way: code beauty and/or greatness

Fri Mar 28 09:40:00 2008

Chad Fowler wrote an interesting article this week on the subject of Great Ruby Code. The article concludes with an invitation for comment:

Anyway, I still don’t have a satisfactory list of great Ruby code. I’d like to build such a list. So, please leave a comment saying the name of an open source Ruby project you feel represents truly great Ruby code.

My comments are somewhat “meta”, and I had an interesting chat with Chad about the whole topic of greatness in Ruby code after I’d read the article, so I thought I’d make my comments here in an article of my own.

For me, the very concept of great Ruby code contains the seeds of its own destruction. Here’s why.

When I see Ruby code and think, “This is great,” what I usually mean, at least as a first approximation, is that Ruby is great. I don’t mean that everything written in Ruby is automatically great. But I do find that a lot of what’s involved in writing what I consider beautiful Ruby code is getting out of Ruby’s way. Ruby is famous for getting out of your way; but you can and should return the favor.

I’m slipping between “great” and “beautiful,” which isn’t fair but maybe that’s part of the problem: I’m not sure what pure greatness in Ruby code would be, because I tend to perceive Ruby code in terms of beauty—not down to the millihelen,[1] perhaps, but as an overall matter—rather than greatness; and I can’t really give an individual programmer “credit,” so to speak, for the beauty I find in, say, yield or class << object or the technically unnecessary but, in my view, manifestly elegant class/module distinction.

Then there’s the subjectivity issue (as many of you non-fans of class << object are probably thinking right about now!). Of course Chad isn’t anticipating universal agreement on what’s great in Ruby code. But for me, the impossibility of consensus is another seed of the very concept’s own destruction. It’s an irony, even a paradox: if there is such a thing as greatness in Ruby code, we’ll never find it because once we shift the discussion to the plane of “What do you consider great?”, it’s likely to unravel in the same way that discussions about what’s great in any art unravel.

And about that art thing: Coding is of course an art, but it’s a peculiar one in that the artist is operating within the boundaries set by another artist&mash;namely, the designer of the language. (Note that I said coding, not programming. I’m not trying to drive a wedge between them, but as Knuth and others have shown us, there are aspects to the art of computer programming that are not about this or that language, and I’d like to keep the terminology at least a bit separate.) Is it like music? Are we interpreting Matz’s score? Or is Matz the playwright, we the actors? Or perhaps Matz is like whoever invented baseball: a set of rules within which we elect to operate. Well, there are great baseball players….

Maybe greatness in Ruby is ours to lose: If you follow stylistic best practices (which is another, but in my view related, matter), and above all let the language talk to you and don’t “write {Java,C,Perl,...} in Ruby,” your code will be great, or beautiful if you prefer, because you’ve collaborated successfully with Ruby. And yes, I do think that Ruby confers an advantage here over many other languages. For me, the most important key to Ruby’s beauty and its greatness is that Ruby code gets clearer, rather than more cryptic, as it gets shorter. I don’t want to jump through the hoop of reciting all the obvious facts (that this can be true in other languages; that Ruby code can be cryptic; etc.). I present it for what it is: my take on the magic of Ruby. I’ve always said that as you work on a Ruby program, code disappears from your screen. So it does—and the program becomes more, rather than less, expressive and communicative.

There’s no tidy stopping point to this exploration, and that’s as it should be. I encourage you to go to Chad’s article and read it and respond. I don’t expect us to end up with a definitive list of great Ruby code. But what Chad is doing is inviting us to look—really look—and I find it well worth the trouble.

[1] A millihelen is the amount of beauty required to launch one ship. (I wish I could take credit for that one but I only know it as an old joke.)

Back to top


Splitting hairs over "resource": the case for the affirmative (Part 2)

Thu Apr 24 11:55:00 2008

In part 1 of this two-part post, I explained my concern that the word “resource” has become too closely associated in Rails-related usage with some combination of model, database table, and controller/model stack—none of which do justice, as definitions or even first approximations, to the concept of a REST resource as originally described by Roy Fielding. Here, I’m going to expand on this observation by exploring a few ramifications of the same topic.

Resources, controllers, and models (or lack thereof)

As I explained in the previous post, the concept of “resource” has no database implications—indeed, no implementation implications. A resource does not have to have a corresponding model. It also does not have to have a corresponding controller. Resources are far more high-level than controllers and models. Controllers and models are tools with which you provide access to representations of resources.

However, if you want to draw a line between resources and Rails, by far the better line to draw is the one that points to controllers rather than models. A controller is not a resource, but it comes closer than anything else in your application to taking on the features of your resources. Models are another big step away.

If controllers are closest to resources, how does this play out? One way is in the creation of resources for which requests are handled by a controller that has no corresponding model.

My favorite example of a likely modelless resource is the shopping cart. In Ruby for Rails, I use a shopping cart in my central example. When I started working on this application, I tried to model it directly; I imagined I would have a ShoppingCart class, a shopping_carts table, and so forth.

I quickly realized, however, that I didn’t need that. What I was calling a “shopping cart” was really a virtual construct or, in Rails terms, a view. I had Order objects and Customer objects, and the shopping cart was basically a screen showing all of a particular customer’s open orders. Calling it a “shopping cart” was just a kind of semantic sugar. There was no need to persist it separately from the persistence of the orders and the customer.

If I were writing the same application today using RESTful idioms, I would in all likelihood do:

map.resources :customers do |c|
  c.resource :shopping_cart
end

or words to that effect. I would then have a shopping_carts controller, with a show action (probably leaving all the related CRUD stuff back in the orders controller, though there might be several ways to approach that part of it). And I would, without hesitation, describe the shopping cart as a resource—even though it has no ShoppingCart model behind it. From the perspective of the consumers of my resources, it doesn’t matter whether there’s a ShoppingCart model (and shopping_carts database table) or not. I can decide on the best application design, and use RESTful Rails techniques to support my design decisions appropriately.

A resource is not a model, and it’s also not a controller. Identifying the resource with the controller is, however, somewhat closer to the mark. The controller layer conforms most closely to the resource mapping, which makes sense since the controller is the port of call when someone connects to your application.

Another area where misunderstandings arise in the course of designing RESTful services in Rails is in the matter of how identifiers (URI) map to resources—and not just how, but how many.

Identifiers and resources: not always one-to-one

I’ve seen people tie themselves in knots trying to come up with the best way to label and/or nest resources. One of the principles that’s gotten lost in the mix is that the ratio between resources and identifiers does not have to be one-to-one. Fielding states:

[A] resource can have many identifiers. In other words, there may exist two or more different URI that have equivalent semantics when used to access a server. It is also possible to have two URI that result in the same mechanism being used upon access to the server, and yet those URI identify two different resources because they don’t mean the same thing.

Therefore, it’s possible that this:

http://dabsite.com

and this:

http://dabsite.com/welcome

can identify the same resource, which would probably be described as something like “The welcome and orientation information at dabsite.com”. The reason they’re the same resource is not that they generate the same HTML. Rather, they’re the same resource because they’re published as the same resource.

It’s also possible that this:

http://dabsite.com/orders/211   # 211th order in the system

and this:

http://dabsite.com/orders/042208-003  # third order placed on 4/22/08

identify different resources, even if the third order placed on 4/22/08 happens to be the 211th order in the system. That’s because resources are not database rows. In this case, the two requests might generate the same HTML, but still pertain to different resources.

You don’t have to make a point of having a non-one-to-one ratio between your resources and your identifiers. Just be aware that if such a ratio emerges, in either direction, you’re not doing anything inherently “unRESTful.”

CRUD and REST and resources

One of the nice things about the REST support in Rails is that it dovetails with CRUD-based thinking about modeling. I add in haste: REST is not CRUD, and CRUD is not REST. (That’s no secret, but I want to go on record with it.) But in Rails, there’s a nice relationship between them.

The REST support in Rails emphasizes the convention of CRUD operations. map.resources gives you a fistful of named routes that have built-in knowledge of CRUD action names. The emphasis on CRUD at this level encourages you to think of modeling for CRUD. Instead of having, say, a users controller with a borrow_book action, you can have a loans controller with a create action. In many cases, this way of thinking might also wag the dog of your domain modeling. Thinking about CRUD in the controller might, for example, lead you to conclude that you should have a Loan model.

It’s perfectly fine—indeed, in my view, it’s very productive—to think along these lines, to bring your modeling and your REST-friendly CRUD operations into harmony, as long as you understand that none of this is actually about resources as such. Rather, it’s about the Rails flavor of implementing the handlers that underpin the creation of resource representations.

Does that sound like just a lot of extra words? It isn’t. It’s a lot of words, but they’re not extra. Again, it’s important not to squeeze the entire framework into the “resource” label. Let a resource be a resource, and let the handler layers be handler layers. They’re nicely engineered—but they’re not resources.

And then there’s the word “representation,” which crept into my “extra words” sentence but which is the least extra of all of them.

Representations: the one that got away

The representation is, in my view, the one that got away: the central concept in REST that no one in the Rails world ever seems to talk about. We need to, though. It’s vitally important.

Your server does not traffic in resources. It traffics in representations of resources. Users of your application do not receive resources. They receive representations. The distinction is big; at stake is the entire meaning, and meaningfulness, of the notion of a resource.

We need the concept of “representation” because it’s the part of REST theory that relieves the pressure on the term “resource.” After all, how can a resource be a “conceptual mapping” (Fielding) and a sequence of bytes that a server sends you and a controller-model stack…? It can’t, and it’s only the first of these things. The second, the response itself, delivers a representation of a resource.

One resource can have many representations. There’s no big news here; we all know that a server can give us a text version of Jane Eyre or a movie version or an audio version. (I’ll refrain from getting philosophical about whether or not a book and a movie are “the same” in any deep sense. They’re the same enough, in this context.) The point is that we don’t need to mush everything into the term “resource.” Rather, we benefit by yanking that term up to the high level where it belongs, and applying the term “representation” to the actual response we’re getting.

Fielding has much more on representations in his dissertation, and I’m not going to try to paraphrase it here. My point is to encourage the liberal use of the term in Rails discourse about REST. The poor term “resource” has already been given too much to do. We need to delegate some of the domain description to the other terms that apply to it.

Now what?

The use of the term “resource” to mean things that, I’ve argued here, it really doesn’t mean is rather deeply entrenched, and widespread, in Rails discourse. I don’t have any quick fix for this. I do have a few recommendations, though.

First, read Roy Fielding’s dissertation. You can skip to chapters 5 and 6 and get a great deal out of them.

Second, pay particular attention to the concept of the representation. I don’t think we can get much further in exploring REST and Rails unless the representation makes a comeback. “Resource” is just plain spread too thin in the way it’s used in and around Rails, and there’s no reason why it has to be, if we look at the theory as a whole.

Third, and last, don’t assume that any deviation from the out-of-the-box behaviors in your RESTful Rails applications is unRESTful. The defaults are in place because they’re high percentage. But they’re just as opinionated as the rest of Rails, and in some respects more so. That’s OK, but do understand that they’re REST-friendly tools. They’re not a definitive statement on the entirety of what REST is.

REST is not an easy topic, and it’s unlikely that anyone is going to create a way for you to create and maintain RESTful applications, over time, without you trying to get a handle on it and developing your own understanding of resources, representations, requests, and responses. I hope these posts will help you out in that endeavor.

References

Fielding, Roy Thomas. Architectural Styles and the Design of Network-based Software Architectures.. Doctoral dissertation, University of California, Irvine, 2000.

Back to top


Death of a racehorse

Sun May 4 13:59:00 2008

I’ve always vaguely disliked horse races. The anthropomorphizing of the horses, the claims that they know that they’re involved in a race and that they share the goals of their owners, is manifestly silly and self-serving. And the whipping always bothered me. I suppose I made myself believe that horses didn’t really care and that an attack with a whip was, to them, kind of like a verbal exhortation to us. (Not that verbal exhortations can’t be painful, but they’re not physical).

The death of Eight Belles shocked me out of my indifferent, complacent position.

All the crap in the news about how noble she was, how competitive her spirit, how great her self-sacrifice… it’s all smug and disgusting beyond belief, despite the accompanying descriptions of the tears glistening in the eyes of the various stakeholders. What really happened was that this horse was forced to run as fast as she could, for reasons she could not understand and that had nothing to do with her well-being, and as a direct result, her legs fell apart, and then someone killed her.

That’s it; that’s all there is to it.

Why is this allowed to go on? Is it simply because more horses survive races than don’t?

For some reason, we continue to give the benefit of the doubt to this bizarre, nasty, money-drenched “sport”. Except that for me, at this point, there is no doubt, and no further conferral of the benefit.

Back to top


Slide words (if that's really what they're called)

Sat Jun 7 15:22:00 2008

A guy I was chatting with in the men’s lounge of the spa at Harrah’s in Atlantic City was telling me about “slide words.” I can’t find anything about them (and I’ve tried “slider words” and a few other variants) anywhere. I don’t think he made the term up, and he certainly didn’t think he had.

Anyway, even though I can’t find any background information or previous discussion, I am going to talk about “slide words” (or whatever they’re called).

A slide word, I gather, is a word or phrase that has come to serve as shorthand for an entire argument—except that the argument isn’t really there. We’re all just supposed to think it is. The slide word acts as a black hole, drawing further discussion and thoughtful debate into itself and killing it.

Slide words are bad because they take the place of actual analysis of situations and events. Every slide word has a kind of implicit, “Sigh. Here we go again” attached to it, even though the “again” part is asserted through the use of the slide word itself and not actually demonstrated.

I have something to say here about three slide words: conspiracy theory, Chinese menu, and bikeshed.

“Conspiracy theory”

“Conspiracy theory” is perhaps the best example of a slide word. Consider the following exchange, which is made up but is actually very similar to several I have had:

Me: Apparently there might have been an eighth Challenger victim. A Brazilian fisherman said that his son was struck and killed by falling debris, while they were out on a boat.

Other Person: Why haven’t we heard about it?

Me: It was in the news briefly. I guess it was considered more prudent to downplay it.

Other Person: That sounds like a conspiracy theory.

With the invocation of the term “conspiracy theory,” all further discussion of what might have actually happened is discredited. The events surrounding the death of John Kipalani’s son need not be examined in any detail; nor need the press coverage (or lack thereof). “Conspiracy theory” plays the role of a rebuttal of the statements about the Challenger disaster, even though it has no actual connection to them.

Here’s another example:

Me: The only people who profited from 9/11 in any way, financially or politically, were George W. Bush and his family and friends. I therefore assume, as a matter of the simplest logic, that Bush had something to do with it.

Other Person: What are you, a conspiracy theorist?

Again, the slide word (or slide phrase) gets played as if it were a trump card, when in fact it has nothing whatsoever to do with the question of Bush’s culpability in the 9/11 attacks, and neither refutes the logic that’s on offer nor adds information that might bring about a reconsideration of that logic.

“Chinese menu”

Another slide word I’ve come across, in a somewhat narrower setting, is “Chinese menu.”

When I was teaching at a university, I was involved in lots of discussions, formal and otherwise, about core curricula: what they should include, how they should be administered, and so on. I remember that in one series of such discussions, any time anyone suggested anything along the lines of having students choose one or more courses from each of several course groupings, someone else would say, “That’s like a Chinese menu.” Eventually it became just “Chinese menu.”

I have no memory of any discussion of why it was considered a bad idea to adminster a core curriculum this way. All that was required to rebut the idea was “Chinese menu.” Actual argumentation did not enter into it.

“Bikeshed”

Another slide word, a rather obnoxious one that seems to be enjoying considerable popularity these days, is “bikeshed.” If someone says “bikeshed,” they’ve said all they need to say (or at least all they think they need to say, and certainly all they’re planning to say) to establish that what you have been talking about is trivial and not worth discussing.

Saying “bikeshed” to someone, instead of telling that person outright that you find his or her statements trivial and worthless, is not only needlessly indirect but, in most cases I’ve seen, wrong.

The original bikeshed concept, as I understand it (which is from second-hand accounts, so I could be wrong), had to do with the phenomenon of committees spending more time arguing over what color to paint the company bikeshed, than over the allocation of funds to build a nuclear power plant.

The problem with the typical usage of “bikeshed” today is that there’s no nuclear power plant in the picture. It’s more likely to be a bunch of people on an email list discussing the best name for a proposed new method in Ruby, or something like that. Then someone who feels superior to the discussion (which would exclude the creator of Ruby, as well as many of his colleagues, associates, and friends) comes along and says “Bikeshed.”

But if we weren’t talking about method names, we’d be talking about literal constructors for runtime objects. And if not that, then perhaps the question of whether parentheses around parameter lists in method definitions should be mandatory. All of these things are important to people interested in the Ruby programming language; but, with respect, I will state unequivocally that none of them is as important an issue as nuclear power.

Furthermore, saying “bikeshed” implies that you think the group you’re addressing not only is wasting its time on the current topic, but has a history of spending too little time on important things. Even scaling it down so that the important things aren’t really important things in the nuclear power sense, no one ever says what those things are. That’s probably because “bikeshed” is just a snide way to say, “What you’re saying is stupid,” and not a unit of cogent or well-sustained argumentation of any kind.

Thus slide words. I’m glad there’s a name for them, even though it’s puzzling that the only person who seems to have heard the name is that guy at Harrah’s.

Back to top


July 6-12 is "Link To Something Other Than Wikipedia" Week!

Sat Jul 5 01:27:00 2008

During the week of July 6-12, I invite and encourage everybody who includes links in their email, blog posts, online chats, and other documents, to link to something other than Wikipedia.

I’m not trying to be a Wikipedia slayer. It wouldn’t matter if I were; that’s not going to happen.

I just want to remind everyone that there are thousands and thousands of interesting, well-informed, thought-provoking, educational websites out there, written by professors, researchers, doctors, artists, scientists, practitioners of every craft and industry—and however you slice it, these websites are getting a raw deal when it comes to links.

It’s not about whether Wikipedia articles are accurate or not. Some are, some aren’t. But that’s true of the whole Web. Let’s stop acting as if Wikipedia has some special status.

The best thing about the Web is that it isn’t an encyclopedia. And Wikipedia is evidence that when Web culture meets encyclopedia culture, encyclopedia culture wins. Sure, Wikipedia is collaborative. Most encyclopedias are. They still give off an aura of total, centralized, complete knowledge and authority. And that’s not very Web-like, is it?

So:

There’s a lot to learn at Wikipedia, but it’s time to spread the linkage!

Back to top


Co-Training with Erik Kastner

Sun Jul 20 12:31:00 2008

My friend and nearly-neighbor Erik Kastner is going to be joining me to teach the Ruby Power and Light course “Advancing With Rails” in Edison, New Jersey, August 18-21. This will be RPL’s first co-taught course, and I’m really looking forward to it.

See the calendar at Ruby Power and Light for more info!

Back to top


Pseudo-persuasion in online discourse

Wed Aug 6 11:57:00 2008

I know it’s pointless—I’m not going to make a dent in it—but I feel moved to say something about the biggest problem in online discourse: pseudo-persuasion.

The term is a bit awkward, but you’ll recognize what I’m talking about because it monopolizes an almost literally incredible proportion of email lists, news groups, blog comments, and IRC chats, and you’ve seen plenty of it. I’m talking about the endless stream of this vs. that. Emacs vs. vi, Ruby vs. Python, Ubuntu vs. Redhat, Mac vs. PC, tabs vs. spaces, and all the monumentally huge and boring rest of it.

Yes, there are interesting comparative points you can make about all of these pairings. Yes, some people make interesting points. I’m not talking about those points. I’m talking about the other 99.99% of online comparative talk, the inexhaustible store of “mine is better than yours” drivel, the vacuous chatter that, despite its vacuity, manages to choke and clog the online world as if it were of substance.

I call it pseudo-persuasion because it sounds like persuasive speech, but isn’t. It is persuasive neither in effect, nor in intent. Millions upon millions of words pour forth—arguments in favor of A and against B, checklists of assertions and accusations, praise of features and denouncement of shortcomings—all delivered in the most fervent persuasive language but not one syllable actually persuading anyone of anything, and not one syllable written in the expectation of persuading anyone of anything.

Have you ever said to yourself, “Gee, someone on IRC said that Emacs keybindings aren’t intuitive, so starting tomorrow I’ll switch to vi”? Have you ever met anyone who, after asking a question about a Linux problem and receiving an answer consisting of the single utterance, “OS X!!”, proceeded to run out and buy a Mac? Did you start using your current favorite programming language because someone told you, in so many words, that the one you had been using sucked and this one was better?

My late father used to say that “No one ever convinces anyone of anything.” He didn’t believe it literally, or he would not have bothered co-authoring the brief in Brown v. Board of Education. In general, he didn’t mean it with regard to legal and forensic argumentation. He did mean it, however, with regard to cocktail party chatter, exchanges among politically widely-separated colleagues, heated classroom arguments among students, and the like: day-to-day exchanges where the urge to state an opinion does not imply an inclination to take someone else’s opinion seriously.

Non-persuasive persuasion can serve a purpose. It’s good, for example, for students to put their thoughts into words, even though they’re not really listening to each other. Usually, though, it’s just a way to fill otherwise awkward social time.

When people yap at each other about Emacs and vi, however, it’s not filling awkward social time. To be honest, I don’t know what it’s doing. It certainly is not debate. It sounds like debate, and it uses rhetorical devices that are also found in debate. But it is not debate. No one can “win”, no one is listening to anyone else, and the likelihood of persuasion being achieved approaches zero. Nothing is at stake, and no one actually expects any conclusion, outcome, or productivity to emerge from the exchange.

But my case against pseudo-persuasion is not that the practitioners don’t take each other seriously enough. They hardly could, given how much of this crap there is. My case against it is that it’s a staggering waste of time, mental energy, and passion. Can you imagine what would have happened if, over the past couple of decades, participants in online forums had taken, say, five percent of the time they’ve spent pissing at each other, and used it instead to collaborate on software or technical writings?

Back to top


Back from RailsConf Europe 2008

Sat Sep 6 08:07:00 2008

I got home yesterday from RailsConf Europe 2008 in Berlin, and am very happy to say that the event was a major success.

It was particularly gratifying to hear from many attendees that they found the program content more advanced and more instructive than last year. It’s always hard to fine-tune the level of talks across a big program like this, and I’m really glad to have evidence that people overall felt it had gone in the right direction.

Highlights included keynote addresses by David Heinemeier Hansson and Jeremy Kemper, as well as a Rails core team panel discussion with David, Jeremy, and Michael Koziarski. DHH led us through some very interesting thoughts on the notion of “legacy” code, and how that concept plays out with respect to one’s own development and growth as a programmer. Jeremy talked about performance, and masterfully expanded the horizon beyond the shop-worn “Does Rails scale?” stuff to some very specific and powerful techniques for evaluating and adjusting performance.

We also held a “Symposimi” (the name is based on a misspelling in the program; it should have been “Symposium” but came out “Symposimi,” and I decided that sounded really cool!) on the subject of Ruby versions and implementations—who’s using what, what’s targeting what, the pros and cons of moving to 1.8.7 and/or 1.9. A symposimi is a town-meeting-like gathering of people who want to ask and answer questions about a topic. It’s more audience-based than a symposium, and less hierarchical.

The symposimi was fun for me because I got to do some live code demos, which I usually don’t at the conferences I’m an organizer of!

Lots of people asked about next year. We don’t know yet where RailsConf Europe will be in 2009. Probably not Berlin, just because we’d like to move it around. If you have suggestions (and a rationale other than that you happen to live there :-) by all means let me know.

Now that RCE2008 is over, I’m looking forward to RubyConf. Stay tuned for announcements of the program and registration!

Back to top


Tracks a-go-go at RubyConf 2008!

Sat Sep 13 10:00:00 2008

Ruby Central is gearing up for RubyConf 2008, which has a fantastic program and which you can still register for (at time of writing, anyway!).

People have noticed, naturally, that we’ve gone over entirely to a multi-track format (except for keynotes and a couple of other special slots). And they’re surprised; we used to be one-track, and then last year we were multi-track but with a good dose of plenary sessions.

So I thought I’d say something about the multi-trackedness of RubyConf 2008, for anyone who’s interested.

The bottom line is that we’ve scheduled multiple tracks because we got so many really, really good proposals. Of course we can’t accept all of them; we can’t be that multi-track. There will always be a cutoff, and where the cutoff comes always involve a judgment call. This time around the judgment was that the number of talks we’d have to exclude, in order to dilute the multi-trackedness significantly, was too great.

In fact, we started drafting a schedule without explicitly discussing the multi-track issue; it mostly emerged from what we jotted down, and then it continued to make sense to us as we started analyzing the track issue more closely.

People have asked whether it’s about the size of the event. It is, in a couple of ways—subtle ways, perhaps, but important.

For one thing, we know that not every speaker is comfortable getting up in front of 500 people. Lots are, but it’s still a lot to ask. Breakout sessions make for situations in which more speakers are likely to be comfortable.

Of course, if there are only fifteen speakers, we could easily find people who don’t mind a big audience. But what about that “only fifteen speakers” thing?

In a conference with 400-500 people present, it’s definitely more fun if, say, twelve percent of the people prowling the halls and sitting next to you at lunch are speakers, instead of two or three percent. Having fifteen speakers at an event with over 400 people isn’t the same, for anyone, as having fifteen speakers at an event with sixty people. If the ratio is too lop-sided, it gets too much into the “us and them” thing. We’ve never been into that.

Another reason we’re OK with moving toward a multi-track format is the proliferation and success of the Ruby regional conferences, many of which are one-track. Everyone should attend, at some point, a one-track conference. It’s really cool the way everyone at such a conference shares the same experience. My first conference was a one-track academic film conference in 1985, and it was great. And the wonderful flowering of the Ruby regional conference culture means that, even if it isn’t at RubyConf, many Rubyists will get a chance to have that experience.

We started our regional conference grant program in 2006 in the hope that “regional” wasn’t going to mean “provincial”—that regional conferences could be top-notch events—and that hope has been fulfilled beyond what we could possibly have wished for. (And certainly way beyond what we can take credit for. The regional organizers have been amazing!) These high-quality small events can address many needs and desires, including the desire for the experience of a one-track format.

In sum, the RubyConf format for 2008 is a format for its time, its year, its configuration of the Ruby world. We’re nothing but excited about it and hope you’ll come and share the fun!

Back to top


Why I am suspicious of the bailout bill

Fri Oct 3 21:14:00 2008

The bailout bill has just passed. I know very little about economics, little enough that I don’t feel entitled to a strong opinion one way or the other on whether the bill should have passed. But I am suspicious of it.

I’m suspicious of it, for one thing, because of the fear-mongering that has surrounded it; it’s very reminiscent of the ongoing “Terrorists will come and kill your family if the executive branch doesn’t get a blank check for waging undeclared war” campaign, and things in that vein.

But I’m even more suspicious of the bill because of all the rhetoric about how it will help “Main Street” as well as “Wall Street”. I don’t know whether it will or not, but what troubles me is the fact that this kind of rhetoric makes it sound like Congress and the Bush administration are desperate to help Main Street. The fact is that, in general, they’re not.

Every microsecond of every day in the history of this country there have been uncountable opportunities for the government to help citizens with financial problems, difficulty paying for a home, lack of job opportunities, inability to get credit, and all the rest of it. The thrust of the behavior of the government for most of the history of the country has been not to bother helping such people to any significant degree.

Now, all of a sudden, helping Main Street leaps to the front of the congressional and executive agenda. I’m disinclined to buy it. If the common weal were really a government priority, we would have known by now. I find it immensely suspicious that the greatest outpouring of social concern, at least as measured in money, comes tethered to a Wall Street bailout.

If Main Street is going to benefit from the delivery of a de facto blank check to Wall Street, surely it would not benefit any less from having money delivered to it directly. But you don’t hear any talk of, say, the government purchasing houses for the victims of fiscal mismanagement. I suppose it would have taken too long to draft a bill that did that; and as we know, the earth would have left its axis if the bill had not been passed this week….

Back to top


RESTful Rails for the restless

Mon Nov 24 12:18:00 2008

QuickStarts-R-Us

As one of the most active Rails trainers on the circuit, I come up a lot against the challenge of introducing RESTful Rails to relative newcomers. It’s a challenge because the REST support in Rails is very high-level and, even for the diligent, basically impossible to understand deeply without a knowledge of the subsystems—in particular, the routing system—on which it is built.

I believe it’s possible, nonetheless, to understand up front how the RESTful support in Rails fits into the subsystems that support it; and I believe that it’s beneficial to gain such an understanding. My purpose is thus to provide a “QuickStart” introduction, not to the practice of writing RESTful Rails applications but to the way the REST support in Rails fits into what’s around and beneath it. If you want to do RESTful Rails but either find it too magical or don’t quite understand how it relates to the framework overall (does it add? supersede? enhance?), then this article may be of interest to you.

You may wonder why I’m not making use of the Rails scaffolding. That is, as they say, “a whole nother” story. Short answer: the scaffolding gives you a quick start, but also a quick end. It explains nothing and leaves you with a lot of work to do to reverse the ill effects of having a lot of “one-size-fits-none” code lying around your application directory.

So no scaffolding. Also, no REST theory—but by all means have a look at the theory once you get into the practice. It’s just not my focus here.

In what follows, I’ve tried to be concise—minimalist, almost. I’d advise not skimming over anything, even if you think you already know it. I’m chosing the path carefully. If you don’t trust me as a guide, that’s another matter entirely :-) If you do, welcome.

What a (non-RESTful) Rails application does

The job of a Rails application is to provide responses to requests. Responses are generated by controller actions, which are (in Ruby terms) instance methods of controller classes.

When your application receives a request, the first order of business is to figure out which action to execute. The subsystem that does this is the routing system. It’s the routing system’s job, for every request, to determine two things:

1. controller
2. action

If it cannot determine those two things, it has failed, and you get a routing error. If it can, the routing has succeeded. End of story. (You might get a “No such action” error, but that’s not the routing system’s problem. The routing system has done its job if it comes up with an action, whether the action exists or not.)

The main information that the routing system uses to determine which controller and action you want for a given request is the request URL. By definition, every URL that’s meaningful to your application can be resolved to a controller/action pair. If the URL contains information beyond that which is needed to determine a controller and action, that information gets stored in the params hash, to which the controller action has access. (That’s how you get params[:id], for example.)

The routing system uses a rule-based approach to resolving URLs into controller/action pairs. The rules are stored in routes.rb. A rule might say, for example (paraphrased here in English), “A URL with (1) a string, (2) a slash, (3) a string, (4) a slash, and (5) an integer means: execute action (3) of controller (1) with params[:id] set to (5)” (and indeed the default routing rule says exactly that). Rules can be specific, to the point of silliness. It’s perfectly possible to program the routing system so that “/blah” means: “the show action of the students controller with params[:id] set to 1010.” There’s almost certainly no point in such a mapping, but the point is that you can program the routing system in a fine-grained way.

In the non-RESTful case, the URL is all that the routing system needs to do its job of performing a rule-based determination of a controller and an action.

In the RESTful case, it isn’t.

Enter the verbs

This is the crux of RESTful routing in Rails. Everything else flows directly from this, so make sure you understand it.

Instead of routing based solely on rule-driven mapping of each URL to a controller/action pair, RESTful Rails adds another decision gate to the chain: the HTTP request method of the incoming request. That method will be one of GET, POST, PUT, or DELETE. It’s the combined information—URL plus request method—that the RESTful routing uses to determine the controller and the action.

That means that for every incoming request, the correct controller/action pair is determined not per URL, but per URL per request method. That, in turn, means that a given URL, such as this:

  http://blah.blah/houses/14

might map to two or more different controller/action pairs. It all depends on the HTTP request method.

In theory, any one URL can be routed to as many as four controller/action pairs, because any one URL can be used in a GET, PUT, POST, or DELETE request. In practice there aren’t that many permutations, because some combinations of request method and URL semantics are not meaningful. But the principle is what matters: a single URL no longer has an unambiguous meaning, but must be interpreted in conjunction with the request method.

Furthermore, these conjoined interpretations are hard-coded to a pre-determined set of seven actions: index, show, delete, edit, update, new, and create. (You can add custom ones, but those are the canonical ones.) For example, the “houses” URL above, if requested as a GET, automatically routes to the show action of the houses controller, with params[:id] set to 14. If submitted with a PUT, it goes to the update action. A URL with no id field (/houses) goes either to index or to create, depending on the request method. And so forth.

That, as I say, is the crux of the matter: routing based on URL plus request method. Keep this in mind as you get into the details and bells and whistles of RESTful Rails.

Interpreting requests, though, is only half of the job of the routing system. The other half is the generation of strings.

RESTful URL generation

When you write this in your view:

  <%= link_to "Click here for help", :controller => "users", :action => "help" %>

your view ends up containing this:

  <a href="/users/help">Click here for help</a>

It’s the routing system that does the job of processing the link_to arguments and figuring out what the URL (or, in this case, the relative path) in your tag should consist of.

The same thing happens with RESTful routing, except that you never have to spell out the controller and action. Instead, you call yet more helper methods. Compare this:

  <%= link_to "User profile for #{user.name}",
               :controller => "users", 
               :action => "show",
               :id => user.id %>

with this:

  <%= link_to "User profile for #{user.name}", user_path(user) %>

You don’t have to define the method user_path. It comes into being automatically, when you write:

  map.resources :users

in routes.rb. And it has a simple job: return the right string, in this case the string ”/users/14” (assuming that user.id is 14).

For every resource you route, you get a fistful of such methods: user_path(user), users_path, new_user_path, and edit_user_path (plus all of these with _url instead of _path). These methods do nothing but generate strings. They have no knowledge of request methods or REST. In fact, they’re just examples of named routes—methods that generate the right strings for specific routing rules—and you can use named routes in routes.rb even without REST. The only REST-related special treatment is that map.resources automatically writes a bunch of these methods for you. You can think of map.resources as, primarily, a macro that writes named route methods, much as attr_accessor automatically writes getter and setter methods.

The specifics of what the various RESTful named route methods do is for future study. The point here is to see the roadmap. You do map.resources :users, and from that point on, you can use methods in your views to create URL strings, rather than having to spoonfeed the information about which controller, action, and id are involved.

But that still leaves the question of the request method. How does ”/users/14” know which action to trigger when clicked?

Specifying request methods

When you write view code that generates path strings (with link_to, form_for, link_to_remote, etc.), you want the right string, obviously, but you also need the link, when clicked, to use a particular HTTP request method for the request. Otherwise the RESTful routing system won’t have enough information to make sense of the URL.

The helper methods that generate hyperlinks all have sensible HTTP request method defaults (which you can override if needed). link_to generates a link that will submit a GET request. form_for generates a POST form tag (method=“post”), unless you tell it to use PUT (which is conventional for update operations, as opposed to new record creation operations), and so forth.

Again, the named route methods don’t have request method intelligence. The enclosing hyperlink-writing methods (link_to and friends) do. They just used the named route methods as lower-level helpers for the specific purpose of generating the right strings.

Invisible ink

One of the challenges of using RESTful routing in Rails is that you end up with not very much information available to you visually. When you write a RESTful form in your view, let’s say for an update:

  <% form_for :house, :url => house_path(@house.id),
                     :html => { :method => :put } do |f| %>
  <% end %>

you never see the word “update” in routes.rb, nor in the URL, nor in the view templates, nor in the HTML source of your rendered views. You just have to know that a thing_path-style named route, coupled with a request method override to PUT (override of the default POST for form_for, that is), will result in a form that, when submitted, will send a PUT request to the update action of the houses controller. And you have to trust that the routing system will succeed in so routing it.

RESTful routing pushes most of the routing intelligence—which, as you now know, means the determination of a controller/action pair from an incoming request—under the surface. You have to learn how the REST-ified routing system thinks. The early phases of learning RESTful routing tend to involve memorizing the combinations of named routes and request methods, and which action they point to. The good news is that there’s a finite number of them, and they make sense. If it seems like routing soup, hang in there and look closely at the logic. It will come clear.

The rest…

That’s the basics. There’s a lot more to it, including (but not limited to) more “magic” shortcuts. But if you get the basic ideas you’ll be in good shape.

Now go forth and REST. Oh, one more thing. Here’s a chart I once made, showing how the named routes map through the request methods to the seven canonical actions. The chart uses the _url methods (which give you the whole thing, including http://), but the _path versions would exist too.

RESTful routing chart

Back to top


Probative Programming: the physical unification of code and tests

Sun Nov 30 13:05:00 2008

I’m encouraged by a couple of recent conversations to go public with this possible wacky idea. It has to do with code and testing.

I’ll start with the idea, and then say something about why I’m thinking along these lines.

The idea is for a programming system designed in such a way that the code and its tests are physically together, in one file. Furthermore, that file is not executable. You have to run it through a dedicated filter utility to generate the actual code file(s) from it.

So it’s a bit like, and indeed inspired by, Knuth’s Literate Programming, where the code and its documentation are fused together in a single file which contains both but is, itself, neither. You can’t execute that file; you have to generate the real code files from it.

Adapting the master-file idea to testing, as I envision it, would also entail the following constraint: that the system would refuse to generate the code files unless the code involved already had tests, and those tests passed. In other words, the whole system would militate against using untested code in production, by physically obstructing the creation of executable code files for untested stretches of code.

It seems to me that this would make for a much more sensible and efficient flow of energy than what we’ve got now. What we’ve got now are separate files, and therefore the possibility of running untested code. As long as that possibility exists, people will run untested code. Reordering things so that the creation of the executable code comes after the successful test run would, potentially, realign the energy of the whole process in a very productive way.

As things stand now, the energy is flowing in a wrong and wasteful way. The evidence for this is sociological, at least as much as it is technical. Thorough testing involves keeping the code and the tests in contact with each other through willpower and force, like holding like ends of two magnets together. Therefore, people who test consistently end up with bragging rights, which they often exercise. I hasten to add that I’m not talking about the really accomplished, masterful engineers of the great testing frameworks we’ve got available to us. Those people are above bragging. But there’s a sub-population that isn’t.

I’m really tired of seeing the test police needling people about not having written tests. It’s not that people shouldn’t write tests. Like I said, it’s about the energy flowing the wrong way. The whole culture of test machismo is, start to finish, a waste of energy and, above all, doesn’t work. You can’t get the whole world to write tests by trying to shame people into it, one person at a time. As long as the technical conditions allow for untested code, untested code there will be.

So we’ve got untested code, alongside a culture of testier-than-thou assertiveness. Neither is good.

And then there’s the programming should be fun thing. Programming should be fun. Testing should be a big part of programming. Therefore, testing should be fun. However, it’s acquired a sort of “do it because it’s good for you” aura, like using a treadmill or eating your vegetables. Again, this take on testing is wasteful and irrelevant—but it arises directly from the physical possibility of running untested code, and will not go away as long as that possibility exists.

I’ve made some very sketchy, preliminary attempts to see what a Probative Programming file might look like, for a Ruby program. It’s a daunting task, and one I may or may not ever succeed at. But I’m convinced that something along these lines is both possible and desirable.

Finally, if there are existing systems that do what I’m describing, or anything substantially similar to it, I’d be interested in hearing about them.

Back to top


On the menu this season: Muslims and gays

Sun Dec 21 15:59:00 2008

Don’t get me wrong. I’m not saying that other forms of hate and prejudice are extinct, or even on the wane. But it feels like the stars anti-Muslim sentiment and homophobia are in the ascendancy.

It’s very much about statements that don’t sound aggressive or hateful, on the surface, but that would never be made if hate didn’t lurk just below. I’m thinking, for example, of a report I heard on the radio of some attack or other, involving “three Muslims of middle-eastern descent.” I might have the phrasing of the “middle-eastern descent” part wrong (though it was that or close to it). In any case, the salient bit, for me, was “three Muslims.”

When was the last time you heard a crime described as having been committed by “three Christians”? How about “A Jew broke into a convenience store…”? So what’s up with “three Muslims”?

What’s up, of course, is hate. I don’t think the radio announcer or the newswriter hates Muslims. But they do operate under a compulsion to mention explicitly that Muslims are Muslims, and ultimately that’s so that the listenership can be put on alert to hate them. Does the phrase “three Muslims” have explanatory power? Did these people do whatever they did because they are Muslims? No. There’s no reason to mention their religion except out of habit of mentioning the fact that Muslims are Muslims.

Back when I was a university professor (1992-2005; in this case somewhere around 2003, I think), the school newspaper had a kind of “person-in-the-street” feature, where they’d ask a few people around campus a question and print selected answers. One week, the question was something about Iraq. One of the people quoted in the feature said something along the lines of, “Bomb them all off the face of the earth.” Or “Blow them all up”—words to that effect.

My response was to call the editor-in-chief of the newspaper into my office and have a little chat with him. I was under no institutional imperative to do so—I was not involved with the paper directly—but it seemed to me that I had an opportunity to teach him perhaps the most important lesson of his college career. “If the question of the week had been about how to improve the cafeteria food,” I asked him, “and someone had said, ‘Line the whole cafeteria staff against the wall and shoot them dead,’ would you have printed it?”

Of course he would not have, and said that he would not have. “The fact that what we would not say about the cafeteria workers, we would say about the entire population of a Muslim country,” I explained, “is the dehumanization process at work.” I do believe he understood and took my point on board.

So we mention that people are Muslims, and we lower the bar when it comes to suggesting (or, if you like, joking about) their violent deaths. And it’s all very dangerous and should be sending up serious alarms.

Labeling the gay as gay is an even more popular pastime. The world has settled for a breathtakingly stunted view of what homosexuality entails, and how it manifests itself. It manifests itself, by the way, as itself, not as an obsession with the song “YMCA” or an expertise in designer footware. Hey, more power to you if you have that expertise. But the set of all men who do intersects in a miniscule subset with the set of all men whose primary sexual orientation is toward men. Ditto for all the stereotypes.

Of course, the world can’t deal with the idea that homosexuality manifests itself only as itself, because if that’s true, it means you can’t tell who’s gay; and that, like being unable to tell who’s Jewish, is unacceptable. The workaround is to pretend that you can tell who’s gay, resorting to babytalk about your “gaydar” when the stereotypes, as they must, fail you.

And then, following a fairly tight train of thought, there’s hatred of gays.

First of all, let me explain that I include, as hatred, the “love the sinner, hate the sin” horseshit espoused by the Catholic church. It is, to be sure, a kinder, gentler hatred than the burning-at-the-stake kind. The idea is that you’re enlightened enough to acknowledge that some people just are gay. But you also understand that, as gays, they must never indulge in the kinds of sexual activities they feel interested in. So you, as the compassionate believer, offer to contribute to their happiness by giving them support and encouragement as they fight to maintain their chastity.

How noble.

The church, of course, has two thousand years of experience disguising hate as love. But this one is particularly devious and malign. Let’s cut to the chase: the only reason that one adult human being would try to stop another adult human being, on a lifelong basis, from attaining romantic and/or erotic satisfaction is that he or she (human one) hates him or her (human two). No amount of theological stroking can change that. It’s hate.

Not news, of course, that the Pope and friends hate gays. But interesting to see how slimy and prurient they can get, in the process. Anyway, let’s move on.

Actually we can borrow a concept from the church: “invincible ignorance.” When I read the stuff about homosexuality being a choice (note that it’s not that sexual preference is a choice, just homosexuality—which makes it kind of weird to describe it as a choice), my reaction is that if you put twenty articulate, knowledgeable people in a room for twenty years with the person who’s taking the “choice” position, that person would emerge still saying that homosexuality is a choice. There’s no point of entry for explanation, and no point of contact with reality.

It’s pathetic, but I still count it as hate. At least it leads to hate. Or from hate, perhaps. Or maybe these people are actually choosing to be vicious, and could stop themselves if they really wanted to. It’s hard to know. They’re not saying.

With gay marriage on the news radar these days, more and more of this kind of discourse is showing up: the choice thing, but also the “gays recruit people” thing (which is actually backwards; have these people ever watched television commercials?) and, most disturbingly of all, the “gays prey on children” thing. And each of these things embodies two problems: first, that people believe it; and second, that it’s acceptable to say it publicly.

Which hateful statements are acceptable and which aren’t is a kind of lump under the carpet that moves around but never goes away. Unfortunately, the underlying hate never goes away either—and ultimately, no matter which targeted people or groups we’re talking about, it’s the underlying hate that matters. But who gets to say what, and when, and with what consequences (or lack thereof) is, in itself, something that I think it’s worth keeping fairly close tabs on.

Back to top


Cool wishlist management at WishSight!

Mon Dec 29 15:13:00 2008

Announcing the opening of WishSight!

WishSight is for managing wishlists and gift-giving. It lets you see who’s given (or promised) what to whom, and it lets gift-givers for particular people communicate with each other, via a comment-board, so that they don’t duplicate gifts.

It’s based on a Christmas-list application I wrote in 2005 that my family and friends have been using every year since then. It’s completely merchant-unaffiliated. You can post links for the gifts you want, and they can be links to any merchant.

WishSight helps you cut down on gift duplication, and increases the chances that people will get things they actually want, without the gift-givers having to do a round-robin of email or phone calls to pin down who’s buying what. And chances are they don’t all know each other anyway—which doesn’t matter on WishSight, because you all communicate by leaving comments directly on your mutual friend’s wishlist.

All you have to do is:

There’s no stealth: the email addresses are only used internally to determine who’s allowed to see whose wishlist. Also, you can list email addresses even if the people haven’t signed up yet. Once they do sign up, they will automatically have permission to see your wishlist and claim your wishes. No two-sided “handshakes” required; you just whitelist people.

Have fun, and let me know if any questions or problems!

Back to top


10 things to be aware of in moving to Ruby 1.9

Wed Jan 14 19:21:00 2009

Update: There’s a sequel to this post, called Son of 10 things…

I’ve been writing a lot about Ruby 1.9 (my book The Well-Grounded Rubyist is due out in a couple of months), and I thought I’d share my personal list of things you need to be careful of as you go from 1.8 to 1.9. This is not a list of changes; it’s a list of changes that you really need to know about to get your 1.8 code to work in 1.9, things that have a relatively high likelihood of biting you if you don’t know about them.

Strings are no longer enumerable

You can’t do string.each and friends any more. This has an impact, for example, on the Rack interface, where there has in the past been a requirement that the third item in the returned array respond to each.

Block argument semantics

This is a big change, and a big topic. The salient point is that when you do this:

  array.each {|x| ... }

the block parameter list is handled like a method parameter list. In 1.8, blocks use assignment semantics, so that @ is like @x=. That’s why in 1.8 you can do:

  array.each {|@x| ... }

(assign to an instance variable) or even:

  array.each {|self.attr| ... }

(call the attr= method on self). You can’t do those things in 1.9; the parameters are bound to the arguments using method-argument semantics, not assignment semantics.

Block variables scope

Block parameters are local to the block.

  x = 1
  [2,3].each {|x|  }

In 1.8, x would now be 3 (outside the block). In 1.9 the two x’s are not the same variable, so the original x is still 1.

However, a variable that (a) already exists, and (b) is not a block parameter, is not local to the block.

  x = 1
  [2,3].each {|y| x = y }
x is now 3. If you want or need to shield your existing variables from being used inside the block, declare variables as block local by putting them after a semi-colon in the parameter list:
  x = 1
  [2,3].each {|y;x| x = y }

x is still 1.

Method argument semantics

Method arguments do some new things too. In particular, you can now put required arguments after the optional argument glob parameter:

  def my_meth(a,*b,c)

There aren’t too many situations where you’d want to do this (though there are one or two).

The * operator has changed semantics

Compare 1.8:
  >> a = [1,2]
  => [1, 2]
  >> *b = a
  => [[1, 2]]
  >> b
  => [[1, 2]]

and 1.9:

  >> a = [1,2]
  => [1, 2]
  >> *b = a
  => [1, 2]
  >> b
  => [1, 2]

I’ve always interpreted the * operator in the following way:

The expression *x represents the contents of the array x, as a
list.

In 1.8, *b = [1,2] means that [1,2] is the contents of the array b, which means that b is [[1,2]]. The 1.9 semantics don’t seem to behave that way. I’m not sure what the new general rule for * is, or whether maybe I was wrong that there was such a rule that governed all cases (though I can’t think of an exception).

Hashes are ordered

This isn’t likely to bite you but it’s something to be aware of, both in your own code and in looking at the code of others. Hashes are ordered by insertion order. Reassigning to a key does not change the insertion placement of that key.

method and friends return symbols

Expressions like obj.methods and klass.instance_methods return symbols instead of strings in 1.9. That means that you might have to do to_s operations on them, if you need them as strings. However…

Symbols are string-like

... symbols have become very string-like. You can match them against regular expressions, run methods like #upcase and #swapcase on them, and ask them their size (i.e., their size in characters). I’m not sure what the purpose of this is. I’d just as soon have symbols not be any more string-like than they absolutely have to be.

Gems are automatically in the load path

When you start Ruby (or irb), your load path ($:) will include the necessary directories for all the gems on your system. That means you can just require things, without having to require rubygems first. You can manipulate the load path per gem version with the gem method.

Lots of enumerable methods return enumerators

Called without a block, most enumerable methods now return an enumerator. It’s fairly unusual to use the return value of blockless calls to map, select, and others, but it’s worth knowing that now you cannot assume that, for example, Array#each will always return its receiver.

You can use this feature to chain enumerators, though the circumstances in which chaining enumerators really buys you anything are pretty few. I don’t know of a case where you would do this:

  array.map.other_method { ... }

with the exception of map.with_index. The map call is essentially a pass-through filter here. (This was not true in early versions of 1.9, where you could attach knowledge of a block to a chained enumerator, but that behavior was removed.)

Incidentally, you win the prize (which is endless glory :-) if you can account for the difference between these two snippets:

  >> {1 => 2}.select {|x,y| x }
  => {1=>2}
  >> {1 => 2}.select.select {|x,y| x }
  => [[1, 2]]

It’s all about enumerators….

If you’re careful about these changes, and keep an eye out for others, you should be able to continue to have fun with Ruby in version 1.9 and beyond!

Back to top


Son of 10 things to be aware of in Ruby 1.9!

Fri Jan 16 14:20:00 2009

I’m happy to see that my recent 10 things to be aware of in moving to Ruby 19 article has proven helpful to lots of people. This article is a follow-up.

The goal of the article was to point out 1.9 features and changes that might cause your existing code not to run correctly, or not to run at all. I went a bit soft, though: two of the original ten (hashes being ordered and the changes in method-argument syntax) weren’t really things that might break your 1.8 code.

So I feel I owe the world two more code-breaking 1.9 features! And they’re here, along with a bonus one.

But first, some links

The denizens of ruby-talk have provided lots of helpful ideas and feedback. James Edward Gray II and others mentioned M17N, a topic on which I defer to the more expert among us, especially James who has written a multi-part M17N guide. He’s going to be expanding it to include 1.9 encoding, so keep an eye on it.

Brian Candler suggested that people might be interested in the presentation by me and Dave Thomas at RubyConf 2008 on Ruby 1.9: What to Expect. We cover some pitfalls but also some new, non-pitfall features you might want to know about.

If you’re interested in Ruby 1.9 generally, you might be interested in my forthcoming book The Well-Grounded Rubyist, which is a fully revised, revamped, “Ruby only” second incarnation of my 2006 book Ruby for Rails.

Apologies to anyone I’ve failed to credit, and thanks to all for the feedback.

And with that, here are the pitfalls! (Speaking of pitfalls, I think I’ve remembered all the <pre> tags this time….)

String indexing behavior has changed

(Thanks to Michael Fellinger and Robert Dober)

In Ruby 1.8, indexing strings with [], as in "string"[3], gives you an ASCII code:

  >> "string"[3]
  => 105

In order to get a one-character-long substring, you have to provide a length:

  >> "string"[3,1]
  => "i" 

In Ruby 1.9, the indexing operation gives you a character.

  >> "string"[3]
  => "i" 

Also, kind of along the same lines, the ?-notation now gives a character rather than a code. In 1.8:

  >> ?a
  => 97

and in 1.9:

  >> ?a
  => "a" 

if-conditions can no longer end with a colon

In 1.8 you can do this:

  if x:
    puts "Yes!" 
  end

In 1.9, you can’t use that colon any more. The same is true of when clauses in case statements. This will not parse in 1.9:

  case x
  when 1: "yes!" 
  end

Bonus thing! No more default to_a

In 1.9 you cannot assume that every object has a to_a method. You’ve probably seen warnings about this in 1.8, and the day of reckoning has now arrived.

  >> "abc".to_a
  NoMethodError: undefined method `to_a' for "abc":String

You can use the Array method to turn anything into an array. If it’s an array already, it returns the object itself (not a copy). If it’s anything else, it tries to run to_ary and to_a on it (in that order), and if those aren’t available, it just wraps it in an array.

Array isn’t new, but we’re likely to be using it a lot more now that there’s no default to_a operation.

Have fun!

Back to top


RailsConf registration (and a hiatus year for RailsConf Europe)

Fri Jan 23 22:31:00 2009

Registration is now open for RailsConf 2009 (May 4-7). You can get more details, and register, at the RailsConf 2009 website.

RailsConf is taking place in Las Vegas, one of my favorite cities. Yes, I know what a weird and ironic place it is. But for whatever reason, I’ve always found it extremely enjoyable. May is a good time to go—hopefully not to hot to step outside!

There’s a lot going on at RailsConf this year, highlighted by its timing in the wake of the Rails/Merb merger decision. There will be lots of merger news and highlights, along with the usual great lineup of talks and, above all, the chance to meet and get to know other Rails developers as well as Rails core team members, authors, bloggers, and pretty much the whole gang!

A hiatus year for RailsConf Europe

Ruby Central and O’Reilly have decided to take a hiatus from producing RailsConf Europe this year, for the simple reason that it didn’t bring in enough revenue last year to justify doing it again, particularly given the tight economy and the need to err on the side of caution. RailsConf Europe has always been a really great event, and people who go to it really love it, but we need a year of retrenchment while we figure out how to get everyone else to realize how great it is! Plans for 2010 are not certain yet; we’re taking it one year at a time.

Meanwhile, the Ruby and Rails communities continue to produce an astonishing number of high-quality, uniquely branded and flavored events. I’m not even going to try to list them all here. Do a search, though, and you may very well find one near you.

Back to top


Why athletes thanking God for victories is stupid

Tue Feb 3 01:38:00 2009

I hate it when athletes thank God when they win. My reasons for hating it have nothing to do with my own atheism. I hate it because it’s narcissistic and because it’s theologically infantile.

If you win a game and then thank God, and do not thank God when you lose, you are going on record as believing that God wanted you to win, and that a victory by your opponent would have represented a thwarting of God’s plan.

But how do you know? Isn’t it possible that losing is what God has planned for you, and that it will do you good? Maybe losing will strengthen your character. Maybe your opponent needs the win (or the prize money) more than you do, and God somehow managed to figure that out in spite of being dazzled by your greatness. Maybe you should be thanking God for protecting you from the sin of pride by not letting you win a spiritually meaningless, entirely earthly contest.

But I’ve never seen an athlete drop to his or her knees and thank God after a loss. Why not? Because the ones who thank God when they win have a dinky, anthropomorphic conception of God. Their God is “the man upstairs,” the Santa Claus figure, the parent who may or may not give them the birthday present they want. And to hell with the other kids. Me, Me, Me.

So what gives? Where does this all come from? Whose big idea was it to thank God only for bringing about what they themselves wanted to happen anyway?

Let’s go back to ancient times. Things were different with respect to thanking gods, because there were lots of gods and the gods took sides in the contest. It made sense for the Greeks to thank Athena for the victory over the Trojans because Athena was, at some Olympian level, duking it out with Ares and Aphrodite. The Greeks’ powerful friends prevailed over the Trojans’ powerful friends. And the Greeks understood that someone had actually made an effort on their behalf, faced uncertainty, and prevailed. So they thanked her.

Dear athlete: Do you think that God faces uncertainty when you play a tennis match?

Do you think that God has to make an effort on your behalf to make sure you win?

Do you think that God’s enemy is rooting for your opponent?

And if you don’t think all that, what exactly are you thanking God for when you win? I mean exactly. Not just vaguely that you’re happy, and happiness feels good, so it must come from God. That’s theological babytalk.

The best thing that can be said about thanking God for an athletic victory and not for a loss is that it’s an ignorant corruption of what was a perfectly reasonable pagan practice. If you’re a monotheist and thank God for a win, you’re making a statement about your own inherent worth, and what you believe is God’s opinion of that worth, in comparison to the inherent worth of your opponent. You’re asserting that your victory is of the Lord to an extent that a victory by your opponent would not have been. And you’re implying unmistakeably that your opponent is in league with God’s enemy.

In other words, thanking God for an athletic victory is stupid, uninformed, thoughtless, self-absorbed, and about as far from anything religious or spiritual as you can get. I understand the whole thing about religion not being the same as rational thought. But this isn’t even the same as religious thought. It’s just vanity.

Back to top


Ruby training in Atlanta, April 1-3!

Mon Feb 16 14:50:00 2009

Want to learn Ruby, or improve what you already know? Come to Atlanta!

Ruby Power and Light and ENTP are teaming up to present a three-day Ruby course in Atlanta. You can get more info, and register, here.

Training will be by me and Ruby developer/author Jeremy McAnally (“mrneighborly”). And Rick Olson (“technoweenie”) will be there too, helping with the training and sagely dispensing Ruby wisdom and advice. (Seriously!) It will be at the Georgia Tech Hotel & Conference Center.

Please email me if you have any questions. Otherwise, see you there!

Back to top


Did I mention Ruby training in Atlanta, April 1-3?

Sat Mar 14 14:21:00 2009

The answer is…yes! I did mention it. But I’ll mention it again.

Want to learn Ruby, and learn it right?

Come to Atlanta for three days and learn Ruby from:

You gotta better way to learn Ruby?

I doubt it. Just read that list of instructors again… and you get training materials, a book (“Ruby in Practice”), and lunches.

There’s registration info here, and you can contact me directly with any questions.

Hope to see you there!

P.S. If you’re a Ruby expert but have friends or co-workers or employees who could use an accelerated intro/intermediate course, send them along!

Back to top


Is this an early use of the slang "cool"?

Sat Mar 21 01:22:00 2009

Here’s a passage from The Man in Lower Ten by Mary Roberts Rinehart, published in 1906. I’ve included some context but the main thing I’m interested in is the appearance of the word “cool” in the second paragraph.

“Nonsense,” he said. “Bring yourself. The lady that keeps my boarding-house is calling to me to insist. You remember Dorothy, don’t you, Dorothy Browne? She says unless you have lost your figure you can wear my clothes all right. All you need here is a bathing suit for daytime and a dinner coat for evening.”

“It sounds cool,” I temporized. “If you are sure I won’t put you out—very well, Sam, since you and your wife are good enough. I have a couple of days free. Give my love to Dorothy until I can do it myself.”

I can’t see what “cool” means in the second paragraph, other than “cool” in the slang sense that we use it. My understanding is that “cool” in that sense started, or at least came into common usage, during or after World War II. In any case, 1906 seems insanely early for it.

But what else could it mean in the quotation above? The wardrobe described in the first paragraph doesn’t suggest a particularly cool climate. Is there some other nuance of the word I’m not getting?

I shall leave comments open on this one, at least until the spam gets intolerable.

Back to top


Envycasts featuring David A. Black: Ruby 1.9: What You Need To Know

Tue Apr 21 23:10:00 2009

I’m pleased to report that Rails Envy has released the Envycasts Ruby 1.9: What You Need To Know, Part 1 and Part 2, in which I introduce you to some important Ruby 1.9 features, tricks, techniques, and a few pitfalls.

The envycasts are $9 each, or you can get them together for $16

The topics include lots of stuff about built-in classes (String, Array, Hash, etc.), an introduction to Enumerators, syntax changes in 1.9, and lots more.

I think you’ll find them instructive, and I hope you enjoy them!

Here’s a sample—go to the Envycasts page for more info.


Back to top


"The Well-Grounded Rubyist" now available in PDF!

Tue Apr 21 23:15:00 2009

It’s been a busy few days, with the release of not my Ruby 1.9 Envycasts but also the PDF version of my new book The Well-Grounded Rubyist.

TWGR is an expanded, updated, Ruby-only reworking of my 2006 book “Ruby for Rails”. It targets Ruby 1.9.1, and includes a great deal of new material (enough that it took me almost a year longer than I thought it would to write :-) The book is entirely about the Ruby language, not Rails. Lots of readers of R4R encouraged me to write a “just-Ruby” book, and here it is!

I’m looking forward to the release of the paper version on May 1, too. Not sure yet whether there are Kindle and/or Sony e-reader versions coming, but I’ll keep you posted.

Back to top


My new Ruby book is out!

Wed Jun 10 23:57:00 2009

I’m realizing that the new book isn’t getting enough buzz, so here’s some buzz!

My new book, The Well-Grounded Rubyist, is now out and available from the publisher as well as Amazon and other retailers and stores.

If you’re learning Ruby, or want to learn Ruby, or want to refresh your Ruby knowledge and get more deeply into it…read this book! I talk more about the book in my recent interviews for InfoQ, On Ruby, and RubyLearning.

Some reviews and comments

Here are some review quotations, from various sources:

I think this book is a definite read and should be in every Ruby developer’s library.
...
Excellent. Easy to read, but not dumbed down. I came away with a much deeper understanding of WHY oop is used, and how to use it in ruby.

If you are looking to understand ruby, look no further.
...
David does an excellent job going beyond the language and hitting those concepts in the built-in classes and modules that you need to know and will experience in the real-world.

You can also find complete reviews here and here.

(And don’t get confused if some sites have a different-looking cover. There were two cover designs. The new one is the one you see here.)

Enjoy!

Back to top


The wise Latina comment in historical perspective

Thu Jul 16 22:05:00 2009

I’ve watched no more of the Sotomayor hearings than has happened to be on while I’ve waited for the guy behind the counter to toast my bagel, and things like that. I don’t see much point in watching them, since it’s pretty easy to predict what her critics are going to ask her and say about her, and not terribly interesting to hear her answers.

But I do want to say something about this “wise Latina” thing, if I can do so without boring myself as well as you to death.

With very few exceptions, all Supreme Court justices, ever, have been white men. So have most other judges in the U.S. That means that someone, somewhere along the line, felt that white men make wiser decisions than people who are not white men. Maybe closer to “everyone” than “someone”, in fact.

White male jurists never have to say anything public to the effect that white males as wiser, as jurists, than people who aren’t white males, because it’s been said for them. It’s been said by virtually every President who has made judicial appointments and nominations, every Senator on whom the strangely homogenous pattern has not weighed heavily, and every citizen who never considered withholding a vote from the perpetrators of this centuries-long exercise in exclusion.

In short, the entire history of the Supreme Court and much of the rest of the judiciary amounts to a sustained assertion that white men make wiser decisions than anyone else.

So along came Sotomayor, and expressed a different opinion. She expressed an opinion that was not the opinion on which the entire history of the Supreme Court has been predicated. She espoused the belief that white men do not, in every imaginable case, make wiser judges.

Well!

How dare she?!

Doesn’t she realize that The Universal Opinion on this subject has already been established?

Of course it’s the same old thing. The belief that white males are wiser is so widespread, so ingrained, so taken for granted, that it seems natural. You don’t have to think about it; your thinking has been done for you. And you don’t have to be so gauche as to say that you believe it, because as long as you don’t saying anything, it will be assumed that that’s what you think.

All Sotomayor did was to respond. She was responding to history. History was saying—loudly, repeatedly, in chorus echoing down the centuries—that white men make wiser jurists. Sotomayor said: maybe not, under some circumstances.

That’s all.

Think of it this way. Sotomayor walks down the street every day, her whole life, and every couple of blocks, somebody says to her: White male jurists make wiser decisions than anyone else. Senators say it; Supreme Court justices say it. Citizens say it; Presidents say it.

After a lifetime of that, Sotomayor says: well, not necessarily.

And everyone gets mad at her.

The every-couple-of-blocks thing represents about one millionth of one percent of what Sotomayor, and the rest of us, have actually had communicated to us over our lifetimes. So why the hell shouldn’t she respond? And why are people treating her like Oliver Twist asking for more gruel?

Back to top


Ruby training: for the non-beginner?

Tue Jul 21 21:11:00 2009

People have been asking me a question about the upcoming Ruby training in September that I’m doing with Erik Kastner, namely:

I’m already using Ruby. The course is an “intro”. Should I take it?

To which I say

Very likely, yes!

And here are some reasons why.

And if you’ve never heard someone explain singleton methods before they explain classes, you’re in for a treat! :-) Some of what we cover may be familiar to you—but some won’t. And you won’t be bored, I promise!

If you’ve got any questions about the course, please contact me. I’ll be glad to discuss it with you and determine whether it’s a good fit.

Details and registration are here.

Looking forward to hearing from you!

P.S. If you have any friends, co-workers, and/or employees who you think might be interested in learning Ruby, please forward the info to them too. Thanks!

Back to top


The Compleat Rubyist: what's it all about?

Sat Oct 17 14:57:00 2009

First things first:

In case you haven’t heard about it, I’m very excited to report that I am teaming up with two other Ruby programmer-authors, namely:

to present The Compleat Rubyist, a two-day Ruby training event in Tampa, Florida, January 22-23 2010.

The idea behind the event

It all started with the books.

We got the idea of doing some kind of joint project because our books (including the two above, plus my book, The Well-Grounded Rubyist) complement each other really nicely. My book is a language tutorial. Jeremy’s book (to which both Greg and I contributed) contains advice about using Ruby in a series of application contexts. Greg’s book makes a different kind of pass through the language, with an eye to idiomatic, productive techniques.

A training event seemed like the perfect collaborative effort. We’ve designed an unusual format, optimized for in-depth learning and for a workshop/hands-on style.

Who’s it for?

I’ve been training Ruby programmers for years, and I can tell you that it’s very common to become quite good at Ruby but still have room for getting deeper into how things work, what the best practices are, and other areas.

I’d say that’s the “sweet spot” for our attendees: people who have been using Ruby, and want to go further in their understanding and skills.

Does that mean intermediate? advanced? talented beginner?

Hard to say. I’d like to think that almost any Ruby programmer can get something out of spending two days with us. (And we’re hoping to get a lot out of it too.) We’re not that concerned with pinpointing a level. Have a look at the event description, and decide whether it sounds good for you.

See you there, we hope!

We’re happy to field questions, if you have any. There’s a contact link on the event website, as well as links for registering and for more info about the venue.

Back to top


Starting a new job in December

Fri Nov 13 13:23:00 2009

I am very pleased and excited to announce that I have accepted a Senior Developer position with Cyrus Innovation, Inc. Cyrus is based in New York City. I will be, at least for the foreseeable future, assigned to a team working on-site at a New Jersey client. It’s a work-place I’ve been in before (I’ve done training for them), and I know some of the other members of the Cyrus team who work there. So while it’s definitely a big change for me and a new adventure, it’s also a familiar and collegial environment that I already know I like working in.

And it really is a big change! The last full-time job I had was my professorship at Seton Hall University (1992-2005).

The question is (drumroll…) why now?

Throughout the years that I’ve been doing freelance and independent consulting and training, I’ve regarded the prospect of a fulltime job with ambivalence. On the one hand, it’s less independent. And much of the brainstorming I’ve done this year about whether or not to seek a fulltime job has been kind of depressing, because it’s been motivated largely by the fact that my freelance business has dropped off a great deal (and I have no marketing skills, which means that when the market gets tight, I tend not to remain competitive). I’ve also been conflicted about fulltime jobs because I am very settled where I live and do not want to move.

On the other hand, I’ve always understood that a fulltime job would provide a measure of continuity and security that I’m increasingly feeling the lack of in my independent work. And, even more importantly, there’s the sense of belonging to a team of colleagues. I’ve always looked with a pang of envy at friends who are part of a development team, and whenever I’ve spent even a couple of weeks on a team helping out, it’s been incredibly stimulating. I always go through a big learning spurt when I work directly with other developers, and I don’t do nearly enough of it.

So I’d reached the point where I was interested in a full-time job but, fussy customer that I am, it had to be one that didn’t require me to sell my house and move, and that I had very, very good reason to believe would provide me with the kind of collegial environment that had been, for four years, the thing I had pined for the most as an independent. (I also didn’t want to telecommute, because sitting alone in my house literally all the time is not the right formula for me.)

Well, fast forward a bit and here I am, having found what I was hoping to find! That’s the story. I start December 7. (And all the “date that will live in infamy” jokes have already been made :-) Wish me luck!

Back to top


AccrediDation

Wed Mar 24 01:07:00 2010

I’ve noticed that people routinely pronounce “accreditation” as if the first ‘t’ were a ‘d’: accredidation. I’ve been wondering why, and I have a theory.

First, consider that ‘t’ often becomes a ‘d’ sound before ‘ed’. “faded” and “fated” can sound very similar. “imitated” is pronounced more like “imitaded”.

Now, it’s also true that while “imitated” sounds like “imitaded”, no one says “imiDation” instead of “imitation”. Nor does anyone say “visiDation”, “mediDation”, or “cogiDation”. So why “accrediDation”?

The reason, I believe, lies in the past tense form of the word: accredited. In that word, the ‘t’ after the ‘d’ sounds like a ‘d’ (like “imitaDed” and so on). I surmise, therefore, that something along the following lines happens when people pronounce “accreditation”: The brain gets to that first ‘t’ after the ‘d’ and, out of habit born of d-ifying the ‘t’ in “accredited”, pronounces it as a ‘d’.

What the brain doesn’t quite take into account is that there’s a syllable “missing”. If the past tense were “accreditated” instead of “accredited”, then no one’s brain would ever have thought that there were two ‘d’ sounds in a row, and no one would say “accredidation”.

It’s the only theory I can think of that explains why this word alone, among all the -itation words in the language, gets pronounced this way.

Back to top


Training: a series introduction

Mon Jan 24 22:52:00 2011

This introduction is the first—number zero, if you like—in a series of articles about technical training, intended to be read by trainers but of interest, I hope, to a variety of teachers, managers, and interested learners from various backgrounds. After this introduction I am planning at least three further articles, addressing such topics as how to handle classes with mixed levels of experience and what’s involved in choosing among different teaching modes (lecture, hands-on, etc.). After that, we’ll see.

Not all teaching is training. But as far as I’m concerned, all training is teaching; and teaching is a fascinating, challenging, absorbing art. I’m not going to philosophize at any length about the terminology. I just want to make it clear that in this series about training, I consider myself to be addressing a branch or style or permutation of teaching, with all that that implies.

I’ve taught a lot and I’ve been at it for a long time. From 1992 to 2005 I was on the faculty of the Department of Communication at Seton Hall University, teaching media history and research to undergraduates. Meanwhile I’d been programming computers as a hobby since 1972 (with some gaps, but pretty steadily since 1990), and I’d become a Ruby and Ruby on Rails expert.

By mid-2005, my academic career and my supposed hobby were on a collision course. I had a year-long sabbatical coming up, with the expectation that I would write an academic book; but that summer I signed a (non-academic) book contract with Manning for Ruby for Rails.

The timing was favorable for a change. Ruby beckoned; and with a sabbatical scheduled I wasn’t expected to be in the classroom anyway. So I changed careers: I resigned from Seton Hall, instead of taking the sabbatical, and started to earn my living as a Ruby consultant, author, and trainer.

I figured I’d finish Ruby for Rails and then get a programming job. I did finish the book, but instead of getting a job I set up a one-man consultancy, Ruby Power and Light, and started taking on short-term contracts—and a lot of training jobs. I trained and trained. In 2006, I traveled to something like twenty-three cities, from California to Sweden, training people in Ruby and Rails.

I continued to make my living mainly from Ruby and Rails training through most of 2009, at which point I started working full-time as a developer at Cyrus Innovation. I’m still involved in training projects, though, especially (though not exclusively) a recurring training event called The Compleat Rubyist. Teaching isn’t my main bread-and-butter at the moment, but it is a part of me and always will be.

I hope you enjoy the series.

Next up: Handling mixed levels of experience in a training class

Back to top


Training, part 2: Handling mixed levels of student experience in a class

Thu Jan 27 12:51:00 2011

For me, the most challenging thing about training is accomodating people who come to a class from different backgrounds and with different levels of experience and knowledge. So let’s dive right into that.

How different are different levels? At times, very.

I remember a Rails class whose members included a participant in that year’s “Rails Day” contest (i.e., a very experienced Rails developer), side-by-side with someone who had literally never written a computer program and never seen a command line. The latter person was a front-end designer, and I have every reason to think she was skilled and successful. But she did not belong in that class. (To be fair, the Rails Day guy probably didn’t either—except that he was actually there in part to help some of the other people in the class, who were his co-workers.)

Given a room with that diverse a population, what you can say? I mean that quite literally: what can you say? What sentence can come out of your mouth that’s going to make sense to everyone in the room and hold everyone’s attention? You don’t want to aim too high and confuse the less advanced people. But you don’t want to bore the more advanced students by aiming too low.

Managers sometimes err (quite understandably) on the side of sending more rather than fewer people to fixed-cost, on-site training courses; and even with public courses, self-selection based on advertised course requirements and content doesn’t necessarily serve to keep the group at one level. If you train, you’ll face this issue early and often.

Still, there’s a lot you can do to make the experience rewarding for everybody even in a very mixed-level group. Here are some suggestions—in no particular order except that the first one is the foundation on which all the rest, and indeed all of your training activities, must be built.

A. Deliver what you promised to deliver

This comes absolutely first and foremost. If the course was sold as a beginner’s course, then you have to provide a worthwhile course for beginners. If it’s an advanced course, you have to give the advanced students the best experience you can. Beyond this you can tweak and adjust; but delivering what you promised has to be the starting point.

Occasionally you’ll get a class where everyone is at the same level as each other and it’s not the level you advertised. That doesn’t happen often, but if it does, you can go ahead and recalibrate the whole curriculum. I did that once with a programming team who had much more experience than I’d been led to expect them to have. They were too polite to come out and say that they were too advanced for the curriculum, but it was pretty obvious. So we changed gears on day two and spent the remaining days on more advanced topics and code critique.

That’s a rarity, though. You’ll find the truly mixed-level class to be much more common, and whatever you do to optimize the experience for everyone, you must stay rooted in the curriculum you’ve promised to cover.

B. Make the prerequisites clear in advance

When you’re discussing the course skill-level with the client or prospective participants, show some tough love: be clear and firm about the prerequisites. It’s in everyone’s interest. Don’t try to be all things to all people. Use clear terms like “not suitable” or “too advanced” or “only right for beginners” if those terms apply.

Course prerequisites don’t have to be fine-grained, but they do have to be clear. “Everyone in the course should already be experienced with at least one object-oriented programming language” is an example of a reasonable prerequisite. So is “The participants need to be at least somewhat comfortable in a Unix-like environment.” You don’t need to know whether they know all the command-line options for grep. You just need to establish the basic requirements.

If you’re teaching a dependent technology—meaning, the way learning Rails depends on learning Ruby—address the role of the parent technology. You can teach Rails to people who know Ruby, or to people who don’t; but mixing Rubyists with non-Rubyists in a Rails class is problematic. Make sure you’re in accord with your clients about any assumed parent-technology baselines.

B. Try to control the teacher/student ratio

To the greatest extent that you can, keep the teacher/student ratio at 1/15 or better. Beyond about fifteen, in my experience, you hit critical mass: the amount of help needed by the students expands beyond the confines of the available time for one instructor, so you fall further and further behind.

This is ancient wisdom, of course. Universities like to brag about their tiny class sizes and all of that. And with training classes (as with universities, incidentally), you can’t always control it. But if you’re presented with, say, the prospect of providing hands-on, closely-coached technical training for twenty-five or thirty people, see if you can find another instructor—or at least a lab assistant who can troubleshoot software installation and other matters so that you’re not doing everything.

D. Have extra material in reserve

Try to have some ideas for extra projects up your sleeve, above and beyond any in your stated curriculum, particularly for students who are too advanced for the course. Bring a few books with you, and if someone isn’t feeling challenged enough, point them to a chapter that you think they can learn from. They won’t feel shunned; they’ll feel relieved. The whole problem is that the too-advanced person shouldn’t be there in the first place, so anything you do to help them not be bored is in their interest.

E. Enlist the help of the more advanced students

I’m thinking of situations where, say, one student is clearly over-qualified for the exercises in the workbook, and another student is struggling. It’s possible that the best course of action is for the over-qualified student to pair up with the struggling one and help them out.

This is a tricky strategy, though. It’s your job, not theirs, to do the teaching. The situation has to be really right before you ask students to teach each other.

But it often is really right. For one thing, teaching something helps you consolidate your own knowledge—so everybody wins, including the student-teacher. And some people would rather spend the time engaged in an activity with someone else than go off and work on an application or read a book.

As the teacher, though, you have to make sure that the result is at least as great as the sum of its parts: all parties involved have to understand and accept the plan. You don’t want it to backfire and have either student (or both) think you’re trying to brush them aside. Be circumspect about this option, but keep it in mind for the right situation.

F. Master the art of not answering questions

Don’t get me wrong: in general it’s good to answer questions. But when questions come from students who probably shouldn’t have taken the course in the first place, and are shifting the focus onto material that’s either too simple or too advanced, it’s your job to protect the class.

When I get a too-advanced question, I usually answer it quickly and, if need be, incompletely. I don’t want to digress too far from the curriculum—and above all I don’t want to make the less advanced students feel anxious because they can’t follow what I’m saying. You can always ask the advanced student to talk to you about their question later; but you only have one shot at making the dynamics of the classroom work for everyone. So answer the question quickly; offer to go into it privately later; don’t get into a lot of examples and demos based on the question (that can really make the other students feel abandoned); and move on.

Too-basic questions can be harder to deal with than too-advanced questions. In fact, it may be through such questions that you first discover that some of your students are under-prepared. This may be a good time to consider a temporary ad hoc student-teacher system (see E., above) where someone else in the class helps the person, assuming it’s something that can be communicated relatively quickly (like how to start Ruby from the commandline, creating a MySQL database from scratch, etc.).

G. Make it easy to move around the materials (e.g., staged code shapshots)

For the main do-as-you-go application in my Rails workbook, I’ve got twelve code snapshots. Each one represents the state of the application at a particular point in the book. If a student falls a bit behind, or wants to skip a section they already know about, they can move to a later chapter or section and “fast-forward” by swapping the appropriate code snapshot into their working code directory.

Furthermore, if I need to fast-forward through a topic, I can then pick up from a particular code snapshot and keep going. I might do this with a couple of topics if, say, a client has asked me to deliver a four-day course in three days—or if I’ve just fallen behind a bit and want to get the class back in sync with the courseware. (I don’t make a habit of falling behind but I do try to provide enough material that compressing one or two subtopics won’t be a tragedy.)

Staged code snapshots aren’t the easiest thing in the world to maintain, but they’re a good example of adding an element of independence to the classroom experience for students who want to adjust the pace.

H. Talk to the person in charge

I’m thinking here mainly of private, on-site training engagements (though the principle could be extended to on-going discussions with individual students too). You’ll probably have a discussion at the beginning and/or end of each day with the manager who set up the training. You should definitely bring any issues about class preparedness level to that person’s attention.

When you do, you’ll find that ninety-nine percent of the time the manager will say something like, “Yeah, I was afraid that it would be too easy for Julie” or “Bill said he’d learn Ruby on his own over the weekend but I guess he didn’t.” The manager knows the team. None of what you say is going to be a huge surprise.

Be sympathetic, though. The client didn’t do this to make your life hard. At worst, they just didn’t think it through in terms of preparation and were eager to get the most value out of your skills. Everyone’s acting in good faith.

Sometimes, the manager will take someone out of the training after the first day. I always feel a pang of guilt at this—but I shouldn’t, and you shouldn’t. It’s a correction that will make things easier and more productive for everyone, including the person who shouldn’t have been in the training in the first place. Of course you want to challenge yourself to make the experience accessible to and meaningful for as many people as you can. But don’t be Utopian about it; there really is such a thing as a person for whom a given class at a given time just isn’t right.

Summary

Here’s a summary of the suggestions we’ve just gone over:

Handling the mixed-level classroom successfully is not easy. You need to stay alert and to keep applying energy to the situation to make it as good as it can be for everyone, while delivering what you promised to deliver. A mixed-level group requires agility and adaptability, but with structure.

Some of the training companies I subcontract with do Likert scale evaluations (“Strongly agree, Agree, Neutral…”—that kind of question). One of the questions is often about the pace of the class: much too slow, too slow, perfect, etc. In a mixed-level class, I don’t expect everyone to say the pace was perfect. I aim, though, for the mathematically best result possible: I want the curve to max out at “perfect” and fall away (hopefully not too far) to the sides.

Then I know I’ve done my best.

Back to top


Training, part 3: The lecturing component of presentation

Fri Feb 4 10:34:00 2011

There’s no such thing as pure lecture in my technical classroom. From the very beginning I encourage students to open up program files and interactive interpreter sessions and play with them while I’m talking. Meanwhile I’m often bouncing from a bullet list on a slide, to a console where I demonstrate a coding technique in real time. And much of the time I’m not even presenting; I’m walking around the room helping people with their hands-on exercises.

In writing about modes of instruction—lecture, demo, hands-on or “lab” mode—I am drawing artificial boundaries. In the classroom it’s actually a blend. But bear with me; the artificial boundaries aren’t entirely artficial, and they allow for some salient and helpful points to be made.

In today’s post I’ll be talking mainly about lecture mode: the part where you’ve got the class’s attention and you’re sitting there saying stuff and showing slides and writing code in a file or console. In later posts we’ll look more closely at some specific points about code demos, as well as some ideas for making the most of hands-on exercise time. This time around we’ll focus on the verbal and its cognitive underpinnings.

The teacher’s “advantage”: the z-axis

The biggest problem people face when speaking to a class about a topic is trying to say too much. In fact, it’s largely for the purpose of isolated and tackling this problem that I’ve separated lecturing out as its own topic.

Consider a lecture snippet that consists of the following two points:

To create a Ruby hash, put the keys and values in curly braces.
You separate keys from values using the so-called “hashrocket”, '=>'.

Never mind for the moment what’s being projected on the screen (maybe bullet points, maybe a live code demo). The teacher wants to make those two points verbally about hashes.

Now here’s what happens: a feeling of guilt kicks in, a kind of full-disclosure compulsion. How (one’s teacherly conscience prompts one to ask oneself) can I mention curly braces as literal hash constructors, and not at least mention that they’re used for other things?

So now we’ve got two main points and an aside, with the main points flowing into each other and the aside understood to be in parentheses, so to speak:

To create a Ruby hash, put the keys and values in curly braces.
    (Curly braces are also used for code blocks, but that's a
    different usage.)
You separate keys from values using the so-called “hashrocket”, '=>'.

But you still feel like you haven’t done your pedagogical duty; or maybe that voice in your head is telling you that if you don’t say at least a little bit about operator overloading in general, as a kind of placeholder, your students will later come to feel that you omitted an important topic reference. So, for either nurturing or self-protective reasons, we get an aside inside the aside:

To create a Ruby hash, put the keys and values in curly braces.
    (Curly braces are also used for code blocks, but that's a
    different usage.
        (Lots of operators are overloaded in Ruby -- square
        brackets, for example.))
You separate keys from values using the so-called “hashrocket”, '=>'.

You know you’re digressing but you’re confident that the main topic is moving forward effectively and that the digressions will serve as useful placeholders for later discussion. You have no doubt that what you’ve done amounts to the utterance of two main points, with a bit of embellishment but clear and communicative nonetheless.

In other words, you perceive the asides as occupying a space somehow different from the space of the main points; you perceive them along a kind of z-axis, oblique to the main axis of exposition—something like the axis of depth shown here:

Digressions stand apart from main points in teacher's mind

The only problem is that what your students are actually hearing—what they, rather than you, perceive—is more like this:

Students hear topics and subtopics in a flattened way

The lesson? Have mercy on your students. They’re probably smart, but they don’t have the necessary experience in the topic to evaluate, as your verbal presentation unrolls before them, what’s a main point and what’s a digression. They don’t have the background, so to speak, to pick out the points in the foreground.

Sure, if you make an aside about Led Zeppelin or how to bake bagels, they’ll get that it’s an aside. But if you chase down every little technical opening or clue in your own speech, if you pepper your exposition of a subtopic with points from elsewhere in the general topic, it will only serve to confuse your listeners and add to their anxiety about mastering the subject matter.

When in doubt, lie

In the preface to The TeX Book, Donald Knuth has this to say about topic flow:
Another noteworthy characteristic of this manual is that it doesn’t always tell the truth. When certain concepts of TeX are introduced informally, general rules will be stated; afterwards you will find that the rules aren’t strictly true…. The author feels that this technique of deliberate lying will actually make it easier for you to learn the ideas. Once you understand a simple but false rule, it will not be hard to supplement that rule with its exceptions.

Lecturing without filling in all the details that you know are lurking in the topic feels like lying. It’s OK, though. In fact it’s your responsibility. You’re not really going to say everything, even if you try to cram some extra points in. All these digressions are no more than token efforts, when measured on the scale of the full complexity of your topic. So treat them very skeptically when they present themselves to your brain for delivery to the class.

I don’t mean that you have to become robotic or cleanse your speech of every molecule of outside reference. (Your students won’t let you do that anyway, once they start asking questions.) But try to shake the feeling that you have to cover the entire canvas with your brush on the first pass through. The learning canvas is random access; you can come back to things instantaneously at a later point when they fit in.

And remember that you are not being tested. A lecture is not an oral examination. Even in an oral exam you’d probably want to do more than just a brain dump; all the more should you pick and choose carefully what you say in lecture mode. No one is keeping score. They’re just trying to connect the dots and learn from you.

It’s tricky, of course, because subtopics do have circular dependencies and there are a lot of enticing sub-subtopics on almost any path through a topic. The art of lecturing on technical material (and lots of non-technical material, for that matter) is the art of presenting a non-linear topic in a linear way. Correspondingly, the discipline of lecturing is the discipline of not trying to say everything in the course of talking about any one thing.

Listening to yourself

When you’re talking to a class, you’re performing. I don’t mean you’re being a phony or putting on an act. I mean “performing” in a more technical sense. I’m a musician, so I understand this best in connection with music.

The most difficult and in some ways the most mysterious thing about musical performance is that when you’re performing, you’re also listening. It’s an instantaneous process: the listening part of you tells the playing part of you how things are going and what adjustments have to be made, yet somehow the adjustments aren’t exactly adjustments to anything because they precede the actual production. You can’t really listen to something you haven’t played yet, but that’s what it feels like.

Like I said, a mystery. Let’s leave it at this: performing means letting go but it also means carefully monitoring what you’re doing.

With experience, you learn to listen to yourself as you lecture. When I’m explaining something, part of my brain is creating and delivering the explanation. Another part is consuming it: I’m listening to myself and instinctively spotting the gaps, fuzzy spots, and glitches, hopefully before they happen. I’m also making quick, executive, performative decisions, perhaps literally as I’m drawing breath, as to what’s really relevant and what isn’t.

My impulses, for what it’s worth, tend fairly strongly toward the fill-in-every-detail direction; I need my inner musician (or my inner editor with a red pencil, if you like) guiding me and directing topic-traffic so that I can keep things moving forward. It works, too; but it’s something I had to become conscious of to master.

Presenting a topic with the right balance, the right arc, and the right (probably small) coefficient of digressions, means you’re truly in the teaching zone.

Next up: advice on code demos

Back to top


Training, part 4: Live code demos

Sat Feb 26 13:13:00 2011

You may think of live coding as a necessary evil: the thing you have to resort to when a connection fails and you can’t get at a running example, or when someone asks a question you’re not sure of the answer to and you have to try it out in real time. Admittedly, memories of coding in public (especially the connection-failure ones where you end up writing an entire Rails application on the spot…) are not always pleasant memories.

But I’d encourage you, as a trainer, to embrace live coding. Don’t wait for things to go wrong before you do it; weave it into your presentations and examples by design. You’ll find that the rewards are well worth the risks, and that the risks can be successfully managed without too much effort.

Live coding in presentations and Q&A

Live coding usually doesn’t happen in silence (except when something’s gone wrong). I use it in tandem with answering questions and presenting topics. I think with my fingers; I’m more comfortable and confident saying things about code while I’m writing code. Whether you’re that way in general or not, live coding can keep things lively in your classroom.

Sometimes the answer to a question doesn’t come to me unless I can do some typing; sometimes the answer comes to me but wouldn’t mean much or be clear enough without live code to illustrate it. I’ve never had the impression that anyone thinks less of me as a programmer or as a teacher because I’ve resorted to trying something out before answering a question. Furthermore, the technique of trying things out is, itself, an important one, and a good lesson for your students to learn. “Is Hash#update a destructive operation?” someone asks. “Let’s ask Ruby,” I reply, and then try it out on the screen in irb. (By the way, update is destructive. So is merge!. But merge isn’t, and there’s no update!. No wonder I have to keep checking.)

“Let’s ask Ruby” is a good slogan to keep in mind, and a good one to impart to your students. I’m always surprised when someone sends a question to a Ruby mailing list that could easily be answered by typing a few characters of code into irb. But it does happen; apparently the trying-it-out habit isn’t ingrained in everyone, and the classroom situation is a good place to try to instill it.

As for live demos during presentations: I show code snippets and examples on slides, but I often end up tabbing away from the slides into a console session and showing live examples of the language features and idioms that the slides describe. In this context I see live coding as a kind of bridge between static presentation and having the students themselves do some coding. Obviously having me code isn’t the same as having them code; but I believe that seeing me enter code on the screen encourages them to do the same, to an extent that seeing a static example doesn’t.

Managing risk with semi-live coding

There are certain things I don’t like doing from scratch live. Deployment with Capistrano is one of them. It never seems to go right all the way along. I’ll take the fall for this—I have no reason to assign blame to Capistrano—but I have to live with the fact that live Capistrano installaton and setup demos are, for me, risky.

So I do my live demo of Capistrano, but I do it with the help of a list of steps, written on a piece of paper, and I prepare a certain amount of it in advance. (It’s the permission settings and passwords that always get me.). I don’t hide the list of steps from the class; there’s no detrimental effect to their seeing it, and if they think my use of a script like this means that I’m inadequately skilled, then at least now they know!

Having the demo scripted reduces the risk, if not to zero then at least pretty close. Deciding when you need this kind of aid is up to you. For me it’s Capistrano; for you it might be something else. The main thing to remember is that the usefulness of a live demo for the students is that it’s dynamic and engaging. It doesn’t matter if you use a “cheat sheet”, any more than it matters whether a pianist plays by heart or from the music, as long as the performance is good.

The “cheat sheet” technique applies mainly to fairly complex code demos that you can predict and plan in advance (as opposed to those that you do spontaneously in response to a question, or as a sample illustration of a language feature). Losing your way in the demo isn’t the only risk of a lengthy demo, though; there’s also the lengthiness itself. You don’t want to get embroiled in irrelevant details, nor to start boring the class.

Managing lengthy demos with the cooking-show approach

I draw inspiration from television cooking shows, in the matter of dealing with code demos that might otherwise be too long or detailed. These shows often use a kind of time-lapse technique. The chef mixes some ingredients and gets everything to the point of putting it in the oven. Then, instead of waiting in real time for the cake to bake, the chef produces a finished cake that’s been baked beforehand. The lesson can then resume at the point of frosting the cake.

The cooking show approach can be very handy for in-class demos. It’s particularly suited to cases where you want to demonstrate how to do something relatively small, and then want to show how it fits into a finished application. Rather than have the students sit through the writing of the whole application, you can write the bit you’re talking about—a data validation directive in a Rails model file, perhaps—and then run the whole application and show that it fails when the data is invalid. Or you might walk through the creation of one class or module, but then have the others already prepared so that you can fast-forward.

On cooking shows, the fast-forward technique might apply to the overall process (baking a cake, say) or to a subprocess that doesn’t lend itself to real-time presentation, like waiting for dough to rise or chopping large quantities of onions. The TV chef might illustrate the chopping technique, but then pull a bowl of pre-chopped onions out of the refrigerator and thus condense the time-frame.

The same thing applies in training. The time lapse you incorporate may involve a whole application, or it may involve a repeated task at one level of abstraction, analogous to chopping onions. By all means do a live demo of adding a “has_many” association to one or two of your models. But if you’ve got a lot of such cases in your sample application, consider doing most of them in advance and leaving just those one or two to do as a live demo.

So keep your irb session open, even during your slide presentations, and think creatively about semi-live and cooking show-style demos. Live coding keeps things in the moment, and adds motion and interest to the features you’re trying to put across.

Back to top