Skip to content

Making OpenID Usable

During the Rails Rumble ‘09, OpenID came up a lot in the #railsrumble IRC
channel.  A lot people had implemented OpenID in their app, and there was
some surprising grumbling from judges who didn’t like it.

The grumbling surprised me at first: I like OpenID.  But I think I’ve figured
out why these judges didn’t: it’s easy to do a crappy login page.

Here’s an example of a really unfriendly OpenID login page:

Yikes.

That blank white text box is like an iron door between me and this site.  I am a
nerd AND an OpenID proponent, but I do not have my provider’s URL memorized.
Even if I did, it’s a drag to type: “https://www.google.com/accounts/o8/id”

(Incidentally, Googlers: can we get https://openid.google.com for this?  C’mon,
that’s kinda cool, no?)

So, please don’t ever make me go look up my OpenID provider URL.  Particularly
if I’m using someone as large as Google for a provider.

Okay, cleanse your palatte and let’s check out an example of an EXCELLENT OpenID login page:

Kudos to you, SO team.  This page kicks ass.

Stack Overflow gives me exactly what I want on an OpenID login page: a huge button with Google’s logo on it.
Not only that, but they’ve shrunk the buttons for the less popular providers. I love that sort of touch in software.

If you’re going to support OpenID, please read the organization’s Best UX
Practices
.  Or maybe Yahoo’s OpenID Usability Research.

Then just go copy StackOverflow’s page.

I think we should shoot to have all OpenID login pages look like siblings: possessing a thread of sameness despite their differences.

Ruby Best Practices: A Review

One of my favorite simple pleasures is reading a technical or instructional book where the level of complexity perfectly matches my expertise.  I’ve been enjoying this exact experience while reading Greg Brown’s new book, Ruby Best Practices.

I have been programming professionally for over three years, with the last five months doing full time Ruby on Rails development.  I would label myself an intermediate Ruby user: comfortable with the basics, but with limited exposure to its more advanced topics.  Lately, I have been reading more and more open source Ruby projects, and have been looking for ways to contribute back to our teriffic community.

Given my experience and goals, Ruby Best Practices was a perfect read.  The book is a collection of general strategies for solving problems in Ruby, with a focus on real-world code examples. Its author is an experienced Ruby developer who also happens to be an excellent writer.

Ruby Best Practices has a number of notable strengths. First, Brown is highly pragmatic. When discussing closures, he writes “I could show some abstract examples or academically exciting functionality such as Proc#curry, but instead, I decided that I wanted to show you something I use fairly frequently.”  This attitude has lead to a book that is full of ideas you can actually use.  It feels like the experienced guy down the hall showing you all his best stuff.

Secondly, RBP’s examples are almost uniformly excellent.  As contributor or creator of several popular Ruby projects (Prawn and Ruport) Brown has no lack of real-word code examples to choose from, and he does so with skill.  In addition, he’s not shy about trimming down the examples to leave behind just the most relevant code elements.  These two factors combine to produce code listings which are indicative of real open-source programs while remaining quite comprehensible.  Not only are Brown’s examples excellent, but they are plentiful.  Nearly every new idea he introduces is demonstrated through a case study of real (or plausibly real) code.  Working through this book will definitely sharpen your code-reading skills.

Beyond simply being clear, Brown’s writing is also fun to read.  His enthusiasm for the subject matter is obvious: “I could stop here and move on to the next topic, but similar to when we looked into the belly of lazy.rb earlier in this chapter, I can’t resist walking through and explaining some cool code.”  This sort enthusiasm continues throughout, and leads to a technical book that I’m tempted to call a page-turner. Making my way through the book really excited me to read and work on open-source projects.

If you’re still on the fence, take a read through the sample chapter, Mastering the Dynamic Toolkit.  Or, if you’d prefer a quicker read, check out this post on the book’s blog to get a feel for Brown’s writing style.  If you like what you see, don’t hesitate to pick up a copy of this excellent book.

Chapter Titles:
1.  Driving Code Through Tests
2.  Designing Beautiful APIs
3.  Mastering the Dynamic Toolkit
4.  Text Processing and File Management
5.  Functional Programming Techniques
6.  When Things Go Wrong
7.  Reducing Cultural Barriers
8.  Skillful Project Maintenance
A.  Writing Backwards Compatible Code
B.  Leveraging Ruby’s Standard Library
C.  Ruby Worst Practices

Good and Not So Good Rails Code

I’ve found I learn best by example. If you do too, these examples of good and not so good Rails code might be useful.

This post is targeted at newer Rails programmers. If you’ve moved beyond the beginner stages you might not find much here for you.

Onward!

Let’s start with some code that’s not so good.


Not so good:

# app/controllers/book_controller.rb
def new
  @book = Book.find(params[:id])
  ...
end
 
def create
  @book = Book.find(params[:id])
  ...
end
 
def edit
  @book = Book.find(params[:id])
  ...
end

Why it’s not so good:

This controller contains repeated code. ALWAYS BE WARY OF THIS! Pay particular attention when you’re doing the exact same thing in multiple places. This type of code should almost always be refactored. In Rails, this duplication can be removed using a before_filter.

Better code:

# app/controllers/books_controller.rb
before_filter :find_book
 
def new
  ...
end
 
def create
  ...
end
 
def edit
  ...
end
 
protected
 
def find_book
  @book = Book.find(params[:id])
end

Why it’s better:

The repeated code has been pulled out into a method (find_book). Now, changes to the way we find books will be easy to make in this controller. Notice also that we made it protected. We only need to use this method in this controller, and a gentleman’s objects share as little as possible.


Not so good code:

# Return an array of titles
 
def all_titles(books)
  book_titles = []
 
  books.each do |book|
    book_titles << book.name
  end
 
  book_titles
end

Why it’s not so good:

Local variables can make complicated code more clear, but the variable in this method isn’t pulling its weight. It’s just a box around the stuff we’re really interested in.

Good code:

# Return an array of titles
 
def all_titles(books)
  books.inject([]) { |book_titles, book| book_titles << book.name }
end

Why it’s better:

It is a single, clear line, where each token pulls its weight. Experienced Ruby users will find this version clearer, despite its greater density.

It is possible you find this version less clear. A few months ago, I would have felt the same. Back then, inject felt a little scary: I’d only bumped into it other peoples’ code, and never written a fresh one myself. However, after a bit of experience, I find it the perfect tool in the certain situations. Think of using it particularly when you want to build up a collection (like an Array or Hash) from some other collection.

If you’d like to improve your skills with inject:
1. Check out Jay Field’s inject post (good)
2. Read its documentation and experiment in irb (better)

Update after posting:
Several commenters have (rightly) pointed out that this code is better written thusly:

# Return an array of titles
 
def all_titles(books)
  books.map(&:name)
end

Quite right guys. Inject is still great in the right spots though, and it’s well worth your time to learn it.


Not so good code:

# app/views/books/index.html.erb
 
<% for book in @books %>
  <%= render :partial => 'shared/book', :locals => { :book => book }
<% end %>

Why it’s not so good:

You’re calling a partial on a collection of objects, passing each one in through a variable. This idiom appears in Rails so frequently that a better syntax was created for it.

Good code:

# app/views/books/index.html.erb
 
<%= render :partial => 'book', :collection => @books %>

Rails will render the partial once per item in @books. Each item will be available in the variable ‘book’ (this is the name of the partial, NOT the singularization of your collection’s name).

Why it’s good:

We’re being efficient by leveraging functionality that Rails already provides for us. This version makes its intention clearer: “I’m rendering a collection.” The goal of the first version is less obvious, and takes longer to parse.

Similar to your ‘repeated code’ alarm, you should have a ‘roughly a million programmers must have written these exact lines in the past’ alarm. When that one goes off, check the Rails API and browse some plugins. Rails is great about providing you efficient ways to perform common tasks.