25 Mar, 2008

Published at 07:48PM

Tagged with code, programming, readability, and ruby

This post has 3 comments

Writing Readable Code

Writing code in Ruby is a real pleasure. It’s a very expressive language, and that allows me to make complex programming problems read like English.

For instance, at work recently I needed to authenticate against a separate system (written in .NET). I also needed to cache the user to the application’s DB for speed and convenience. And I also needed to make sure the cached version gets updated if the .NET version gets updated. Etc. Etc. Etc. The point is there was a lot to do there, but it didn’t have to appear that way.

1
User.process_login(username, password)

Once that complicated mess is abstracted, that’s all I have to do. Here’s a piece of the mixed in module that does a little more of the dirty work:

1
2
3
4
5
def process_login(username, password)
  returning Proxy.authenticate(username, password) do |user|
    cache! user if user && user.needs_cached?
  end
end

Proxy is a class that nicely handles the WSDL/SOAP communication to the .NET system; the authenticate method on the Proxy authenticates against the .NET system’s DB; the cache! method (you guessed it) does the caching based on a last-modified date comparison of the returned SOAP user versus the cached version (if there even is one). The returning part simply returns the user object or nil, depending on if the authentication was successful or not.

Hopefully you’re thinking, “there was really no need to explain all of that.” Because the goal here isn’t to focus on all of the behind-the-scenes mumbo-jumbo, it’s to give yet another example of how clearly a complex thing can be written in Ruby.

I might even be able to show that to my Mom and have her tell me what it’s doing. Well, maybe not, but the average (technically-minded) person would have no problem.

As an aside, this is what I’m really starting to love about Rspec. It sort of guides your mind into writing readable code, which I’m all about.

Comments

_eric Tuesday, 01 Apr, 2008 Posted at 07:50PM

I believe you may be misusing returning a little bit.

This may work a little better:

1
2
3
4
5
def process_login(username, password)
  returning Proxy.authenticate(username, password) do |user|
    cache! user if user && user.needs_cached?
  end
end

_eric Wednesday, 02 Apr, 2008 Posted at 03:25AM

Actually… I didn’t realize the example for “returning” shows both. That is strange.

I do feel that the version I posted feels a bit more “Ruby” than the other… but I suppose that’s just a matter of personal taste.

Ryan Wednesday, 02 Apr, 2008 Posted at 04:02AM

Yes, I’ll have to agree with you, your version does feel a bit more Ruby-ish. I’ve taken both approaches in the past, and don’t really have a reason for choosing “user =” over “do |user|” in this particular case (or any case, really). The first time I learned about returning, I believe I took the “user =” approach, and I guess old habits are hard to break :-)

I’ll update the example to reflect your suggestion.

Do you have something to say about this post?
Retype the image to the right Spam Hint: Are You Human? Textile Formatting Tips

or

Ryan Heath | Site Management A Ruby on Rails production.

This site is a Formed Function. Formed Function LLC | @formedfunction | Get in Touch