Code like a hobo
For the last 2 months, I’ve been using a new Ruby framework at work. A very… interesting framework :) It looked very promising in the beginning, only to become a complete disaster a few weeks later. I thought I could share some of my experiences with it here, although not to recommend it, but rather to warn you not to use it…
Its name is Hobo, which makes most people think of homeless people, and makes it a constant object of jokes in my company (see below :)…
A sign hanging in my room - copyright by Wombat It’s not really technically a framework - it’s a set of gems that act as an add-on to Rails; but its complexity makes it almost a small framework. Why would you want to add another layer on top of Rails? To gain development speed - “rapid development” is its main goal (“rapid” is also a name of its part that deals with javascript and UI in general). And I must admit, it might indeed be a great tool for such situations when you need something simple, crude, and need it for yesterday. Something to be thrown away later. This introduction shows how to make a simple webapp with one model and controller in 2 minutes, probably less (!). A standard 15-minute blog example could probably be done in 5 minutes. And this includes such things as authentication, registration, permission checking, even password resetting. This is an awesome speed boost if you just need to show a prototype to a client quickly.
Details
So, what does it do exactly? It does several different things:
Smart (in a way) permission checking; all you need to do is define a few methods in each model class - creatable_by?, updatable_by? and so forth - which tell if a given user can perform a given action on the object, and that’s basically the only place where you need to be concerned about permissions - Hobo infers lots of information from these methods and uses them everywhere. Auto-generated migrations; fields are defined inside the model (like in DataMapper) in a fields do ... end block, and it generates migrations automatically for you, detecting which columns or tables were added, removed, or changed since the last migration. You can update the migrations manually before you run them. Automatic controller actions. This is how a default controller looks like: @css(brush: ruby) class FilesController < ApplicationController hobo_model_controller auto_actions :all end And it’s fully functional - the auto_actions command tells it to use the methods in Hobo::ModelController class, which do such stuff as fetching necessary objects, checking permissions, validating records, saving, redirecting and printing default flash messages. If you need some extra functionality (and you usually do, though not always), you can call the methods in such a way that you only add your extra lines and the rest happens as before. Automatic routing - all standard routes are auto-generated based on controller actions, you don’t need to touch the routes.rb file unless you need something non-standard. A new template language, DRYML (DRY Markup Language). It consists of XML-like tags, which internally work like Rails helpers; you can (or rather should) define your own tags in files called taglibs, and there are literally hundreds of tags in Hobo’s taglibs. Also, the more advanced sets of tags are intended to let you write pretty complicated things, like AJAX-ified fields and forms, using just one or two tags - this is what the “rapid” part is about.
Why it won’t work
Looks awesome, doesn’t it? Yeah, that’s what I thought too. So where’s the catch? There are two.
The first is that although it would seem that Hobo makes development much much faster, it really doesn’t. It has a steep learning curve and you need to spend a lot of time to just get started, if you plan to write anything more complex than a default scaffold interface. After a week and a half, the only thing that I’ve managed to write was redesigned registration process… And although it gets better, even after a few weeks you still spend a lot of time digging deep into Hobo code, trying to find out how to use a controller action in a specific way, which one of the hundreds of tags you should use and how, or why the hell does it throw that exception when it shouldn’t (and the reason is often that it’s just a bug or that this is one of the 10% cases when the Hobo magic doesn’t work).
And I’ve left the best for the end… It’s SLOW. Really f***ing SLOOOOOOOOOW. In the development mode, it takes between 2 and 5 seconds to load a page. I thought it was just because it had to parse the DRYML tags each time, and that in production it would be fine. It wasn’t. Sometimes it takes as little as 30 ms, and sometimes you get something like this:
Completed in 1.01311 (0 reqs/sec) | Rendering: 0.96372 (95%) | DB: 0.02360 (2%) | 200 OK
That’s 0 (zero) requests per second… in a normal index action that just lists objects. That’s exactly ∞ times slower than a normal Rails application ;) (I know, it’s just rounding, but it looks funny. or terrifying, depending on how you look at it…). This also means that if your users send a request to the server every 10 seconds, you need a separate machine for every 10 users… o_O
It took me a few weeks to realize that Hobo is just designed in such a way that it can’t run fast. It’s not a matter of implementation which can be optimized, it’s a matter of starting with wrong ideas at the beginning. Like the idea that you can define permissions in methods in a model, and then call these methods a lot of times for every single object that you want to display. Hobo does a lot of things for you, it’s really smart, it can determine thousands of details by itself without your help; but because it needs to check those thousands of details in every request, it must be slow, and will always be slow…
So, the bottom line is: even if you thought this was cool at the beginning, don’t use it. Seriously. Unless you want to end up as a hobo and eat hobo soup… ;)
Discussion in the ATmosphere