PragPub 2010-12: Issue #18

Table of Contents

Features

- Chad Fowler on Ruby
interviewed by Michael Swaine
A legend in the Ruby community shares his recollections and insights and hopes, from the early days of Ruby enthusiasts to the future of Ruby on silicon and Ruby for phones.

- What’s New in Ruby 1.9.2
by Dave Thomas
It’s been a long time coming, but we finally have a worthy successor to Ruby 1.8. Fast, fully featured, and fun, Ruby 1.9.2 should be your Ruby of choice.

- Three Bundler Benefits
by Paolo Perrotta
Why you should start using Bundler to manage your Ruby gems right now.

- New Series: Everyday JRuby
by Ian Dees
Wherein Ian begins a series of articles on using Ruby on the JVM to solve everyday problems.

- Cohesive Software Design
by Tim Ottinger, Jeff Langr
Those big software design concepts like coupling, cohesion, abstraction, and volatility have real practical value. In this article, we'll talk about how cohesion can make your life as a programmer easier.

- When Did That Happen?
by Dan Wohlbruck
Dan wraps up the year with a look back at the era of the personal computer.

Departments

- Up Front
by Michael Swaine
Our Ruby issue celebrates ten years of RubyConf, the tenth anniversary of the Pickaxe Book, and the latest version of the language.

- Choice Bits
A new use for gummy bears and other tweets.

- Guru Meditation
by Andy Hunt
The Perfect Deadline: how to avoid both cognitive shutdown and endless procrastination.

- Way of the Agile Warrior
by Jonathan Rasmusson
Jonathan explains the benefits of startin’ Spartan.

- Calendar
Ruby on Rails and February in Florida: a win-win-win-win.

- Shady Illuminations
by John Shade
John laments stochastic intransitivity and the loss of the Wordstar diamond.

Except where otherwise indicated, entire contents copyright © 2010 The Pragmatic Programmers.

Feel free to distribute this magazine (in whole, and for free) to anyone you want. However, you may not sell this magazine or its content, nor extract and use more than a paragraph of content in some other publication without our permission.

Published monthly in PDF, mobi, and epub formats by The Pragmatic Programmers, LLC, Dallas, TX, and Raleigh, NC. E-Mail support@pragprog.com, phone +1-800-699-7764. The editor is Michael Swaine (mailto:michael@pragprog.com). Visit us at http://pragprog.com

ISSN: 1948-3562

Up Front

The Ruby Issue
by Michael Swaine
This is our Ruby issue, celebrating ten years of RubyConf, the tenth anniversary of the Pickaxe Book, and the latest version of the language.

The Ruby programming language, as everyone from Kansas to Oz knows, was created by Yukihiro “Matz” Matsumoto in 1993, was first seen in the wild in 1995, and finally came to the attention of forward-thinking American programmers around 1999. With the arrival of the Rails framework in 2005, Ruby got famous, but it hasn’t forgotten its old friends, even as it captivates new friends with its magic.

We’ve put on our Ruby slippers for this issue, so get ready to experience the magic.

Specifically, Pragmatic Dave Thomas explores the magic to be found in Ruby 1.9.2. Named matches and Enumerators and multinationalization, oh my! Dave shows why you ought to be using Ruby 1.9.2 right now. And Paolo Perrotta gives three reasons why you should be using Bundler right now to manage your Ruby gems.

In addition to the articles by Dave and Paolo, Ian Dees starts a new series of features on everyday JRuby, and Chad Fowler talks with us about Ruby from its early days to its bright future, in a wide-ranging must-read interview.

If you’re an experienced Rubyist, you’ll find much to enchant you here. And if you’ve been waiting for an entrée to the magic land of Ruby, consider this issue your engraved invitation. Welcome. You’re not in C++ anymore.

But Wait, There’s More

In addition to our Ruby goodies, this issue has a few other gems. Tim Ottinger and Jeff Langr continue their series of agile articles with a thoughtful essay on the value of “Cohesive Software Design.” Jonathan Rasmusson’s “Way of the Agile Warrior” morphs for the month into the “Way of the Spartan Warrior.” Andy Hunt explains why you should seek “The Perfect Deadline.” And Dan Wohlbruck’s series on technology history wraps up the year with a look back at the era of the personal computer.

Also, as usual, we troll the Twitterstream for Choice Bits and keep you up to date with our Events Calendar, while John Shade offers his view on dice and shell games and the twisted topology of technological progress.

Choice Bits

We thought you might like to know...

A few selected sips from the Twitter stream.

What’s Hot

Top-Ten lists are passé—ours goes to 11. These are the top titles that folks are interested in currently, along with their rank from last month. This is based solely on direct sales from our online store.

1^

5

Programming Ruby 1.9

2v

1

Agile Web Development with Rails

3^

8

Seven Languages in Seven Weeks

4^

NEW

Driving Technical Change

5v

2

The RSpec Book

6^

9

HTML5 and CSS3

7^

11

Pragmatic Guide to JavaScript

8v

3

Pragmatic Guide to Git

9v

4

The Agile Samurai

10v

7

Hello, Android

11v

6

iPad Programming

We’re Always Learning

Trying to get back into the iTunes U Stanford class on Fourier Transforms, but my math is rusty. Don't recall learning Euler's formula. — @invalidname

implementing unification for fun. all the cool algos are behind paywalls, but that's ok because i'm slow at getting even robinson to work. — @KentBeck

Asked Jinx the turtle if I should use @fogus's unification engine in #midje. He was noncommittal. — @marick

Spent the afternoon teaching the neighborhood boys (ages <= 8) how to play blackjack. #lifeskills — @scottdavis99

OH: There's no way he wants to get his masters, become an engineer, listen to the same obscure band, and learn to ride a unicycle. — @tswicegood

I've gotten a better adoption curve with screwdrivers -> tequila sunrises -> Laphroig. — @mfeathers

Sometimes Invention Is a Motherless Child

Look! Science has created a fabric that'll help politicians dodge journalists by becoming invisible! http://j.mp/9PxwRw — @tswicegood

awesome hack! RT: @McDwayne: new favorite use for gummy bears: www.zdnet.com.au/sweet-bypass-for-student-finger-scanner-339306878.htm — @squarepegsys

The Øredev Monday night speakers' event is a trip to an 85C sauna followed by a naked plunge into the Öresund. — @headius

I need a coat rack. — @tswicegood

The Coding Life

I wonder how many developers never call a log() or exp() function in their programming lives. That used to be what computing was about. — @invalidname

OO makes code understandable by encapsulating moving parts. FP makes code understandable by minimizing moving parts. — @neal4d

"extreme project mgmt" from @yourdon reminds me of rules for running down an exploding volcano. mine: don't stand on exploding volcanos. — @KentBeck

I Think We Can All Agree...

I take back the nice things I've said defending the TSA. www.pixiq.com/article/the-airport-security-grope — @jaredrichardson

I got to enjoy the TSA kubuki theater an extra 10 minutes today as they checked to make sure that my toothpaste wasn't too big to fly. — @neal4d

http://www.imadethetsafeelmyresistance.com/ — @benrady

Do you read the monthly Pragmatic Magazine? It's top notch content, and it's free! Can't beat that. pragprog.com/magazines — @jaredrichardson

We're dropping the silly $xx.95 pricing on books going forward (at least as an experiment). Our readers are smarter than price points. — @pragdave

Zen Moments

Losing an illusion makes you wiser than finding a truth. ~Ludwig Börne #zenmonday — @PragmaticAndy

To do two things at once is to do neither -- Publius Syrus — @staffannoteberg

How Is It Where You Are?

Quiet and peaceful (except for the ducks) — @rachelcdavies

So, which is it: sunny and 74 degrees, or November? #itCantPossiblyBeBoth http://yfrog.com/ep5skpj — @scottdavis99

Its going to be a @dresdendolls kind of day. I *love* those :-) — @alancfrancis

I think I just saw snowflakes out my office window. — @jeff_lamarche

And here's the snow. Too soon! — @invalidname

I wish to register my disapproval of the earth's axial tilt. 10 degrees would have been ample. #brr #bicycle #shorts — @marick

This month we were following Chris Adamson, Kent Beck, Rachel Davies, Scott Davis, Michael Feathers, Neal Ford, Alan C Francis, Mike Hostetler, Andy Hunt, Jeff LaMarche, Brian Marick, Staffan Nöteberg, Charles Nutter, Ben Rady, Jared Richardson, Travis Swicegood, Dave Thomas. You can follow us on twitter.

Guru Meditation

The Perfect Deadline
by Andy Hunt
Deadlines cause cognitive shutdown. But without a deadline, activities drag on forever. What to do?

A hard deadline means no more excuses, no more options, no second chances. It’s literally now or never.

Of course, deadlines don’t usually work that way. That’s the part of the threat of a deadline, and after the deadline passes, threats usually escalate. The stakes get higher; consequences and punishments more severe. You’re not off the hook—the deadline just hangs around your neck like a millstone that keeps growing and getting heavier.

Hard deadlines, with their attendant fearsome consequences, can shut your brain down as the deadline looms, and leave you with reduced cognitive function for up to two days after the event.

The Panicked Samaritan

What happens to your ability to observe, to problem-solve, even to think clearly when faced with time pressure?

Researchers have devised a number of experiments to show how your performance degrades under pressure, the most well-known being the “Good Samaritan Experiment.” (“From Jerusalem to Jericho: A Study of Situational and Dispositional Variables in Helping Behavior,” Darley, J. M. and Batson, C. D., Journal of Personality and Social Psychology, Number 27, 1973.)

In this experiment, you start with a group of seminary students on the day of the Good Samaritan lecture. Against this backdrop of being good stewards of the earth and helping and serving your fellow man, the researchers set up an encounter. They took one set of students and explained to them that they had a critical meeting with the dean of their school right after the lecture. It was across campus, and they could not be late—their future careers depended on it. They then arranged to position an accomplice, dressed and acting as a homeless beggar, right in their path to the dean’s office.

Sad but true, these devout students, under the pressure of an important meeting, practically walked on the beggar’s head in their mad rush to get to the appointment. They ignored his cries, and rushed past—ignoring everything they just heard in the lecture.

But a second group was told they had that same crucial meeting, only they were given some spare time between events—they weren’t in a rush. The students in this second group stopped to help the beggar; they took him to the infirmary, cleaned him up, and so on. Seems this group was able to think more clearly.

Time pressure hurts your creativity and problem-solving abilities as well. Dr. Teresa Amabile at Harvard worked on a ten-year study on creativity in the workplace, and one of the things she and colleagues discovered was that you are the least creative when you feel time pressure. In fact, it’s even worse than that. Not only are you less creative when battling the clock, but there’s a sort of after-effect: a time pressure “hangover.” Your creativity suffers on the day you’re under the gun and remains depressed for the next two days as well. (Cited in “The 6 Myths of Creativity,” Bill Breen, Fast Company, Dec 19 2008.)

That’s why it’s a good idea to end a project iteration on a Friday. That’s why you really do need some down-time after an unscheduled, panicked time-crunch.

When your mind is pressured, it actively begins shutting things down. Your vision narrows—literally as well as figuratively. You no longer consider options. It would seem that deadlines, in general, are very bad for your cognitive processing.

Timeboxing

On the other hand, there’s the very useful, very popular agile notion of timeboxing. We love to timebox everything we can, from iterations to meetings.

A fixed, limited amount of time for an iteration (or a meeting, for that matter) helps everyone to focus. You become aware that you don’t have all day to waste, that you need to make the hard decisions now, ship something useful, and get on with it. This is really helpful in software development, because we developers have a marked tendency to take as much time as is allocated, and then some. (We also tend to fill up any available disk drive like so much closet space, but that’s a topic for another time).

In an agile iteration, we like to slip features, not the date (see this month’s “Way of the Agile Warrior”). So the date is a hard deadline, but the consequences are manageable: if you were trying to deliver five features, and one of them is not ready, it slips to the next iteration. The good news: you successfully delivered four things. The acceptable news: the thing that slipped will be delivered in a known, fixed time frame.

In agile timeboxing, the deadline is hard; it’s not subject to being moved around and slipped on a whim. But at the same time, it should not instill a brain-damaging panic. The difference is in perception and management of the consequences of missing the deadline.

For a deadline to be psychically damaging, it has to cause undue pressure and stress; fear of the severe consequences (be they real or imagined) shuts down higher-order processing in your brain, so you can be ready for a rapid physical response. Well, that would have worked great in our not-so-distant anthropological past, but in the modern office environment it’s an unhelpful response.

The trick in creating a useful deadline is to make the consequences more realistic and less of an all-or-nothing affair. Agile development is all about taking small bites and avoiding big, dramatic events, from weeks-long requirements meetings to insufferable integration phases to the oft-dreaded and more often skipped Big Testing at the end of the project. Instead of relying on large episodic events, agile development tries to spread the risk out a bit, and is made up of a nearly continuous stream of small events.

An agile deadline works the same way. You could have one massive deadline at the end of the project; the consequences are huge, and include your job, your boss’s job, and the fate of the company and your 401k. Or, you could have more frequent deadlines where the consequences of missing the deadline aren’t professionally fatal, but instead include adjusting resources and expectations, and actually help you become more accurate over time.

You need deadlines. If it weren’t for deadlines, nothing would get done. But be mindful of the consequences. If the consequences of missing the deadline are fearsome, then you can expect that your brains will start shutting down as the deadline approaches.

Something to think about.

Andy is a Pragmatic Programmer, author of a bunch of books, and dabbles in music and woodworking. Follow him on Twitter at @PragmaticAndy, at his blog andy.pragprog.com, or email him at andy@pragprog.com. What’s a guru meditation? It’s an in-house joke from the early days of the Amiga computer and refers to an error message from the Amiga OS, baffling to ordinary users and meaningful only to the technically adept. Send the editor your feedback or discuss the article in the magazine forum.

Way of the Agile Warrior

The Way of the Spartan Warrior
by Jonathan Rasmusson
Jonathan explains the benefits of startin’ Spartan.

There’s more to successful projects than time and money, but if you ask the people with the money, they’ll tell you that time matters a lot.

In this column I am going to show you one sure-fire way to quickly figure out how realistic your budget and schedule are and how to reset expectations like a pro when you need to.

How Much Can You Afford?

One of the great strengths of agile development is the leeway you get in building any given feature or story.

You can build it cheap. You can give your customer something with just a few bells and whistles. Or you can build them the Taj Mahal if they want that.

This looseness around high-level stories gives customers a lot of flexibility when making decisions about features. They can go light on user interface spit and polish if they are building a back-office invoicing system. Or they can invest heavily in look and feel for the tablet application insurance adjusters are going to be taking with them to into the field.

The challenge for you (and your customer) is to get a sense of how much they can afford right at the start of the project. We’d all like the deluxe version of whatever it is we are building, but not at the expense of the budget or the schedule. As Steve Jobs likes to remind us, “Artists ship.”

To help our customers figure out this balance, we need a way of quickly confirming that we

- have enough time and money to build the system they want, and

- have a sense of how much they can afford in terms of bells and whistles that would improve the product and experience.

One way to get there is to start Spartan.

The Way of the Spartan Warrior

The Spartan Way is built around one really simple, common-sense premise: If we can’t build the Ford Focus version of the system with the time and money we’ve got, there’s no way we can build the BMW.

So the way we figure out what we can afford is to build a few bare-bones core features, measure how long that takes, and then take a fresh look at the plan and see how realistic things are looking.

Once you can see clearly that the current plan doesn’t support the scope of what’s on your plate, having this conversation with your customer is much easier.

“Yes, we’d like to build the world’s greatest automated invoicing system, too. It’s just that we can’t get the bare functionality in place (much less any of these other whizbang features you’re asking for) with this schedule and timeline—we’ve tried!”

No wishful thinking. No guessing. The truth is self-evident.

This is really the crux of agile planning. We don’t know when we are going to be done until we build something of value, measure how long that takes, and then update our plans accordingly. I realize that some people (i.e., executives) don’t like hearing this, but this is the reality of software delivery. All we are doing here is eliminating as much schedule risk as we can up front, giving them a heads-up early on about how things are looking.

What to Do if the Plan Is Wrong

If the the plan is wrong, we have two options for bringing reality back into the fold:

1. We can reduce scope (recommended).

2. Or we can flex on the date.

Reducing scope is how agile developers prefer to keep their commitments and avoid the pain that comes from asking for more time and money.

There is always going to be more to do than the time and money allow (that’s just the reality of any interesting project). And if we keep adding features we’ll never ship anything.

So when given the choice we’d rather fix our dates and flex on scope.

If, however, there is a core set of bare-bone features that just have to be delivered as a whole, we can commit to delivering that core set of features. We just have to be a little flexible on the date.

Even in this scenario we will still need to flex on scope a bit (because new things are always going to come up). But we can go in with the understanding that these high-level core features need to be there and that we are going to ship as soon as these are done.

Pushing out the date a little is OK, but it’s not a good habit to get into. For one thing, it’s just too easy. Secondly, it puts your project in danger of delivering no value. Until you get it into production you haven’t an ounce of value, and agile hates that.

Summary

So if you suspect that your project has some scheduling challenges, try building a few spartan core features, see how long that takes, and update your plan to reflect that reality. If things are going well, swell. Keep on truckin’.

Otherwise, work with your customer to set them up for success by either reducing scope or suggesting they be prepared to wiggle a bit on dates.

Doing this early will enable you to have this conversation with conviction in an open and honest way. And your customer will appreciate knowing the facts at the start of the project instead of near the end.

Jonathan Rasmusson is the author of The Agile Samurai. As an experienced entrepreneur and former agile coach for ThoughtWorks, Jonathan has consulted internationally, helping others find better ways to work and play together. When not coaching his sons’ hockey teams or cycling to work in the throes of a Canadian winter, Jonathan can be found sharing his experiences with agile delivery methods at his blog, The Agile Warrior. For more information on the Agile Inception Deck check out The Agile Samurai. Send the author your feedback or discuss the article in the magazine forum.

Chad Fowler on Ruby

An Interview with a Ruby Pioneer
interviewed by Michael Swaine
A legend in the Ruby community shares his recollections and insights and hopes, from the early days of Ruby enthusiasts to the future of Ruby on silicon and Ruby for phones.

Chad Fowler cut his programming teeth on a Commodore 64 as a kid making blobs of color fly around the screen with ridiculous text and awful “music.” Years later, he has come to realize that this describes his ideal project.

Well, that’s his story. Those whose lives have been enriched by encountering Chad are more likely to emphasize his talents as a teacher (in courses from Pragmatic Studio with Dave Thomas, as author of several excellent books, or for his many lectures and conference keynotes), as a much sought-after consultant (whose consulting work takes him to many countries every year), as a skilled software developer (he’s presently CTO of InfoEther and formerly software developer or manager for some of the world’s largest corporations), or as a generous contributor to the Ruby community (who organizes RubyConf and co-created RubyGems). Or possibly for his earlier career playing saxophone in Memphis bars.

Chad’s generosity was obvious to us when a few simple questions from us led him to share his rich memories and deep insights about Ruby, the most exciting programming language to come on the scene in a generation. Here’s Chad.

Discovering Ruby

ms: When and how did you first encounter Ruby?

cf: Around the turn of the century (I love that I can say that now) I had a habit of spending my Saturday mornings learning a new programming language. It was my rapid, shallow version of Dave and Andy’s suggestion in The Pragmatic Programmer to learn a new language every year. I would typically download the runtime or compiler of a new language, read some documents, and try to write a useful program in the new language on the same day. Sometimes the languages were mainstream ones I’d just never played with. Sometimes they were completely esoteric obfuscated languages such as Befunge, Ook or Malbolge. Every once in a while I’d spend time looking at a spoken language like Lojban or other so called “conlangs.” Whatever the case, I was always looking for something that would make me think differently or able to express myself in a way I hadn’t considered.

At the same time, I was going through the decision-making process of what programming language to more fully dedicate myself to. I had been using Java for several years by then and had gone pretty deep with it including a fair amount of mucking about with the JVM itself, compiling my own little non-Java-language programs into JVM byte code. I had finally reached the stage where I felt I had learned about as much as I could from Java, and though I mostly loved it, it was time to broaden my horizons.

As an aside, when I got started in the IT industry as a young musician looking for side work, I was lucky enough to find a mentor to guide me through the process. I was focused on system administration at the time, and he gave me some magic advice which I’m convinced is the seed that made my career what it is today. He told me to learn three technologies, all very different from each other which would make me think differently from each other and also open up a new set of marketable skills that would look good as a set on my resume. This worked so well for me early on it was as if I had literally been given the recipe for successful career starts. So I naturally decided to construct my own list as a programmer.

So I decided to jump full-bore into Smalltalk. It was dynamic, had this weird concept of a persistent image that was foreign to me at the time, and had a remarkably minimal syntax, which I’m sure we’ll all agree is on the far end of the spectrum from Java’s. Not only that, it was used by some of the programmers I respected much from the budding agile development community (nobody called it “agile” then). I made this decision on a Friday afternoon as the work week wound down in my corporate job.

On Saturday morning, with full knowledge that I was about to embark on a journey into the center of Smalltalk, I did what I always did: loaded up my Web browser and searched for the Language of the Week. I’m not sure where I first heard about Ruby. It had been a few years earlier. But this Saturday morning, a post from (Pragmatic) Dave Thomas on the Extreme Programming mailing list is what made me decide on Ruby as my weekend project.

I quickly learned the syntax, discovered ERb (“Embedded Ruby”), and rewrote and deployed my weblog software in Ruby as a CGI framework with a mysql backend. I did all this by around lunch on Saturday. I’d been in this new language routine for quite a while and I’d never made this much progress so quickly. It was bizarre. On Sunday, I came back to Ruby. And on Monday evening after work. And so on.

On the down side, I never really got that good at Smalltalk.

The Early Days

ms: You got involved with Ruby at a time when it was known only to a small number of people outside of Japan. Could you talk about what the Ruby universe was like then?

cf: Being in the innovation wasteland that Louisville, Kentucky was in 2000, I frequently turned to the internet to find an inspiring professional community of creative software developers. This was no different with Ruby. I’m pretty sure I was the only person using Ruby in Louisville then. I started to introduce Ruby to my co-workers, who would frequently snicker when I mentioned it. I think they were playing a minimalist form of buzzword bingo in the office where the only word on the sheet was “Ruby.” They thought of it as just another crazy thing Chad was goofing around with again. I don’t blame them. But that gives you a sense for how well accepted Ruby was in those early days of Western adoption. My team then remains one of the smartest I’ve had the privilege of being a part of, and they all thought I was crazy.

So I spent a lot of time on irc and on mailing lists arguing minutiae and dreaming of a day when Ruby was in wide enough use that I could use it as my primary work language. There were usually 10-15 people on the freenode #ruby-lang irc channel. The main English Ruby mailing list was of high quality and low traffic. It was my first time stepping far outside of the mainstream IT programmer world and into the realm of software pioneers. I don’t mean that everyone involved with Ruby then was a genius or thought leader or necessarily shaping history. But it was a small community of people who were using a tool nobody around them wanted them to be using, because they felt better and more productive using it. It was a small, global phenomenon. A sign of resistance against mediocrity. I wasn’t even sure Ruby was better than the alternatives. I just knew I felt smarter when using it and when rubbing virtual elbows with the rest of our small community of users.

Back then, by the way, “community” was an apt description of the collection of world-wide Ruby users outside of Japan. I’m quite sure Japan also had a thriving group that would be appropriately dubbed a community as well, but I (still!) don’t speak Japanese and had no way of being sure of it. But in our community, almost everyone at least knew of each other. Many had connected on mailing lists or irc to work on software or documentation together. It reminded me of my local community BBS when I was younger. If we had all been in the same place, we probably would have had a meetup at a bowling alley once a year.

And even early on, there was a strong influx of people from the extreme programming community (which was also a community back then). So at a time when few programmers were talking about things like test driven development, I’d say most Rubyists were versed in TDD if not actively doing it.

I know I’m getting old now, because I find myself thinking things like “those were the good old days.” I think it’s actually more a sign that those days were good than a sign of my age, though. It’s exciting to be part of something new and subversive that you feel is better than what most everyone else is doing. It’s also scary to be putting as much effort into something so shaky as most of us were putting in. For all we knew the project might die, or it could just never catch on. Most of us were working on Ruby based on a combination of love, naivety, and faith.

As for the kind of work people were doing with Ruby at the time, the main thing I can say is that almost nobody was doing their job with Ruby. Most of what was being developed in the Ruby community was stuff around the language itself, such as documentation tools and code browsers. I was using Ruby at work for backend processing tasks and scripting. I also used it to generate Java code to save me time. I think a lot of us were using it behind the scenes in that way.

Ruby on Rails

ms: What was the impact of Rails?

cf: In mid-2004,we heard the sound of our little community’s death knell. Its origin was Denmark. Its name was Ruby on Rails. When I say “death,” I refer specifically to the little community that I was talking about earlier. Rails changed things for us and for a lot of people who had never (and might still never have) used Ruby.

I knew about Rails and was running an application for a small non-profit that my wife and I were involved with. I knew David Heinemeir Hansson from The Internet and had helped him with issues with the RubyGems packaging system. But even so—I remember the night before RubyConf 2004 in Chantilly, Virginia. I showed up early, as I always do to help set up, and the usual suspects were all arriving from the airport. What was different this time was that almost every one of them was asking, “Has that David Flanemeyer Landon guy gotten here yet?” or some such mispronunciation. Everyone wanted to meet him and to talk to him about Rails.

I was surprised. To me, Rails was just another Web framework in Ruby like Iowa and Arrow and a few others you probably haven’t heard of. People had been using Ruby to do Web development since before I started programming in Ruby, and to me Rails was just a Model/View/Controller framework written in a niche language that almost nobody was using. Though I liked it, I didn’t expect much from it.

But RubyConf 2004 convinced me otherwise. Rails and its creator were the force of the conference. And I remember that DHH did something unusual with his presentation. Rather than spend the entire time discussing technical details of Rails, he gave what seemed more like a How To speech about launching a successful marketing campaign and building a remarkable, successful product. This was definitely not the kind of subject material RubyConf was accustomed to, but what was really interesting about this is that he was effectively laying out the future of Rails’s success before it happened, and speaking as if it already had. It seems like this strategy was successful, and I’ve seen him do it repeatedly since then.

That was late September of 2004. By July of 2005, David was keynoting at O’Reilly’s huge Open Source Convention, at which we had previously been struggling to keep our little Ruby track alive. OSCON 2005 was, as much as any other date, location, and time, the arrival of Ruby (via Rails) into the mainstream software developer’s consciousness. After that, the flood gates opened into the Ruby community, with developers leaping in from all corners. We had PHP programmers and even HTML people on one end of the spectrum and hardcore Java and .NET developers and architects on the other end. Well-known developers from other language communities were dipping their toes in or even jumping in head first and re-identifying as Rubyists.

Ruby and Rails books started to flood the shelves. Normal companies started to consider and then adopt Ruby for their main lines of business. People were getting jobs working in Ruby!

And, much to the chagrin of some of us who had been working with Ruby as a labor of love for years prior, Ruby became a “Web language.” Rails was so influential that, for a time, it was common to have conversations with other developers who didn’t know that there was a difference between Ruby and Rails. “Ruby on Rails” was just one thing, not a language and a framework.

That all being said, the overwhelming sentiment was that of thankful disbelief. We all got what we’d been hoping for and more with the arrival of Rails. Not only did it allow us to use our beloved Ruby all day at work, but it gave us both a wonderful Web framework and a shining example of how when bad ideas that become so ingrained that most people don’t even notice them anymore, the ground is fertile for innovation.

Rails on Ruby

ms: Has Rails influenced the development of Ruby itself? What outside forces have influenced the evolution of Ruby, if any?

cf: Rails has definitely had an influence on the development of Ruby. Rails definitely doesn’t drive what Matz does with Ruby, but consider that adopted languages (even spoken languages) change largely due to societal pressures. And for most Ruby developers at this point, Rails was the gateway in. That means the initial examples of the language that people see are within the context of the Rails framework. The APIs people first learn are the Rails APIs. The conventions, terminology, expectations of succinctness vs. verbosity all come initially through Rails.

Before Rails, I don’t recall feeling that Rubyists had really settled on accepted style. There weren’t really even pockets of styles that I remember. Some people were still doing camelCaseMethodDefinitions. Some people were putting all of their library code in a single file. Some people set up their packaging with install.rb, some with setup.rb, some with RubyGems.

Rails ingrained a style of Ruby code by example. It became common to define methods that accept a Hash of additional options where the keys in the Hash are Symbols like this:

Botanist.find(:all, :conditions => {:first_name => "Bobby"})

We take that sort of thing for granted now, but back then it was jarring and ugly to my eye. It’s used so pervasively in Rails, though, that it’s commonplace. In fact, Ruby 1.9 takes the Symbols-as-keys convention to a new level of brevity:

Botanist.find(:all, conditions: {first_name: "Bobby"})

It may have been inevitable but I’d say Rails had at least a major indirect effect on that happening.

In Ruby 2.0, Shugo Maeda is working on a new feature called “Refinements.” Refinements allow us to re-open and change Ruby classes only within a specific scope. This makes Ruby’s open classes, modules, and Objects safer to go crazy with. While we’ve been waiting for such a feature since years before Rails was created, Rails’s penchant for souping up existing Ruby classes with convenience methods has certainly fanned the flames of the need. Rails lets you do things such as:

ruby-1.9.2-p0 > 1.day.ago

=> Sat, 27 Nov 2010 00:01:36 UTC +00:00

ruby-1.9.2-p0 > "Botanist".pluralize

=> "Botanists"

ruby-1.9.2-p0 > Object.ancestors.map(&:name).to_sentence

=> "Object, Kernel, and BasicObject"

Shugo’s Refinements implementation would allow us to create these handy convenience mechanisms, but localize the effects of their changes, making it safer to do it even more than we do now.

There are many small examples of Rails influencing either the language or the standard library, but the short answer is: it has made an impact.

Another major impact Rails had was that it helped to popularize the RubyGems packaging system (of which I was a co-creator). RubyGems was the way to install Rails, which meant that as Rails grew in popularity, so did RubyGems. Even if people weren’t sold on RubyGems, having it available everywhere Rails was available meant it was the easiest way to get a library or Ruby application out into the hands of developers.

This led to a bazaar-style Open Source ecosystem (as defined by Eric S. Raymond’s The Cathedral and the Bazaar) as opposed to the slower, more conservative Cathedralesque model a monolithic Open Source project might adopt. What we’ve found is that if RubyGems are simple to create and distribute, there’s almost no barrier to creating one for the simplest of needs.

This has evolved in our community to include the new RubyGems.org, which Nick Quaranto developed and led into production last year. Now gem publishing is automated and command-line driven, which means you can go from idea to published, announced gem in minutes if you’re solving a simple problem.

So while this isn’t really an impact on the language directly, it majorly effects the ecosystem of software. Ruby programmers are rarely stuck when their language or standard library does’t support what they want it to. They can often trivial “fix” those holes and distribute the solutions to everyone else. Rails had a major role to play in making this true.

RubyConf

ms: Could you talk about RubyConf—the first one and how it has evolved—and the phenomenon of regional conferences and code fests?

cf: The reason I’m still as involved with Ruby as I am is probably RubyConf. We held the first RubyConf in 2001 in Tampa, Florida. It was originally planned by a developer named Guy Hurst. He came up with the idea, registered a Web domain, set up a Web site, organized a venue, and then got busy with the rest of his life and had to give it up. Dave Thomas didn’t want to see the first conference die on the vine, so he invited David Alan Black and me to a private channel on IRC and asked if we would help see it through.

And we did. The first conference was co-organized by the three of us. We had 34 attendees. Many of us were authors. Four of us were signatories of the Manifesto for Agile Software Development. One of us was the creator of Ruby!

The first RubyConf was more like a meeting than a conference. We had presentations, but most of them became discussions. We had a planning session for what was to become the successor to the Ruby Application Archive (RAA.succ, we called it).

We’ve taken it to a different city each year since and have rotated among the continental US time zones to try to make it easier for people to attend. We’ve gone from 34 attendees in 2001 to around 800 this year in New Orleans. In 2005, just after Rails was released, we had our first rapid sellout. We’ve since sold out events every year, and in 2006 split off another conference called RailsConf to help accommodate the load and stratification in focus and interest that was apparent in 2005.

As an organizer, I can get away with saying that RubyConf has always been informal, sloppy, and somewhat haphazard. But it’s also been magical. People leave the conference with new aspirations, new collaborators, and sometimes with new careers.

Because RubyConf has so far always taken place in the US, a couple of years in, some programmers in Europe took it upon themselves to organize a European conference. They called it Euruko. They also started out very small. They also took to moving the conference around Europe. They now apparently not only move it around but elect new organizers in new host cities every year.

After Euruko started, the organizers of RubyConf (who had incorporate a non-profit called Ruby Central) thought it would be cool to help others get together locally and more frequently than RubyConf would allow. So we put together a grant program, giving out money to people who wanted to organize codefests, where they would get together locally and work on a project. We had a little money left over from the 2003 conference, and being a nonprofit, decided to put it back into the community in this way. We awarded several codefest grants before changing the grants to be in support of regional conferences instead.

I may be wrong, but I think the first major regional conference to spring up in the US was the Mountainwest Ruby Conference in Utah in early 2007. I remember being astonished at the crowd there. It was their first conference and they had something around 200 people. For a local, regional conference.

Since then the regional Ruby conference phenomenon has exploded. Each one has its own local feel and flavor. They’re happening all over the world. I’ve been to many of them and have enjoyed each one differently. And we’ve borrowed ideas for RubyConf.

I’ve been hoping the next step would be to start seeing topic-specific conferences. And this year, once again in Utah….hmmm, we saw Ruby|Web Conference 2010, a Ruby conference specific to Ruby Web technologies. Maybe next year we’ll see Ruby|MusicConf or Ruby|HardwareConf. I hope so.

Ruby Adopters

ms: You meet a lot of Ruby developers in your travels and talks. Do you have a sense from those encounters just what people are using Ruby for today? And has that changed over the years?

cf: People are using Ruby for all sorts of things these days. Web apps, backend code, GUI apps, simple Web services. It’s all over the board. And telecom apps. And even televisions. More than that, the domains Ruby is finding its way into are getting more and more diverse. In the 2005 timeframe, we always heard about a lot of startups using Ruby. I remember hearing second-hand from the Web 2.0 conference in early 2006 that if startups weren’t using Ruby, people asked them why they weren’t. It was kind of assumed.

But these days it’s not just startups. It’s big corporations and governments. And people trying to open their governments. Some of the biggest companies on the planet are making strategic investments in Ruby code. Many government agencies are doing the same. I’ve personally interacted with five or six US government agencies in the past couple of years.

Ruby in the World

ms: Can you comment on adoption of Ruby throughout the world?

cf: Ruby is being adopted world-wide, though I see it moving more quickly in the US and Canada than anywhere else. I guess the same would be true of agile development methodologies, NoSQL, git, and other leading-edge ideas. We tend to pick things up quickly in North America. I don’t mean we’re smarter than people in other places. We’re just more likely to play with new things. I learned this lesson while living and working in India. In the US, we have things like food and shelter so figured out (for the most part) that we don’t think about it anymore. Of course we have a computer or two at home. Of course we have free time. If we don’t, we whine about it. We’re really spoiled.

In other places, technologies are adopted more slowly. In India, a large part of that I think is that the Indian economy is still stabilizing and India’s most successful programmers are typically only a couple of generations past having to worry about the basic needs in life. So the average Indian programmer isn’t yet to the point where they’re goofing around with programming for fun. They’ll get there eventually, but they aren’t there yet.

I’ve seen the same things in other places as well. I’m not sure it’s all economically driven, but I have yet to find a technology culture more thirsty for constant change than the US. When I travel to places like Brazil and India, I see frustrated thought leaders pushing hard to drive change, but basically situated culturally where we were five or six years ago.

Part of me feels bad for them. Another part of me envies them. It’s rewarding to be a revolutionary. :)

JRuby and Other Rubies

ms: Could you say something about what seems to be the large number of distinct Ruby implementations?

cf: Ruby has several viable implementations. That is to say, “Ruby” with a capital “R” (the language) can be executed by any of a handful of high quality, mostly-code-independent implementations of it. There’s Matz’s Ruby (1.8), YARV (1.8 + a new VM and syntax for 1.9), JRuby, Rubinius, Maglev, IronRuby, MacRuby, Rite, and others in development. All of them can run real Ruby code. All of them provide advantages over the others. Each implementation is faster for some things than the current state-of-the-art canonical Ruby implementation.

Outside of the Lisp/Scheme world, I don’t think I’ve ever seen this happen before. There are tons of options. And Matz embraces them all. In his RubyConf keynote this year, diversity of implementations was a major theme. The many Ruby implementors communicate with each other frequently, share ideas, complain about hard features to implement (heh), and generally make each other better. Even the canonical Ruby implementation has a lot to gain from this thriving community of Ruby implementors.

If you’ve ever worried about the long-term viability of your language, whether it be a niche language or VM, or a commercial situation like the current JVM situation, knowing there are so many Open Source alternatives is refreshing. If something really really bad happened and all of Matz’s interpreter work was somehow lost or compromised, most of us could happily switch to JRuby with minor modifications at most. That’s amazing.

Ruby Culture

ms: Is there a distinct Ruby culture?

cf: I think there is a cultural aspect to the Ruby ecosystem. We have a bazaar model for implementations. And libraries and library distribution. And conferences. And documentation. And Open Source contributions. And so on.

I think this has happened, because Ruby fosters a culture that has always taken a hard, critical look at our assumptions as software developers and turned them upside down.

Here’s a simple example: why don’t we have to use parentheses and semicolons all over our code? We’ve programmed with needless semicolons and parentheses littering our code for years without questioning it. But with Ruby we don’t have to do that.

The question this raises in my mind is “Why did we ever have to use so many damned parentheses or end every line with a semicolon to begin with?” Could the Java parser not have figured out when a line was ending without a semicolon? Of course it could!

But then again, why did we ever have to do a lot of the things Rails automates for us? Or why hasn’t PBX development always been as easy as it is with the Ruby Adhearsion framework? Or why haven’t we always had Capistrano?

We’ve seen Ruby software break so many habits and assumptions that it has become rightly known as a language for which assumption- and habit-breaking is the norm. One such assumption it broke was that “weird” languages shouldn’t be welcome in Real Enterprises.

Java was weird once too, I guess. But it was also a technology backed by major industry players and a lot of money. When Ruby took the Web development industry by storm in 2004 and 2005, it was a niche Open Source language created by a Japanese man whom nobody in the West had ever heard of. And as I said before, it was the subject of laughter in the traditional IT setting.

But then suddenly many people saw what it made possible. And maybe I’m fooling myself, but I feel as though that opened up the flood gates to the acceptance of things like erlang, python, ocaml, haskell, scala, mongodb, cassandra, and so on. All of these weird unconventional technologies sprang up and were semi-accepted at the same time. I think Ruby (through the success of Rails) at least temporarily made it OK for people to experiment, even in traditionally conservative environments. It became more palatable to attempt to choose the right tool for the job at hand even if that tool didn’t fit into a homogenous corporate toolbox.

As I’ve traveled around the world, I always encounter that one person in every company who’s trying to push everyone else to think more effectively, try harder, strive for beauty, focus on the craft, free themselves from heavy useless process, and so on. That same person espouses “agile” processes and dynamic languages. He or she advocates test-driven development and customer involvement. Domain driven design. Lean startup ideas. All the Good Stuff. Since I’ve been involved with Ruby, Ruby’s been a honey pot for that one person. That’s the magic of Ruby. I can’t explain it, but all of those people…they’ve shown up year after year. It’s a lucky place to be.

The Future

ms: Where is Ruby headed? What are your hopes for the language or the community?

cf: I have no idea where Ruby is headed. Part of me says “Screw it. It’s good enough. Let’s just fix bugs and make it faster.” But that’s because I’m not as smart as people like Matz, Shugo Maeda, Nick Quaranto, anyone on the Ruby Core team, anyone on the Rails Core team, etc., etc., who have proven that things can continue to get a lot better consistently even when they seem to be pretty damn good.

I do know that Ruby 2.0 is finally on the horizon. I first heard about Ruby 2.0 at RubyConf 2001. Matz gave a keynote about it. In the keynote he said, “I hope this takes longer to create than Perl 6.” He didn’t really say that. But in 2006 in his RubyConf keynote he did say “Ruby 2.0 is worse vaporware than Perl 6.” He showed dates and proved it.

When your 1.x language isn’t dying, maybe a forever-elusive 2.0 keeps people excited. Think about something you’ve committed to long term. If you always thought you were just in the nascent, undeveloped stage of whatever it was, you’d probably be more motivated to stick with it to see where it goes. If 1.x is awesome, imagine what 2.0 is going to be like! Why ruin it for everyone, right?

Well anyway it looks like Matz is going to ruin it for us all soon. And by “ruin it,” I hope I mean he’s going to rock our worlds. That’s what I hope for. 1.9.2 is the best Ruby ever. In any other language it probably would have been called 2.0.

So what I hope for Ruby is that 2.0 introduces incompatible changes. I hope 2.0 removes all of the little ugly things we’ve all gotten used to. I hope it fixes problems I didn’t realize I had. I hope 2.0 is remarkably different from 2.1, because 2.0 contained crazy ridiculous ideas that didn’t work and had to be pulled out for 2.1.

And I hope Ruby 2.1 can run everywhere. I want to use it to do hardcore math I’m not qualified to do. And I hope to run it on my phone and my microwave. I met Gilad Bracha in Poland a couple of years ago and before he knew I was a devoted Rubyist he criticized the Ruby apologists for justifying the poor performance of the Ruby interpreter by saying that all we do is IO-bound application (Web apps). Gilad said what we all know: there’s no reason Ruby has to be relegated to applications where computation can be slow. Even if that’s a whole lot of apps.

At RubyConf this year, Matz spoke about a new project called “Rite.” Rite is a subset of Ruby with a new implementation made specifically for low-footprint applications such as cell phones and appliances. There’s apparently even a Ruby chip being developed to help speed up method lookups and other slow operations. Maybe that will succeed and become Ruby 3? Or Rubyists might start switching to Rite. It’ll be fascinating to watch.

Chad Fowler is a software developer, author, speaker, conference organizer and musician. By day he is CTO of InfoEther, Inc. where he solves hard problems for companies of all shapes and sizes. By night he writes books such as The Passionate Programmer and the upcoming Rails 3 Recipes. Send Chad your feedback or discuss the article in the magazine forum. The photo of Chad is by James Duncan Davidson and is used with his permission.

What’s New in Ruby 1.9.2

If you’re not using it, you should be…
by Dave Thomas
The author of the definitive reference to the Ruby language leads a tour of some of the best features of the latest release.

At the risk of inflaming Apple’s lawyers, Ruby 1.9.2 is the best Ruby ever. It’s fast—things run noticably quicker than 1.8. It has some killer new features (we’ll briefly look at the new regular expression engine, some new classes and methods, and the new encoding support in this article). And, despite growing fairly significantly, it still has that playful feeling to it—programming Ruby is still fun.

Early versions of 1.9 had problems with third-party libraries. Although the language is basically the same, there were some incompatibilities (mostly with indexing into strings and block variable scoping, along with some low-level changes for C extension writers). However, those problems are now in the past. I’ve been using Ruby 1.9 for a year now, and everything I’ve needed has just worked.

So, if you’re still using Ruby 1.8, let’s see if I can convince you to upgrade with a few tasty nibbles of what’s new.

Not-So Regular Expressions

Ruby 1.9 uses a brand new regular expression engine, giving it unparalleled regular expression support. Let’s look at just one feature—named matches.

The pattern /(?<hour>\d\d):(?<min>\d\d):(?<sec>\d\d)/ matches a time. It contains three groups in parentheses. Unlike Ruby 1.8, though, I can give each of these groups a name (I used hour, min, and sec). If my pattern matches a string, I can then refer to those named groups.

pattern = /(?<hour>\d\d):(?<min>\d\d):(?<sec>\d\d)/

string  = "It is 12:34:56 precisely"

if match = pattern.match(string)

puts "Hour = #{match[:hour]}"

puts "Min  = #{match[:min]}"

puts "Sec  = #{match[:sec]}"

end

produces:

Hour = 12

Min  = 34

Sec  = 56

There’s even a shortcut (although it’s a little tacky). If the regexp is a literal, it will set local variables to the contents of named groups:

string  = "It is 12:34:56 precisely"

if /(?<hour>\d\d):(?<min>\d\d):(?<sec>\d\d)/ =~ string

puts "Hour = #{hour}"

puts "Min  = #{min}"

puts "Sec  = #{sec}"

end

You can use named groups a little like subroutines—you can invoke them many times inside a pattern. You can even call them recursively: the following pattern matches text between braces, handling nested braces correctly (so it will match "{cat}" and "{dog {brown}}").

pattern = /(?<brace>

{            # literal brace character

( [^{}]      # any non-brace

| \g<brace>  # or a nested brace expression

)*           # any number of times

}            # until a closing brace

)/x

puts $1 if pattern =~ "I need a {cat}, quick"

puts $1 if pattern =~ "and a {dog {brown}}"

produces:

{cat}

{dog {brown}}

The \g<brace> part of the expression means invoke the part of the pattern named brace at this point. Because this happens recursively inside the group, it handles arbitrarily nested braces. (Note also the use of the x option, which lets me lay out the regular expression neatly and include comments.)

Related to \g, the \k construct means match what was previously matched by a named group. It is similar to the existing \1, \2,… feature in Ruby 1.8. But, unlike the old backreferences, \k knows about multiple matches made by the same group, and you can use this knowledge to say match the text that was matched by this group at a certain nesting level. Here’s a regexp that matches palindromes—words written the same forwards as backwards:

palindrome_matcher = /

\A

(?<palindrome>           # palindrome is:

#    nothing, or

| \w                    #    a single character, or

| (?:                   #   x <palindrome> x

(?<some_letter>\w)  #   ^              ^

\g<palindrome>      #   |  ^^^^^^^^^^  |

\k<some_letter+0>   #   '--------------'

)

)

\z

/x

The new regexp engine also offers better control over backtracking, positive and negative look-behind, and full internationalization support. On its own, it’s a reason to switch to Ruby 1.9.

New Classes and Methods

Ruby 1.9.2 has almost 400 more built-in methods and 13 more built-in classes and modules than Ruby 1.8.7. That’s a boatload of extra goodness, baked right in. Many of the new methods were introduced when the Rational and Complex classes were merged into the core, but even allowing for those, there are literally hundreds of new methods to explore. Let’s look at a few here—all these are somehow related to collections and enumeration.

Let’s say you need to deal a deck of cards to four people. Each card is represented as a suit (C, D, H, and S) and a rank (2 to 10, J, Q, K, and A). We can use some of Ruby’s spiffy new methods to do this easily.

suits = %w{ C D H S }

ranks = [ *'2'..'10', *%w{ J Q K A } ]

deck  = suits

.product(ranks)

.map(&:join)

hands =  deck

.shuffle

.each_slice(13)

puts hands.first.join(", ")

produces:

C9, H3, H9, S6, D10, SQ, CJ, D4, H4, C8, C4, HQ, S9

Pretty much every line in this little example has some 1.9 goodness. First, we can now use splats (*) inside array literals. Next, notice that we can now put the period that appears between an object and the message we send it at the start of the line (in 1.8, it had to be at the end of the line or Ruby would think the statement was terminated). It’s a small thing, but it makes it easier to chain calls together, as the last line in the chain is no longer a special case.

The product method returns all the combinations of its receiver and its parameter(s). In this case, it combines the suits and ranks into an array of 52 subarrays. The next line uses the fact that Symbol.to_proc is now built into Ruby—it joins the contents of each of these subarrays, converting ["C", "2"] into "C2", the two of clubs.

We use Array’s new shuffle method to shuffle the deck, and then split it into four sets of 13 cards. There’s something subtle here—normally each_slice would take a block, passing each chunk to it as a parameter. Because we didn’t provide one, it instead returned a new 1.9 Enumerator object.

An Enumerator is basically an enumeration wrapped into an object. Enumerators make it easy to take something that used to be expressed in code and instead represent it as an object, allowing it to be passed around and manipulated. Enumerators are typically lazy—they don’t typically do the work of evaluating the thing they wrap until you need it. And the cool thing is, they’re pretty much part of the core of the language—built-in methods such as each that in 1.8 expected a block will now return an Enumerator if you leave the block off. Here’s an example using the new Prime standard library. The each method will normally call its block forever, passing in successive prime numbers. Here, we don’t give it a block, so it returns an Enumerator object. We then call take_while on that object to print out the primes less than 20.

require 'prime'

puts Prime

.each

.take_while {|p| p < 20}

.join(" ")

produces:

2 3 5 7 11 13 17 19

Enumerators don’t sound like much, but over time you’ll find they subtly change the way you program; I now can’t live without them. And this just barely scratches the surface of 1.9’s new functionality.

Multinationalization

Ruby is a citizen of the world, and the world speaks many languages and uses many different sets of characters doing it. Older Rubies ignores this—to them, strings were just sequences of 8-bit bytes. Ruby 1.9 changes this—saying that Ruby 1.9 is encoding aware is a bit like saying that Google has some servers. Many languages say they support international character sets because they have Unicode support. Well, so does Ruby. But Ruby also has support for 94 other encodings, from plain old ASCII, through SJIS, to KOI8, to old favorites like 8859-1.

What does it mean to support these encodings? Well, first it means that strings, regular expressions, and symbols are suddenly a lot smarter. Rather than being sequences of 8-bit bytes, they’re now sequences of characters. For example, in UTF-8, the string ∂og has three characters, but is represented as five bytes internally. If we run the following program with Ruby 1.8:

str = "∂og"

puts str.length

puts str[0]

puts str.reverse

We see the following:

5

226

go???

Notice that the length is the number of bytes in the string, the first character is returned as an integer, and the reversed string is mangled. But run it with Ruby 1.9, and you see something very different:

3

∂

go∂

But, to make this work, I had to do one extra thing. Remember that Ruby supports almost 100 encodings. How did it know what encoding I’d used for the source code of this program? I had to tell it. In 1.9, every source file in your program can potentially have its own encoding. If you use anything other than 7-bit ASCII in a file, you have to tell Ruby that file’s encoding using a comment on the first line of the file (or the second line if the first line is a shebang). The actual program I ran looked like this:

# encoding: utf-8

str = "∂og"

puts str.length

puts str[0]

puts str.reverse

This per-file encoding is very cool—it means that you can knit together code written using different encodings by people working all over the world, and Ruby will just do the right thing. To my knowledge, that’s unique among programming languages.

But encoding support doesn’t just stop with program source code. When you open a file or other external data source, you can tell Ruby the encoding to use. All data read from that source will be tagged with that encoding. The same applies to data you write out. Behind the scenes, Ruby works hard to make sure that when you work with this data, you’re doing things that make sense—it’ll raise an exception, for instance, if you try to match a SJIS string using a UTF-8 regular expression.

All this great support means that Ruby is incredibly well suited for writing true international applications.

Prime Time

Ruby 1.9.2 is more than just another point release—it’s the next Ruby in a chain that started over 15 years ago. It’s stable and production-ready. It’s fast and it’s huge. It’s comfortably familiar and it has lots of challenging new features.

But, most of all, it’s still fun.

Dave Thomas has been writing Ruby all his life, and was relieved in 1999 to find a language that let him do it for real. Send the author your feedback or discuss the article in the magazine forum.

Three Bundler Benefits

Bundler Gives You Pay-as-you-go Gem Management
by Paolo Perrotta
Bundler is a gift you should open right away.

You may have heard about Bundler, a rising star in the latest wave of Ruby tools. Bundler’s specialty is libraries management: it helps you to sort out the gems that your projects need.

With all the interesting tools coming out lately, you might be tempted to file Bundler under “cool stuff I’ll eventually look at,” together with the latest testing framework and NoSQL database. However, there is a good reason to adopt Bundler in your own project right now: Bundler is a pay-as-you-go technology. It doesn’t force you through a steep learning curve like other tools do (cough, vim, cough). You can reap a few benefits out of Bundler in a matter of minutes, and the more time you invest in it, the more time-saving features you seem to discover.

In this article I’ll show you three very cheap, very quick ways to get a little help from Bundler. But first, let me explain why you should use Bundler in the first place.

Isn’t RubyGems Enough?

RubyGems is a powerful, flexible package manager. However, there is one place where even RubyGems has trouble reaching: inside your projects.

By “project,” I mean anything from a simple script to a full-fledged Rails app. RubyGems doesn’t know anything about this stuff. When you install a gem, RubyGems just adds it to a global list of system gems. As this list grows, it can become difficult to tell which gems are used by which projects.

You might have experienced some of that confusion yourself. Maybe you checked out the latest version of your team’s project, and saw it crash because of a missing gem. Maybe you were left wondering which gems in your system you could safely uninstall without hurting some long-forgotten project. Or maybe your freshly deployed system crashed because of a gem on the production machine that wasn’t the exact same version you’d been using in development. In general, per-project gems management can turn out to be more trouble than you might expect.

For years, Ruby programmers have rolled out their own custom-made solutions to this problem. Now we have Bundler, which builds upon RubyGems to give you a number of project-focused goodies.

First Benefit: A List of Gems You Can Rely On

First, install Bundler—it’s a gem itself:

gem install bundler

(You might need to run most commands in this article as a superuser, with the sudo command. Also, you need RubyGems 1.3.6 or later to install Bundler. You can check your current RubyGems version with gem --version, and update it with gem update --system.)

OK, now you have Bundler. Pick one of your existing projects, or just create a test project—a directory containing a simple Ruby script. Go to the project’s root directory, fire up your editor and create a file named Gemfile. In the Gemfile, list the gems that you want to use in your project. Use this syntax:

source :rubygems

gem "activerecord"

gem "json"

The first line in the Gemfile points Bundler to a place where it can download missing gems—in this case, the official RubyGems host. If you want to be sure that all the gems in the Gemfile are installed on your system, just issue Bundler’s most popular command:

bundle install

Bundler checks whether you already have all the gems that your project needs. If you don’t, it installs the missing gems—and the gems they depend upon. When I ran bundle install on my system, that already had json installed, Bundler installed seven more gems: activerecord, and six other gems that activerecord depends upon.

You already got one benefit out of Bundler: now you have an authoritative list of your project’s gems, and you can install them all with one command. You could do the same with a simple script that calls gem install, but Bundler does that in a standard way, so anyone looking at your project will immediately see the Gemfile and understand what’s going on. Also, Bundler looks at the list of gems and their dependencies all at once, rather than one at a time like RubyGems does. As result, Bundler is better than RubyGems alone at preventing conflicts that can result from complex tangles of dependencies. Those conflicts tend to be rare on small project, but they’re more and more likely to happen as your list of gems grows longer.

One word of warning, though: if you install your gems through Bundler, you should also use Bundler to launch your gems’ command-line utilities. For example, instead of writing cucumber, you’d write:

bundle exec cucumber

If you don’t do that, your commands will probably work anyway, but they may stop working later—for example, when you update your system’s gems.

One More Thing about the Gemfile

If your Gemfile don’t specify a gem’s version, then Bundler will just download the latest version, or use whatever version it finds on your system. However, for some gems you usually want to stick to a specific version, or a restricted range of versions.

For example, maybe you’re using a feature of the json gem that’s been implemented in version 1.4.0—so you need that version, or a later version. But suppose a future version 1.5 turns out to be incompatible with your current code—so you want a version earlier than 1.5.0. You can tell Bundler about these constraints by using the standard RubyGems version operators:

gem "json", ">= 1.4.0", "< 1.5"

Or specify this range of versions more succinctly with the ~> operator:

gem "json", "~> 1.4"

Enough with the Gemfile. Let’s look at the lock file, one of Bundler’s killer features.

Second Benefit: No More “It Works On My Machine”

Your Gemfile is your way to tell Bundler: “I want these gems on my system.” However, the Gemfile alone doesn’t solve the problem of running the same project on another system.

Imagine this scenario: in your Gemfile, you specified that you want the json gem, version 1.4.0 or later. On your system, you have json 1.4.3 installed, so Bundler will happily use that version. You colleague Bill, however, has json 1.4.2, which also satisfies Bundler, but happens to be plagued by an obscure bug. The entire project runs fine on your box, but it crashes spectacularly on Bill’s machine.

You might solve this problem by always specifying the exact version that you need for each gem, down to the minor version:

gem "json", "= 1.4.3"

However, even such a meticulously crafted Gemfile wouldn’t guarantee that you and Bill are sharing the same exact gems, because your project might indirectly depend on gems that aren’t even mentioned in the Gemfile. For example, the activerecord gem depends on the arel gem. If Bill has a different version of arel already installed on his system, you might still have a problem.

To really fix this problem, you have to specify the exact version of each and every gem that your project depends upon, either directly or indirectly, and keep this specification aligned with the gems on your system. Doing that by hand would be a mind-numbing maintenance hassle for most projects. The good news is that Bundler can do it for you—in fact, it already did.

Look in your project’s directory right now, and you should see a file named Gemfile.lock. This file, also known as the lock file, is not meant to be edited by hand. Instead, Bundler silently updates it every time you run bundle install.

Like the Gemfile, the lock file contains a list of gems, although in a different format. While the Gemfile only lists the top-level gems that you’re directly using, the lock file is a complete snapshot of all the gems you’re using and the gems they depend upon, including their exact versions:

GEM

remote: http://rubygems.org/

specs:

activemodel (3.0.3)

activesupport (= 3.0.3)

builder (~> 2.1.2)

i18n (~> 0.4)

activerecord (3.0.3)

activemodel (= 3.0.3)

activesupport (= 3.0.3)

arel (~> 2.0.2)

tzinfo (~> 0.3.23)

activesupport (3.0.3)

arel (2.0.4)

builder (2.1.2)

i18n (0.4.2)

json (1.4.6)

tzinfo (0.3.23)

PLATFORMS

ruby

DEPENDENCIES

activerecord

json (~> 1.4)

You’re never supposed to edit the lock file—Bundler does it for you. When you run bundle install, Bundler checks whether the very detailed information in your lock file is consistent with the sparsely detailed information in the Gemfile. If it’s not, it assumes that you’ve edited the Gemfile, and it updates the lock file to make it consistent with the Gemfile. Then it proceeds to install the exact gem versions that are listed in the lock file, unless they’re already available on your system.

If you add both Gemfile and Gemfile.lock to your repository, your colleague Bill will be able to check out the project, run bundle install, and get the exact same gems that you have, down to the specific version. This alignment goes a long way to avoiding mysterious “it works on my machine” problems.

If Bill wants to add a new gem to the project, he can manually edit the Gemfile and then run bundle install. If he wants to update an existing gem, he can do so with bundle update <gemname>, or just use bundle update to update all gems to their latest versions. Once Bill has committed the updated Gemfile and Gemfile.lock to the repository, anybody on the team can check out the changes and run bundle install to align with the current state of the project.

But wait: what if you check out updated versions of Gemfile and Gemfile.lock, but you fail to call bundle install?

Third Benefit: Make Your Project Bundle-aware

So far, Bundler knows about your project and the gems it needs. On the other hand, your project still doesn’t know about Bundler. Usually this isn’t a problem. By default, Bundler installs your gem in the same global location that RubyGems uses—so you don’t have to do anything special to use the Bundler-installed gems in your project. You can just require the gems as you would with regular, manually installed gems.

If you do that, however, your project will require whatever gems are installed on your system, regardless of what your Gemfile says. If you forget to run bundle install before you run your project, you might expose your code to a gem that is not listed in the Gemfile, or to the wrong version of a listed gem, sliding back into pre-Bundler confusion. Also, as you get into the most advanced features of Bundler, you might decide to install a project’s gems to an alternate location—maybe inside the project itself. Once you do that, your project won’t be able to find the gems in the default system location.

You can prevent all these issues by adding two lines of code to your project:

require "rubygems"

require "bundler/setup"

(You need to load rubygems before you require bundler/setup, because Bundler is itself a gem. You can skip the first line if you’re sure that rubygems is enabled by default on all your target systems).

Now your code and Bundler are really working together. You can install gems through Bundler, and Bundler tells your code which gems are available and where to load them from. If you have a gem on your system that’s not listed in your Gemfile, then your code will flat-out refuse to load it. If a gem is listed in your Gemfile but you forgot to install it, your code will fail with a graceful error message that clearly points you to the problem, and you’ll be able to fix the situation by running bundle install. Quite a list of features for two lines of code, isn’t it?

Keep Paying, Keep Going

I showed you three juicy low-hanging fruits that you can pick and taste in a matter of minutes. However, you can do much more than that with Bundler. You can define separate groups of gems for different environments, like separate gems for the development and production machines. You can package your gems inside your project folder and commit them to your repository as part of the project. You can even list a git repository as a source to download gems (for example, by using a GitHub URL), so that you always get the very latest committed version of any library. Bundler’s bag of tricks is surprisingly deep, and most of these tricks require just a few minutes to learn.

I told you it was worth it!

Paolo Perrotta has been developing, writing and speaking at conferences for longer than he’d care to admit. He has worked in domains ranging from embedded to enterprise software, computer games, and web applications. He also wrote the Metaprogramming Ruby book for the Pragmatic Programmers. These days, Paolo works as an itinerant coach for companies adopting agile methodologies. When he’s not on the road, he lives in a small Northern Italian village with his girlfriend and a cat. Send the author your feedback or discuss the article in the magazine forum.

New Series: Everyday JRuby

Part 1: Writing a Plugin
by Ian Dees
Ian shows off how well Ruby plays with others by using JRuby to build a plugin that reads a thermometer.

People are using JRuby for amazing things. They’re running massively scalable websites, designing grammars for new programming languages, and even stopping the proliferation of nuclear weapons.

Does that mean you have to be a superhero facing unimaginable obstacles to use JRuby? No! In this series of three articles, we’ll look at three ways JRuby can help programmers like you and me with the kinds of ordinary tasks that crop up in our day-to-day work.

A Heated Situation

Imagine you’re testing a circuit in your lab, and you need to measure the temperature at certain points throughout your test. You’re doing the number-crunching in an engineering software package like MATLAB or GNU Octave. You’d like to poll the temperature directly in your analysis program, but the thermometer came with no programmer’s manual—just a CD-ROM with a creaky GUI program.

Luckily, you know your way around a packet sniffer. You’ve discovered that the thermometer regularly connects to a configurable IP address over port 4444, sends the Fahrenheit temperature as ASCII text, and disconnects. All you need to do is write a TCP server.

Both MATLAB and Octave have some networking support built in. But they’re mostly geared toward acting as network clients. Writing a server directly in these environments would be a painful task. Fortunately, there’s an alternative.

JRuby to the Rescue

It’s possible to extend MATLAB or Octave by writing a plugin in Java. More interestingly, you can write a plugin in any language that targets the Java virtual machine—including Ruby.

The Ruby language supports the kind of experimentation and prototyping that will make server development easy—and the JRuby project makes it possible to use Ruby on the JVM.

Here’s how we might get started in JRuby. For reasons that will become clear later on, we’re going to use the Java networking APIs, even though they’re a little more verbose than the Ruby ones.

First, let’s pull a few Java I/O classes into the Ruby namespace. This step isn’t strictly necessary—we could just spell out the full names in the middle of our code. But this will keep things readable later on. Create a file called temperature_taker.rb, and type the following lines into it:

jruby-lab/manual/temperature_taker.rb

require 'java'

import java.io.BufferedReader

import java.io.InputStreamReader

import java.lang.Double

import java.net.ServerSocket

Now, we’ll add the code that does the real work. We open a socket, wait for the temperature to come in, and convert the result to a number:

jruby-lab/manual/temperature_taker.rb

server      = ServerSocket.new 4444

client      = server.accept

stream      = client.getInputStream

reader      = BufferedReader.new InputStreamReader.new(stream)

temperature = Double.parseDouble(reader.readLine)

client.close

puts "Temperature is: #{temperature}"

Time for a quick check before we move on. Run your program like this:

$ jruby temperature_taker.rb

Once you see the Waiting... prompt, open a new terminal and send a temperature in the same format the thermometer uses:

=> $ telnet localhost 4444

<= Trying 127.0.0.1...

Connected to localhost.

Escape character is '^]'.

=> 48.0

<= Connection closed by foreign host.

As soon as you type the temperature and press Enter, the Ruby program should pick up where it left off, print the temperature, and exit.

Classing Things Up

Now that the basics are working, it’s time to start packaging this code up into a class we can call from other programs. With the same import section at the top, change the body of your code to look like this:

jruby-lab/simple/temperature_taker.rb

class TemperatureTaker

def temperature; @temperature end

def initialize

@temperature = 0.0 / 0.0 # NaN

end

def run

@server      = ServerSocket.new 4444

@client      = @server.accept

stream       = @client.getInputStream

reader       = BufferedReader.new InputStreamReader.new(stream)

@temperature = Double.parseDouble(reader.readLine)

@client.close

end

end

The body of the run function is nearly the same code as before. The only difference is that we’ve changed a few local variables into instance variables—these will come in handy when we’re controlling this class from outside. Go ahead and try the class interactively in jirb:

$ jirb -rtemperature_taker

irb(main):001:0> tt = TemperatureTaker.new

=> #<TemperatureTaker:0x48cd13 @temperature=NaN>

irb(main):002:0> tt.run

=> nil

irb(main):003:0> tt.temperature

=> 48.0

That gets us one temperature. But it’s hardly convenient to call run every time we want to take a reading.

Threads

Let’s wrap the body of the run method in a loop, so that we can keep reading temperatures as long as the server is running:

jruby-lab/temperature_taker.rb

def run

@server = ServerSocket.new 4444

while true do

@client      = @server.accept

stream       = @client.getInputStream

reader       = BufferedReader.new InputStreamReader.new(stream)

@temperature = Double.parseDouble(reader.readLine)

@client.close

end

end

Now, a call to run will go on forever without returning—at least until the networking APIs throw an exception. If we want to be able to continue with other tasks after we’ve started the server, we can run the server in its own thread. Add this function definition inside the TemperatureTaker class:

jruby-lab/temperature_taker.rb

def start

java.lang.Thread.new(self).start

end

The start method spins up a new Java thread. The Thread constructor we’re using takes a java.lang.Runnable instance. We haven’t made any mention of this interface in our Ruby class; how is it that this code is allowed to run?

JRuby is doing something nice for us here. Since Runnable requires its implementers to have a run method, and we happen to have a method with that name, JRuby presents our Ruby class as a Runnable to the Thread constructor.

As I mentioned a moment ago, a networking exception will break out of the while loop and allow the run method to finish. This is hardly the most elegant way of shutting down a server, but it’ll do for this minimialistic project. Add a stop method to the class, where you’ll terminate the loop by closing sockets:

jruby-lab/temperature_taker.rb

def stop

@client.close if @client

@server.close if @server

end

This class has some data contention in it, by the way. If you call start multiple times, or call stop and start from different threads, you can end up with the server not listening when you thought it was.

Remember the situation in which we’re using this code, though: starting a server once at the beginning of a long-running analysis program, reading a bunch of temperatures, and only shutting it down at the end of the run. Under these circumstances, this particular sin will go unpunished.

Go ahead and try out the new version of your class:

$ jirb -rtemperature_taker

irb(main):001:0> tt = TemperatureTaker.new

=> #<TemperatureTaker:0x48cd13 @temperature=NaN>

irb(main):002:0> tt.start

=> nil

irb(main):003:0> # Before typing the next line of code,

irb(main):004:0* # use telnet to send a temperature:

irb(main):005:0* tt.temperature

=> 48.0

irb(main):006a:0> tt.stop

Exception in thread "Thread-1" java/net/PlainSocketImpl.java:-2:...

=> nil

Notice that we’re not calling run directly anymore; we just call start, which returns immediately and lets our main thread continue on to other tasks.

We should expect to see an exception when we call stop, since we’re closing a socket in the middle of an I/O routine. If you like, you can modify the program to rescue the java.net.SocketException and print a message such as Server shutting down.

Running in MATLAB

All we have to do to compile this code into a class file callable from the outside world is to run jrubyc --javac on the source file:

$ jrubyc --javac temperature_taker.rb

You’re almost ready to use this class from your analysis routine.

To use a Ruby class in MATLAB, you need to give MATLAB the location of the JRuby support libraries. Add the following line to MATLAB’s classpath.txt, and modify the path to point to your JRuby installation’s lib/jruby-complete.jar file:

/path/to/jruby/lib/jruby-complete.jar

Now, you can launch MATLAB and run your analysis program. Here’s a simple routine that takes ten readings at one-second intervals, then plots them:

jruby-lab/analyze.m

javaaddpath('/path/to/your/project');

tt = TemperatureTaker();

tt.start();

fprintf('Listening for temperature for 10 seconds\n');

v = [];

for i = 1:10,

pause(1);

v(i) = tt.temperature();

end

tt.stop();

plot(v);

If you type quickly, you can enter two or three readings into telnet during that ten-second window. Afterward, MATLAB will show something like the figure.

Now, on to Octave. As of this writing, Octave’s Java integration has trouble loading the JRuby support libraries. Is there a technology that will let us compile our TemperatureTaker class in such a way that it doesn’t require any support libraries? As it turns out, there is: Mirah.

On Self-Reliance

Mirah is a programming language that has Ruby’s syntax but none of its dependencies (other than the JVM, of course). Our Ruby example can be turned into a valid Mirah file with just three minor changes:

1. Remove the line require 'java' from the beginning of the file.

2. Add the line implements Runnable just inside the TemperatureTaker class definition.

3. Change the text java.lang.Thread to just Thread inside the start method.

Here’s the completed Mirah file:

jruby-lab/temperature_taker.mirah

import java.io.BufferedReader

import java.io.InputStreamReader

import java.lang.Double

import java.net.ServerSocket

class TemperatureTaker

implements Runnable

def temperature; @temperature end

def initialize

@temperature = 0.0 / 0.0 # NaN

end

def run

@server = ServerSocket.new 4444

while true do

@client      = @server.accept

stream       = @client.getInputStream

reader       = BufferedReader.new InputStreamReader.new(stream)

@temperature = Double.parseDouble(reader.readLine)

@client.close

end

end

def start

Thread.new(self).start

end

def stop

@client.close if @client

@server.close if @server

end

end

Once you have Mirah installed, you can compile the example to a class file using the mirahc command:

$ mirahc temperature_taker.mirah

Now you can take out the entry you added to MATLAB’s classpath.txt earlier, and run the analysis program as before.

Even better, you can now measure temperatures from Octave as well:

jruby-lab/analyze.octave

javaaddpath('/path/to/your/project');

tt = java_new("TemperatureTaker");

tt.start();

fprintf('Listening for temperature for 10 seconds\n');

v = [];

for i = 1:10,

pause(1);

v(i) = tt.temperature();

end

tt.stop();

plot(v);

As you can see, the Octave version is nearly identical; the only difference is the syntax for creating Java objects. To run this example, you’ll have to enable Octave’s Java support on your machine.

Wrapping Up

With just a few lines of code, we’ve written a MATLAB/Octave plugin for our hypothetical networked thermometer. By starting in the JRuby interpreter, we were able to code interactively: type in some Ruby, send a few temperature readings, modify our program while it’s running, and so on.

Building the final plugin in Mirah let us keep the lightweight Ruby syntax without having to bundle the JRuby runtime with our plugin.

Are there times when you’d want to just stay in JRuby, rather than moving to Mirah? Sure—if you’re using third-party Ruby libraries like Rails, it makes sense to just code in Ruby and deploy your program along with the JRuby runtime and libraries.

In the next installment of this series, we’ll do just that.

The source code shown here is available at http://github.com/undees/pragpub. Special thanks to Charles Nutter and Nick Sieger for reviewing this article.

By day, Ian Dees slings code, tests, and puns at a Portland-area test equipment manufacturer. By night, he dons a cape and keeps watch as Sidekick Man, protecting the city from closet monsters. Ian is the author of Scripted GUI Testing With Ruby and co-author of the upcoming Using JRuby. Send the author your feedback or discuss the article in the magazine forum.

Cohesive Software Design

Cohesion makes code easier to understand, debug, and test.
by Tim Ottinger, Jeff Langr
Cohesion—the principle that “things that belong together should be kept together”—makes code easier to understand, debug, and test.

The Agile In A Flash deck we’re developing for the Pragmatic Bookshelf forced us to be very concise in expressing ideas about agile development, since we were constrained to very small spaces (5”x7” index cards). But we are passionate about some large ideas that we simply could not fit on the cards. We also had a limited number of cards, so we emphasized agile topics over broader topics such as design or the theory of constraints.

Our intent with this PragPub article series is to provide more depth than cards can ever do, and to help provide some of what we think are critical, missing pieces. We’ll start with design. We believe that agile endeavor in the absence of good design sense is folly and a recipe for disaster.

The biggest ideas in software are:

1. Cohesion - proximity should follow dependency

2. Coupling - dependency should be minimized

3. Abstraction - hiding details simplifies code

4. Volatility - changes tend to cluster.

To some developers, these big ideas may sound like academic theories and CS dogma, disconnected from the real world of releasing new code every few days, every few weeks, or every few hours. But nothing could be further from the truth. Programmers famously complain and agonize over the pile of code they have to deal with, yet these four ideas succinctly describe the situation we are in, how it came to be, and how we can move forward. If we understand how these ideas apply to us, we can improve the code we write so that our software becomes increasingly workable.

We’ll talk about cohesion this month, and follow up with the other three ideas in later articles.

What is Cohesion?

Cohesion tells us that proximity follows dependency—simply put, “things that belong together should be kept together.” The classic OO design involves grouping data and the functions that act on it. We can understand cohesion as a measure of how exclusively an object’s methods interact with its data and how exclusively an object’s data is used by its methods.

Cohesion has been egregiously violated when an object’s function does not use any of the object’s data, when an object contains data that is not used by its own functions, or when an object has a function that deals only with the data of some other object. Less egregious violations are common, where a function deals with some of its object’s data but deals also with the data or functions exposed by another object. Code smells such as feature envy and primitive obsession are tip-offs to a lack of cohesion.

Lack of cohesion can also be apparent from an external perspective: If you find that approaching any system behavior via one path (command, screen, or web page) produces different results than approaching the same behavior from a different path, you’ve been bitten by duplication as an effect of poor cohesion.

Good cohesion makes it possible to find functions easily. If methods dealing with an address are located in the Address class, someone working with an address can easily find the method they need and call it, instead of re-implementing it from scratch. If functions that deal with an address are buried inside an mail-authoring component, a programmer working outside of that component is unlikely to find them. He may end up rewriting the needed behavior into the function he is working on so that afterward it is still not in the Address class. Later his coworkers will re-implement it again. Without cohesion, duplication propagates.

Cohesive code forms tighter, more testable objects. Testability has gained a lot of prominence due to test-driven development (TDD), acceptance TDD (aka ATDD), behavior-driven development (BDD), and their fellow travelers. A method with poor cohesion may do many things in the course of trying to accomplish some other goal entirely. These side-effects make it hard to test. The non-cohesive method may also bury some functionality in a maze of if/else statements that require careful and complex setup. A cohesive class is comparatively trivial to unit test.

Cohesion Simplifies Objects

In a system with primitive obsession, related data is passed around as loose variables to any number of functions, not combined into an abstract data type or class. These functions operate directly on the data—creating disjoint (non-cohesive) code—and will often re-implement common operations on the data in the course of fulfilling their own behaviors.

As cohesion is improved the loose variables are pulled together into a new class, and the functions that operated on the loose data are also moved into the class. This simplifies the old data-using methods, reduces code duplication, and establishes a home where others can expect to find similar functions. It greatly shortens parameter lists for many functions. A properly cohesive design can also allow for optimizations like lazy loading or caching that wouldn’t be possible if the functionality were still spread across the application.

Closely related to cohesion, the Single Responsibility Principle (SRP) tells us that each class should do one thing and one thing only. Following SRP results in a cohesive class structure in which each class is a “conceptual center” in the application. You know why you should go there, and what it should do, and why it should change. You can understand it as a whole. It is deucedly hard to give a meaningful name to an amorphous blob of functionality, but when a class does one thing it is relatively easy to name it.

Another way of violating cohesion is seen in packaging structures that are defined according to some architectural ideal instead of being based on common dependencies among objects. Poor packaging makes systems harder to refactor, harder to comprehend, and slower to build and deploy than systems that are packaged according to the principle of cohesion.

An Example

The following bit of code is from a free-source game. It exhibits a classic way to violate cohesion: throwing everything into an application startup class. In this case, we have a number of hints that there’s a problem (other than the class source file being over 3000 lines long). We can take a look at the fields on the class:

private StringTokenizer StringT;

protected RiskController controller;

protected RiskGame game;

private PrintWriter outChat = null;

private BufferedReader inChat = null;

private ChatArea chatter = null;

private Socket chatSocket = null;

private ChatDisplayThread myReader = null;

private int port;

protected String myAddress;

private ByteArrayOutputStream Undo = new ByteArrayOutputStream();

protected boolean unlimitedLocalMode;

private boolean autoplaceall;

private boolean battle;

private boolean replay;

protected Vector inbox;

protected ResourceBundle resb;

protected Properties riskconfig;

The class has numerous reasons to change, an obvious violation of the SRP and thus an indicator of poor cohesion. We made some assumptions about what this class does, based solely on analyzing the field names and types:

- loads information from or stores information to a properties file

- contains flags for managing game properties (replay, battle, autoplaceall)

- manages a socket-based server

In other words, about the only thing all these variables have in common is that they appear in the same program.

A look at the methods confirms that these and many more responsibilities are munged together. The bulk of the class code appears in a single 1800-line-long method named GameParser, a name that turns out to not be so precise. This method serves not only the purpose of tokenizing input coming from the socket server (see the elided example below), but also is in charge of interacting with the game controller object that embodies most of the game rules (not shown).

String T = new StringTokenizer( message );

String Addr = GetNext();

if (Addr.equals("ERROR")) { // server has sent us a error

// ...

}

else if (Addr.equals("DICE")) { // a server command

// ...

}

else if (Addr.equals("PLAYER")) { // a server command

// and on and on...

The game built on this source base is at least five years old, and continues to be maintained by its sole programmer with several releases a year. (We chose this example as a fairly typical source of cohesion violation, despite its being a sole-programmer effort. It exhibits characteristics common to most source bases we’ve ever worked on. Yet it’s actually an enjoyable and now fairly solid game.) The programmer is no doubt intimately familiar with the code, and has the advantage of not working in a team of seven or twenty or two hundred programmers. Still, the release log is dominated by notes that start with the word “FIXED,” particularly in the first few years of release.

Instead of continuing to conjecture about another programmer’s experience, we’ll relate our observations of the impact of poorly cohesive code in larger, more enterprise-y source bases. Over time, original programmers lose familiarity with the continually growing code base and sometimes leave the project. The shortcomings of the source base become more visible and apparent to everyone who remains.

We learn of more defects. We are frustrated by the difficulty of setting up just the right conditions to replicate the defects in unit tests so that we can fix them. We spend more time, far too much time, in simply understanding what’s going on in a disjoint class. We spend still more time determining the total effect from even trivial modifications on line 200 of an 1800-line monolith. The ugliness causes no end of other nuisances; for example, having so many variables in the same address space makes automatic code completion less satisfying.

It doesn’t have to be this way. As stated in Uncle Bob’s book Clean Code, the first rule of functions, and also of classes, is that they should be small. The second rule is that they should be smaller than that. While it’s possible to go overboard with a notion of ever-smaller, it’s actually very rare, and it’s pretty obvious when methods are no longer pulling their weight. Don’t fear tiny methods and classes.

Try it. As a simple exercise, break one or more longer (20+ line) methods up by simply extracting small, logically related chunks of code. In Java or C#, take advantage of your IDE to make this a reasonably safe exercise. Sometimes you can use “guiding comments” as hints on what bits of code you might extract. Once you’ve extracted the methods, re-examine them. Do they really depend on the core concepts of the class in which they’re defined? Or could you potentially move them to another existing class? Or do they represent a new abstraction entirely that you can embody in a separate class? (We’ll provide some code examples in an upcoming article on abstraction.) Can you spot simple two- or even one-line repetitions in the longer methods that you could extract to a simpler abstraction, possibly generating some valuable reuse?

Cohesion is a practical issue, and not at all a matter of some abstract sense of design purity. When proximity follows dependency, your system becomes easier to use, easier to fix, and sometimes easier to optimize. Work mindfully, and see where your new appreciation of cohesion takes you this month.

Jeff Langr has been happily building software for three decades. In addition to co-authoring Agile in a Flash with Tim, he’s written another couple books, Agile Java and Essential Java Style, contributed to Uncle Bob's Clean Code, and written 90+ articles on software development. Jeff runs Langr Software Solutions from Colorado Springs, where he also pair-programs full-time as an employee of GeoLearning.

Tim Ottinger has over 30 years of software development experience coaching, training, leading, and sometimes even managing programmers. In addition to Agile in a Flash, he is also a contributing author to Clean Code. He writes code. He likes it. Send the authors your feedback or discuss the article in the magazine forum.

When Did That Happen?

The Machine of the Year
by Dan Wohlbruck
If the personal computer was the machine of the year 1982, was 1982 the definitive year of the personal computer? And with pods and pads and phones replacing desktop machines, will we soon see the last year of the personal computer?

On December 26, 1982, Time magazine named the personal computer its man—or machine—of the year. Time’s editors reported that for 1982, more than 100 companies were building personal computers and predicted that they would sell almost three million units for revenues of just under five billion dollars. The magazine conducted a poll and found that 80% of Americans believed that the personal computer would soon become as commonplace as the television set. Machine of the Year indeed.

If anything, the public underestimated the speed with which the PC would be adopted and the impact that it would have.

The PC Era

The PC catapulted to prominence in 1981 when IBM introduced the model 5150, built in Boca Raton, Florida, and made largely from off-the-shelf electronics and running a DOS operating system. When the company decided to ditch the model number in favor of the initials, the term PC went mainstream. By 1990, the IBM PC and its clones had overtaken both the Apple Macintosh and the Commodore 64 as the world’s preferred small computing device.

Exactly eight years to the day after the PC was featured on the cover of Time magazine, on December 26, 1990, Tim Berners-Lee placed the first web page on the Internet. It was the start of a little experiment that he called the World Wide Web. On that day there was one web page on the Internet. By 1999 the one billionth document was added to the World Wide Web. It was already beyond any person’s or computer’s ability to catalog. It wasn’t for lack of trying. In 2001, Google surveyed one billion unique web URLs (Universal Resource Locators) for the first time. Within less than ten years, the World Wide Web took the Internet from its academic roots to Main Street. Without the PC and the network, of course, there would be no possibility of—and no need for—a World Wide Web.

Since February of this year, we’ve been surveying innovations in technology, discussing each innovation in the month that it came into existence (or tying the article to some other convenient date in the history of the technology).

End of an Era

As we’ve considered different technologies, I claim that we’ve seen a pattern emerge. From the typewriter to the telegraph and then the radio, a technology or a device is invented, it suffers growing pains, it is accepted and adopted, and it is finally superseded by something else. Typically, it takes about 25 to 30 years for the process to run its course.

In the tradition of year-end predictions, I claim that the PC fits into the same mold. The desktop PC is already a relic and within five years the laptop will be nothing more than an overweight piece of luggage completely replaced by tablets and small, personal smart phones. What was once heralded on the cover of Time will be unknown to our grandchildren.

The Internet, however, and the World Wide Web will persevere.

What’s the difference?

The PC was all about electronics, economics, and empowerment. When computer components could cheaply be placed on a silicon wafer, society could take advantage of a device that entertained, educated, and empowered it beyond anything that had been known before. Once men and women with vision saw the same result being delivered with more powerful chips and more friendly devices, the death of the personal computer was inevitable.

The Internet and its World Wide Web are more about ideas than they are about machines. No one owns the Web, no one entity sets its course, and everyone benefits from it. HTML leads to CSS and XML, and the Web is a better place for it. The Internet will, eventually, be powered by something other than servers. Perhaps some space-based satellite will ultimately route messages and MPEGS. But the Web, in some form, will endure.

It began 28 years ago—and it continues.

Dan Wohlbruck has over 30 years of experience with computers, with over 25 years of business and project management experience in the life and health insurance industry. He has written articles for a variety of trade magazines and websites. He is currently hard at work on a book on the history of data processing. Send the author your feedback or discuss the article in the magazine forum.

Calendar

Author sightings, partner events, and other notable happenings.

Ruby Events

In keeping with the Ruby focus of this issue, let’s start off with a couple of big upcoming Ruby events. Note: this calendar only looks three months ahead. To see what Ruby events are coming up later in 2011, take a look at ruby there or railsevents.com.

- Jan 12–14, CodeMash, Sandusky, OH
Code Mash: “CodeMash is a unique event that will educate developers on current practices, methodologies and technology trends in variety of platforms and development languages such as Java, .NET, Ruby and PHP. Attendees will be treated to an impressive set of keynote addresses from industry luminaries. CodeMash 2010 had keynotes from Mary Poppendeick, Andy Hunt, and Hank Janssen.” Note: CodeMash 2011 sold out (in just four days).

- Feb 4–5, Magic Ruby, Orlando, FL
Magic Ruby at the Magic Kingdom: Bring the kids! (Or the kid in you.) Chad Fowler will deliver the keynote here as well as at Code Mash. Other Magic Ruby speakers will cover topics from developing Cocoa apps with MacRuby to getting started with cloud computing.

Author Appearances

- Dec 1–3, Summit 2010 Europe, London, UK
Workshop Seminar: “Agile in the Workplace”Rachel Davies, co-author of Agile Coaching

- Dec 2–3, Agile, Lean & Kanban EXchange, London, UK
SpeakingRachel Davies, co-author of Agile Coaching

- Dec 7–10, Pragmatic Studios, Denver, CO
“iPhone/iPad Programming” with Matt DranceDaniel Steinberg, co-author of iPad Programming: A Quick-Start Guide for iPhone Developers and author of Cocoa Programming: A Quick-Start Guide for Developers

- Dec 8, DSDM Sweden, Stockholm, Sweden
“Pomodoro Technique: Can you focus for 25 minutes?”Staffan Nöteberg, author of Pomodoro Technique Illustrated

- Dec 8–10, Pragmatic Studios, Denver, CO
Pragmatic Rails Studio with Dave ThomasChad Fowler, author of The Passionate Programmer

- Dec 9, IIBA, Boston Chapter, Waltham, MA
“The Role of the BA in an Agile Project”Johanna Rothman, author of Manage Your Project Portfolio: Increase Your Capacity and Finish More Projects, Manage It!: Your Guide to Modern, Pragmatic Project Management, and Behind Closed Doors: Secrets of Great Management

- Dec 13, Cleveland CocoaHeads, Cleveland, OH
“Understanding Blocks in Objective-C”Daniel Steinberg, co-author of iPad Programming: A Quick-Start Guide for iPhone Developers and author of Cocoa Programming: A Quick-Start Guide for Developers

- Jan 12–14, CodeMash, Sandusky, OH
KeynoteChad Fowler, author of The Passionate Programmer

- Jan 12–14, CodeMash, Sandusky, OH
“iOS Development: A Fresh Start” and “What’s new in iOS”Daniel Steinberg, co-author of iPad Programming: A Quick-Start Guide for iPhone Developers and author of Cocoa Programming: A Quick-Start Guide for Developers

- Jan 12–14, CodeMash, Sandusky, OH
“iOS Development in the Real World” and “The Dark Depths of iOS”Chris Adamson, co-author of iPhone SDK Development

- Jan 25–28, Pragmatic Studios, Reston, VA
“iPhone/iPad Programming” with Matt DranceDaniel Steinberg, co-author of iPad Programming: A Quick-Start Guide for iPhone Developers and author of Cocoa Programming: A Quick-Start Guide for Developers

O’Reilly Events

As publishers who think of ourselves as being on the cutting edge, we’re always interested in O’Reilly’s Tools of Change conference.

- Feb 1–3, Strata, Santa Clara, CA
O’Reilly Strata Conference: “Get control of the new data opportunity at Strata—immerse yourself in three full days of hands-on training, information-rich sessions, and a sponsor pavilion filled with the key players and products. This new O’Reilly conference brings together the people, tools, and technologies you need to make data work.”

- Feb 14–16, TOC, New York, NY
O’Reilly Tools of Change Conference: “Join us as we explore this new world of ‘Publishing Without Boundaries’ at the fifth annual O’Reilly Tools of Change for Publishing Conference.... This premiere event provides an unparalleled opportunity for stakeholders from across the book publishing and tech industries to network, share ideas, engage in lively debate, and consider the many issues we face individually and collectively.”

USENIX Events

What’s coming from our USENIX friends.

- Feb 15–18, FAST ’11, San Jose, CA
9th USENIX Conference on File and Storage Technologies: “FAST ’11 brings together storage system researchers and practitioners to explore new directions in the design, implementation, evaluation, and deployment of storage systems.”

Other Happenings

- Dec 3
John Backus would have been 86.

- Dec 4
Eric Raymond, aka ESR, is 53.

- Dec 9
Grace Hopper’s 104th birthday.

- Dec 10
Ada Lovelace’s 195th birthday.

- Dec 10
Ada, the programming language, is 30 today.

- Dec 10
PragPub’s editor’s having a birthday today. He’s younger than Ada and older than Ada.

- Dec 16
John Bardeen and Walter Brattain created the first transistor on this day in 1947.

- Dec 17
Ken Iverson, creator of APL, would have been 90 today.

- Dec 17
Les Earnest, inventor of first spell checker and of the finger protocol, is 80.

- Dec 23
Birthday of Bob Miner, who wrote Oracle’s original database software.

- Dec 25
Richard Greenblat, famed MIT hacker, is 66.

- Dec 26
Charles Babbage’s 219th birthday.

- Dec 28
Linus Torvalds is 41.

- Dec 30
Bjarne Stroustrup is 60.

- Dec 31
Leonard Adleman, the A in RSA encryption, is 65.

- Jan 10
MUD co-creator Richard Bartle is 51.

- Jan 10
Donald Knuth, who continues to inspire authors who are having trouble finishing that book, is 73.

- Jan 11
Tony Hoare, author of Quicksort, is 77.

- Jan 20
Sims creator Will Wright is 51.

- Jan 21
Paul Allen is 58.

- Jan 22
On this day in 1984, Superbowl viewers watched a woman with a hammer smash Big Brother.

- Jan 24
Alain Colmerauer, Prolog’s creator, is 70.

- Jan 25
Pac-Man creator Toru Iwatani is 56.

- Jan 31
Guido van Rossum, author of Python and possessor of an excellent last name for a programmer (Google “R.U.R.”), is 55.

- February
In February, 1986, Richard Stallman published the first official definition of Free Software. In February, 1992, Linus Torvalds first placed Linux under the Gnu Public License. In February, 1998, the Open Source Initiative was founded. And in February, 2001, at The Lodge at Snowbird ski resort in the Wasatch mountains of Utah, seventeen people wrote the Agile Software Development Manifesto.

- Feb 4
Ken Thompson is 68.

- Feb 5
Brad Fitzpatrick, author of memcached, is 31.

- Feb 7
Leslie Lamport, creator of LaTeX, is 70.

- Feb 8
MIT professor Gerald Jay Sussman is 64. Among his other accomplishments, he is a bonded locksmith, so he can stay out till quarter to three and not worry about anyone locking the door.

- Feb 12
Phil Zimmerman, author of PGP, is 57.

- Feb 15
Niklaus Wirth is 77.

- Feb 16
Ward Christensen created the first Computer Bulletin Board System on this date in 1978.

- Feb 19
CGDA Hall of Fame game developer Danielle Bunten would have been 62 today.

- Feb 22
Bill Jolitz is 54.

- Feb 24
The Ruby programming language was conceived on this date in 1993.

- Feb 27
Grady Booch is 56.

- Feb 29
Seymour Papert would be 83 this year if it were a leap year.

Shady Illuminations

The Cat, the Diamond, and Other Beautiful Losers
by John Shade
John finds that fairness isn’t fair and better is the enemy of even better.

Mother Nature makes the rules. She picks the winners and the losers. Pretty much like Oprah. She has a lot of power, and you know what they say about power.

I mean “power corrupts.” In case you thought I was referring to Joule’s Law.

According to Wikipedia, which I consulted just now to make sure I actually meant Joule’s Law and not, say, Blaauw’s Law, Joule’s Law says:

(apparent power)^2 = (real power)^2 + (reactive power)^2

I consider myself both real and reactive, and now and then I convince myself that I have some power. But sooner or later Nature explains to me that any power I think I have—real or reactive—is purely imaginary. Which would make both terms on the right side of that equation negative. Likewise the expression on the left side. No wonder nobody takes me seriously.

Anyway, I think her absolute power has corrupted Nature to the point where she doesn’t care about the rules—or about logic—when she’s picking the winners and losers. Much like the audience for “Dancing with the Stars.”

Trolling the Dice

Take the case of nontransitive dice. (Even if you think you know all about nontransitive dice, you might want to follow the link just for the Warren Buffet-Bill Gates anecdote.)

You’d think it would be a basic requirement for gambling that “beats” would be transitive. If I beat Lottie and Lottie beats Luigi, then surely I beat Luigi. Otherwise what sense is there in the universe?

Beats me. Which Luigi does, again and again. It turns out that Nature has rigged the odds, and she permits a numbering of the faces of three cubes so that if Luigi and Lottie and I each take one of these dice and roll against one another pairwise for a sufficient number of rolls, I’ll consistently trounce Lottie, Lottie will routinely clobber Luigi, and despite my obvious superiority over the two of them, I’ll reliably lose to Luigi.

It’s like stochastic perpetual motion. Or a shell game:

Lottie played Luigi’s game;

Paid in queer and split for Maine.

Brady was Luigi’s shill;

Took his pay in phony bills

And sent it off for alimony

To his old lady, Lottie Brady.

In case you’re not up on carnival slang, queer is counterfeit money and a shill is a confederate who poses as a winning gambler to induce bystanders to participate in a crooked game. The point is, Nature is running a rigged game. And what goes for Nature goes double for technology.

In the Backwash of Progress

Every day a new technology replaces an old one. In every such case, the new technology is an obvious improvement over the old one. This is only natural. The new technology was designed with the defects of the old one in mind. It fixes those defects. It has to be better. Think of James Dyson, observing that vacuum cleaners suck and coming up with a better vacuum cleaner. It still sucked, but he was able to get people to pay £2,000 for it. So it was clearly better.

And yet we can all think of cases where some old technology is demonstrably better than the new one that replaced it. How can this be?

Because technological progress, like Nature, cheats. For example:

Now that CDs are being replaced by phones, the backlash against the CDification of sound has subsided. There may still be some audio aficionados who have every edition of The Absolute Snob and think that digital recording is ruining music. I don’t have a horse in that race; my ear’s always been too tin for that. But I do have one beef with digital audio: the volume control. Even my tin ear can discriminate dozens of jnds of sound volume. More to the point, it feels like the experience is a continuum. I want to crank that knob until the volume is just right. But no, technological progress has taken away the analog volume control.

Or typewriter keys. You know what was so great about typewriter keys? They were designed for human hands. There’s a radical concept. What twisted mind came up with that screwball idea? And does anybody have his number?

It wasn’t Jef Raskin, but Jef was someone who designed a tool for creatures with human hands. His Canon Cat had ease of use that has never been replicated in any subsequent computer, pod, pad, or phone. Content persistence, modelessness, commands instead of applications, navigation using incremental text search—and you do it all without lifting you hands from the keyboard.

Well, we’ve fixed that. Hundreds of thousands of hours of developer effort have gone into making operating systems better. From the primordial ooze of CP/M, we advanced to the towering summit of Windows NT. And yet somehow, no currently manufactured computer can match the performance of the Canon Cat, a machine with no operating system.

The Diamond Age

A fair amount of developer time and user research also went into the development of command-line interfaces for consumer apps. All that was lost with the advent of GUIs, which were demonstrably slower. Progress.

And then there’s the WordStar diamond. Wordstar was a word processing program with an interface designed for touch typists. Just more craziness.

Asking what we have given up for what we have gained is never popular but always appropriate. Out on the freeway, a line of cars hurries away from wherever you’re going in such a rush. Hidden under the machinery, the up escalator creeps perpetually downward. The ladder of technological progress was apparently designed by M. C. Escher.

John Shade was born under a cloud in Montreux, Switzerland, in 1962. Subsequent internment in a series of obscure institutions of ostensibly higher learning did nothing to brighten his outlook. He’s got Nature’s number, but she won’t return his calls. Send the author your feedback or discuss the article in the magazine forum.