Posts Tagged ‘Ruby’

Is Your Code Clever or Maintainable?

December 20th, 2011 - 5 Comments »

A few months ago, I found the following line of code in a CSS file:

div.updated { <%= 'color: #800;' if DB.execute("SELECT id FROM sessions WHERE session_key=? LIMIT 1", params[:session_key]) %> }

I expect most web developers with Ruby experience will be able to understand the code, and other developers should be able to sort it out without too much trouble.

That said:

  • Did you have to read that line of code more than once?
  • Did you have a moment of distraction (e.g.: closing your eyes, looking out a window)?
  • Did you glaze over everything after the if DB.execute bit?

I’ll bet that all of you did at least one of those things, possibly all of those things, the first time you read this post. I know I had at least one mental hiccup when I discovered that little gem (and some architectural rage, but that’s a post for another time).

Our working memories have a fairly well defined boundaries: We can track three seconds worth of data, or seven similar elements (depending on who you talk to). We have trouble maintaining integrity in our working memory when we switch between topics. We also have a subconscious reflex to distract ourselves (that is, a preemptive context switch) when faced with complexity that overloads our working memory.

These are basic human limitations. Some of us may have extraordinary talents that push these boundaries, but even so, the simplest software is complex enough to overwhelm our basic mental processes.

Fortunately, we humans are exceedingly good at building abstract mental models to represent complex concepts and patterns. One measure of software maintainability is how easy it is for other developers to learn and reconstruct those underlaying abstractions. In other words, how easy will it be to figure out what your code does?

Given our universal constraints, and the goal of making code easy to digest, lets look at that snippet again and see what we can do about it.

div.updated { <%= 'color: #800;' if DB.execute("SELECT id FROM sessions WHERE session_key=? LIMIT 1", params[:session_key]) %> }

The purpose of this code is both plausible and easy to comprehend: updated content on a web page is colored red when someone has an active session. Unfortunately, a developer seeing this code for the first time needs to understand 15 different concepts in 5 contexts on 1 line of code:

  • The general CSS structure of the web site: we’re working with the updated class of the div tag.
  • The template environment: we’re working in ERB and inserting the result of a statement into the document.
  • The Ruby language and application server environment: the behavior of the if conditional, the scope of the DB.execute object and method, and the params object and :session_key symbol.
  • The database connector’s binding style: the replacement of the ? placeholder, and the result of the query.
  • The SQL and database structure: the relevence of the id and session_key columns in the sessions table.

Ouch. There are clearly too many interdependent pieces to fit in your head in one shot — however, all of the dependencies must be satisfied for the code to work, so we don’t have an opportunity to remove anything.

The first step towards easier comprehension is to break out of a single line of code. For better or worse, most of us think of a line of code as a discrete concept — like a sentence, or a simple action.

Even if we don’t change the content of the code, we can make it considerably more readable by breaking it out into a few lines:

<% if DB.execute("SELECT id FROM sessions WHERE session_key=? LIMIT 1", params[:session_key]) %>
  div.updated { color: #800; }
<% end %>

Although the quantity of code has increased, it has been significantly simplified on a line-by-line basis, reducing our contextual overhead:

  • The first line is still cumbersome, but at least it is limited to a single conditional statement containing Ruby, ERB, and SQL. As a conditional statement, it creates a simple context: we know we have an active session if we’re inside of the block.
  • The second line is just CSS.
  • The third line closes the conditional block.

That first line is still a bit problematic, though. What if we did something like this?

/* CSS File */
<% if active_session_id() %>
  div.updated { color: #800; }
<% end %>
# Ruby file
def active_session_id()
  DB.execute("SELECT id FROM sessions WHERE session_key=? LIMIT 1", params[:session_key])
end

We’re still adding code, but we’re also adding clarity:

  • We’ve separated our primary concerns into independent pieces of code: first, determining when to change the style; second, how to detect whether we have an active session.
  • In the first part, we have a simple conditional statement, followed by the simple CSS, then the block closure. We are still exposed to the conditional statement in Ruby, but shielded from the mechanics of how the decision is made.
  • In the second part, we’ve define a method that checks the database. The context is our Ruby environment: even if it’s a stand-alone Ruby file, we are free and clear of any concern about ERB, HTML, or CSS. It’s also possible to reuse this code in other places.

We’re at a pretty good spot: a first encounter with this code is less likely to cause those mental hiccups we hit the first time around. Is there a better way to accomplish the same task? Is this a fairly trivial example? Undoubtedly yes, and well worth discussing some other time.

So, how did we get to that single line of code in the first place?

Lets revisit, for the fun of it:

div.updated { <%= 'color: #800;' if DB.execute("SELECT id FROM sessions WHERE session_key=? LIMIT 1", params[:session_key]) %> }

I bet you were able to read that in a single pass, right? No distraction, you just powered through it — because you already understand it. We’ve worked through the code in three different forms, and now we “get it.” I’ll bet a few of you have an inclination to see if you can tighten it up a little … and therein lays the problem.

We rightly value concise answers, and find a lot of pleasure in simplifying complex systems. Unfortunately, we have a difficult time distinguishing between brevity and clarity when we’re already intimately familiar with a section of code.

How do we determine if source code is clear, when we are thoroughly acquainted with it?

Here’s a stab at figuring it out, from an objective perspective …

For each line of code, score a point for each:

  • Language you use
  • Conditional statement you introduce
  • Data structure you are dependent on, or change
  • Change of scope

If have more than three or four points for a line of code, consider breaking it up into multiple lines, or refactoring the task into smaller pieces.

This clearly isn’t something that you can do for every line of code, but a little practice can help you develop a healthy reflex for judging whether your code is “cleverly complex” or actually maintainable.

I’m thinking about writing more on maintainable software, addressing topics like languages, documentation, and releases. I’d love to hear what’s most interesting to you. Leave a comment and tell me what you think!

EC2 + OpenSolaris + Rails

August 30th, 2008 - Comment »

For the last couple of months I’ve spent a little time each week with the OpenSolaris team at Sun, putting together an Amazon EC2 image that makes it easy to deploy and experiment with Ruby on Rails.

They released the AMI last Friday, but I’ve been too crazy busy to make an announcement. Here’s the official word, and here’s my take on it …

My goal with this project was to help people get a Rails app running as quickly as possible. We set up this AMI so that you can get your hands dirty with Rails if you don’t want to spend the time installing everything on your home system or server, and it’s an inexpensive and easy introduction to OpenSolaris if you’re curious.

All the requisite goodies are pre-installed: Rails 2.1, Mongrel, PostgreSQL and MySQL, Subversion, Git, Capistrano, and a few others choice gems. You also get DTrace built into Ruby, if you’re keen on that sort of thing.

There’s also a sample Rails app in your home directory, and a pre-configured SMF file that serves as a handy introduction to the very handy Service Management Framework — the OpenSolaris system for managing daemons and other server processes.

Working with the OpenSolaris AMI team was a lot of fun, and in particular I’d like to give a thanks to Prashant who did most of the hard work getting everything set up.

FOSCON III – Tonight!

July 24th, 2007 - Comment »

Get your nerd on!

FOSCON III is upon us — tonight at 7:30 at Holocene.  Prepare yourself for free pizza, lighting talks, and hob-knobbing with Ruby geeks from around the world.

Check out the Upcoming page for more information, including a map and how to hitch a ride from OSCON.

FOSCON III

July 9th, 2007 - 3 Comments »

It’s that time of year again!

O’Reilly’s Open Source Convention (OSCON) is coming to Portland, and the Portland Ruby Group is putting on FOSCON, a free event where geeks of all stripes can meet, greet, and get their nerd on. The last two years were standing room only (don’t tell the fire marshal), so we’re movin’ on up to a larger venue!

If you’re coming to OSCON, register today for FOSCON III — it’s free!

http://upcoming.yahoo.com/event/216872

PS: If your business is interested in a little attention from an international crowd of alpha-geeks and decision makers, we’d love to talk with you about sponsorship for food, drinks, and other goodies.

Dependency Injection ala Ruby

April 3rd, 2007 - Comment »

Back in the days when I was a Java developer, there was a really hot meme called “dependency injection” (also known in some circles as “inversion of control”). The hype was oriented around the Spring framework, which promised to be the next hotness for developing web apps (amongst other things). It’s still around, and doing quite well, but I was seduced by Ruby on Rails before I could really sink my teeth into Spring.

Why am I rambling about this now? Last night when I was trying to fall asleep, Spring floated through my head and I wondered if there was a similar framework for Ruby. Lo and behold, it turns out Jamis Buck constructed a container back in the days before Rails became the web’s darling framework.

It’s called Copland, and this one example is enough to make me keep thinking about it …