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:
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 inHobo::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… ;)
6 comments:
Radarek
Nice write-up. I can only say (probably very obvious thing) that building another layer on top of rails is stupid idea.
omar
I found Hobo last week and I am following the path you did. I believe the docs are much better than last year but what raised a concern on me was the speed. I hoped it would get better in production but as you said it wont.
My question is what are your feelings about the dryml tag library as standalone product that can be use with Rails alone (not now, but soon as hobo website says).
I believe there is some repetition on views in standard Rails. I am looking for a better alternative in that department. Any suggestions?
Thanks for your advice I will not lost as much time as you did
Kuba
Honestly? Just use the standard tools that Rails gives you - ERB, partials, layouts, content_for, helpers, block helpers, and so on. Learn to use that well, learn all the best practices - and you're going to have much clearer code that if you used DRYML. Also, any new Rails programmer that joins your project will understand everything immediately.
I spent about 5 months working with DRYML and I never got to a point when it would be clearer or easier to read than the classic way... I hated it when I went to one file, saw a tag and then had to think long and search through several different files to find which ones are extending that tag - I had to keep several templates loaded into my brain simultaneously in order to understand what was going on.
Also, check out presenter pattern (Viewtastic, ActivePresenter plugins) and Rails Cells plugin for other ideas how to clean up your view layer without changing everything.
bronson
Heh, I'm a Hobo refugee too. Someone should start a support group.
I quite liked 0.6.2 (except for dryml -- markup is ugly enough without trying to make it executable!), I was uneasy about the 0.7 series, and absolutely loathed 0.8. ViewHints? taglibs/auto/rapid? Such horrible, horrible design decisions. And you're not kidding about page render time -- it was seriously slow in 0.6, and got much worse with each subsequent release.
I finally finished eradicating Hobo from my app in October 2009. What a bright and clean feeling that final checkin was!
There's only one feature I really from Hobo -- declaring fields in the models and letting the computer write the migrations. I've been playing with extracting that into a simple, dependency-free gem: http://github.com/bronson/rich_models I'm using it successfully in my own projects but it will take a lot more cleanup effort to bring it to a releasable state.
Anyhow, congrats on seeing the light. :)
Kuba
Yeah, I liked the idea of hobofields too... Another option is switching to DataMapper, which also defines all properties inside model files.
Colin
FYI - Hobo just released a gem called "hobo_fields" which let's you declare fields in your models and auto-generate your migrations, but you get to leave the rest of hobo *out* of your app:
http://cookbook.hobocentral.net/manual/hobo_fields
I really wish I knew about this before my latest app which is complicated enough that my development mode page loads are ~10-20 seconds, I'm screwed.