Rails 3.0: It's ready
A couple of years in the making, thousands of commits, and hundreds of contributors, Rails 3.0 is finally done. We’re already running a handful of our applications on it and the rest are moving to it shortly.
You’re reading Signal v. Noise, a publication about the web by Basecamp since 1999. Happy !
A couple of years in the making, thousands of commits, and hundreds of contributors, Rails 3.0 is finally done. We’re already running a handful of our applications on it and the rest are moving to it shortly.
What questions do you have for the 37signals programming team? We’ll be recording a programmers’ roundtable podcast soon and we’d like to answer your questions. Please leave your name too (anonymous questions won’t get answered).
Big Think Interview With David Heinemeier Hansson:
Some of the questions asked:
What inspired you to create Rails?
Ruby on Rails lowers the technical expertise necessary to create a web application; is expertise becoming less critical?
How simple can things get in terms of programming?
Do you think any company can dominate the Web the way Microsoft dominated computers circa 1992?
What do you make of Apple’s mandate that all apps for iOS devices be written in specific languages?
There’s a transcript of the interview available and this summary (excerpted below) offers links to specific parts of the video.
Hannson also talked about the highly anticipated release of Rails 3, saying they’re “incredibly close” to unveiling it. And he admitted to us that he feels “let down personally” by Apple’s choice to restrict what programming languages can be used for smart phone apps. It was an “insecure move,” which Hansson finds strange because Apple is “winning on their merits.” It’s another case of absolute power corrupting absolutely, just like with Microsoft in the 90s, even though now Microsoft is “irrelevant” to Hansson.
We’re all to blame.
When we set out to build finger-friendly controls for iOS devices in Basecamp, two major constraints informed our design.
In Basecamp on a PC, when you hover over a to-do, milestone, or file, you’ll see edit and delete controls. But as has been covered here and elsewhere on the web, there’s no way to hover on a touch device. So our solution to this first constraint is to show the controls when you tap instead of when you hover.
The second constraint is that the controls must be finger-friendly. That is, they should be sized such that they’re always big enough to operate with a thumb, but never too big to fit on the screen.
Our first attempt at these controls turned out to be too small when zoomed out…
…and too big when zoomed in.
Continued…We are constantly looking for ways to make our products faster so recently we spent some time optimizing UI graphics in Basecamp. With better support for CSS3 properties in the latest browsers and solid techniques for progressive enhancement, we began by eliminating some graphics altogether. We found that subtle gradients and drop shadows can be completely rendered with CSS properties and many times aren’t missed when viewed with a browser that doesn’t support them — the very definition of progressive enhancement. Using CSS instead of these graphics results in fewer HTTP requests to our servers plus browsers draw native CSS elements much faster than images.
Another approach we’ve used is CSS sprites, a method for combining many graphics into a single image which is then displayed via CSS. For us this technique reduced dozens of HTTP requests into one — a single, cache-friendly image file. For those new to the technique, the stylesheet references the coordinates of the desired graphic inside the image file. But keeping track of coordinates and creating new CSS styles everytime we wanted to use a graphic would have added a lot of code and made maintenance a chore.
We wanted to keep the code as easy to write as the Rails image_tag
method that we used previously. So this:
<%= image_tag ("email.gif"), :class => "email" %>
…became this:
<%= image_sprite :email, :class => "email", :title => "Email" %>
The image_sprite
helper method contains the dimensions and coordinates for each and renders the HTML. Here’s a shortened look at the method:
def image_sprite(image, options = {})
sprites = {
:add_icon => {:w => 16, :h => 16, :x => 0, :y => 0},
:email => {:w => 26, :h => 16, :x => 41, :y => 0},
:print => {:w => 25, :h => 17, :x => 68, :y => 0},
:trash => {:w => 10, :h => 11, :x => 94, :y => 0},
:comments => {:w => 13, :h => 13, :x => 105, :y => 0},
:comments_read => {:w => 13, :h => 13, :x => 120, :y => 0},
:comments_unread => {:w => 13, :h => 13, :x => 135, :y => 0},
:rss => {:w => 14, :h => 14, :x => 150, :y => 0},
:ical => {:w => 14, :h => 16, :x => 166, :y => 0},
:drag => {:w => 11, :h => 11, :x => 360, :y => 0},
:timeclock => {:w => 17, :h => 17, :x => 375, :y => 0},
:timeclock_off => {:w => 17, :h => 17, :x => 392, :y => 0}
}
%(<span class="sprite #{options[:class]}" style="background: url(#{path_to_image('/images/basecamp_sprites.png')}) no-repeat -#{sprites[image][:x]}px -#{sprites[image][:y]}px; width: #{sprites[image][:w]}px; padding-top: #{sprites[image][:h]}px; #{options[:style]}" title="#{options[:title]}">#{options[:title]}</span>)
end
Keeping the image details in a helper method made it easy to convert the existing images to sprites, easy to re-use the sprited images throughout the app, and will really pay off anytime there are changes to the images. Update the sprite image, update the helper, and the change is done everywhere. This improvement has already been rolled out for Basecamp and we hope to streamline our other products using these techniques soon.
Sharding is a database technique where you break up a big database into many smaller ones. Instead of having 1 million customers on a single, big iron machine, you perhaps have 100,000 customers on 10 different, smaller machines.
The general advise on sharding is that you don’t until you have to. It’s similar to Martin Fowler’s First Law of Distributed Object Design: Don’t distribute your objects! Sharding is still relatively hard, has relatively poor tool support, and will definitely complicate your setup.
Now I always knew that the inevitable day would come where we would have no choice. We would simply have to shard because there was no more vertical scaling to be done. But that day seems to get pushed further and further into the future.
Continued…Emil Sundberg asks:
When serving thousands of customers with Basecamp, Highrise etc there must be a lot of advanced features though, how do you document your projects? How easy is it for a newly hired developer to understand how your products work.
The short answer is that we don’t document our projects. At least not in the traditional sense of writing a tome that exists outside of the code base that somebody new to a project would go read. I haven’t ever seen that work consistently and successfully at any software company I’ve been involved with.
Further more, I don’t really find it necessary for the kind of work that we do. Our biggest product, Basecamp, is about 10,000 lines of code. That really isn’t a whole lot in the grand scheme of things. Everything we do is build is also using Ruby on Rails, which means that most Rails programmers would know their way around our applications straight away. It’s the same conventions and patterns used throughout.
We try to do a fairly good job at keeping our test suites current and exhaustive as well. Basecamp has a 1:1.2 ratio of test code (thanks to the persistence of Jamis!), Highrise has a ratio of 1:0.8 (bad me!). So you can change things in the applications and feel fairly comfortable that you at least haven’t killed the entire application if you make a mistake as the tests would catch that.
Finally, we write our application in a wonderfully expressive and succinct programming language like Ruby that leads itself very well to a programming style like the one Kent Beck preaches in Smalltalk Best Practice Patterns. Keep your methods short and expressive. On average, our models have methods just four lines long. Adding documentation to a method should usually only be done when you’re doing something non-obvious that can’t be rewritten in an obvious way.
Writing documentation for your code base is a very heavy, upfront, planning kind of way to go about things. Maybe that’s what you need some times if you work in an environment that’s especially onerous or if you have very complex policies and strategies you’re implementing. But if you’re not burdened with such things, I’d recommend trying to work on the quality of the code itself and see if you can get by with sparring with new developers.
Got a question for us?
Got a question about design, business, marketing, etc? We’re happy to try to provide some insight into how we’d tackle the problem. Just email svn [at] 37signals dot com with the subject “Ask 37signals”. Thanks.