(Looking for DHH’s keynote at RailsConf Europe 2007? Find it here)
I’d been looking forward to David Heinemeier Hanssons (DDH) key note in the same way I’m guessing people looks forward to hearing Bill Gates and Steve Jobs talking at the big Microsoft and Apple conferences. Any community needs its mythical founder amongst whom the community can revolve, and DHH makes a good job of filling that role, backed up by wise men such as the Fowlers and the Pragmatics.
DHH had just returned from a trip to a Ruby conference in Japan, and - still very much jetlagged, as he explained later that evening in the bar - introduced the topic of his key note: CRUD. Create, Read, Update, Delete. An idiom so widespread that they even teach it in my Java-centric school, an abbreviation that lays out the four basic operations of manipulating database tables. DHH explained that he has lately started seeing all his code in the light of CRUD, in fact, he starts to spot “crudness” everywhere – perhaps CRUD can be used as the basic pattern for making beautiful code?
DHH pointed out the similarities between CRUD, database operations, Rails actions and – last but not least – the http methods:
- Read,
SELECT,findandGET - Create,
INSERT,createandPOST - Update,
UPDATE,updateandPUT - Delete,
DELETE,destroyandDELETE
When you browse to a url like GET /people/show/1, you are basically repeating yourself: show is redundant, because the http method sent by the browser has already specified that you want to do a GET. So the beautiful version of the url would be GET /people/1, just as PUT /people/1 is more beautiful than POST /people/update/1.
The problem is, however, that even though the http protocol specifies all of the mentioned methods, only GET and POST has achieved wide spread use, and thus, specifying PUT or DELETE as the method on a form tag won’t work as intended, since browsers just ignores it and defaults to GET, and if even if it is capable of passing the method on, many web servers and proxies sees the use of methods like PUT and DELETE as unsafe and rejects them. No problem, DHH said, we’ll just fake it in Rails using a hidden field to specify PUT and DELETE methods. This should raise some alarm bells, he continued, and it certainly did with me. By using a hidden field I get ugly flashbacks (well, wish they were flashbacks, I’m still doing loads of .NET) to the heavy use of hidden fields in .NET which result in 500 KB pages - excluding images – so asked, at the Rails Core Q&A session, if this wasn’t a slippery slope taking Rails in a wrong direction?
No, DHH answered without hesitating, we’ve done plenty of things that could be a slippery slope before. It’s a hack, and we might be able to take it away eventually, but right now it’s the way to go. I guess I’ll just have to try it out, since the Simply Restful plugin, which promotes this kind of urls, will be implemented in Rails 1.2, according to the Rails Core team (and they should know it).
Tightly connected to the point about restful urls, is DHH’s newly found desire to promote controllers that only do the four CRUD operations. Basically, he argues, if you have more than the default actions in a controller; index, show, list, new, create, edit, update and delete, you haven’t thought enough how to structure your controllers and actions. If have “scoped” actions like add_user or post_comment, you haven’t “crudified” your application, and you should move those actions to a UserController or a PostController.
As I discussed later with Victoria, many of the brilliant people at RailsConf are self taught college drop outs doing cool projects their own way, instead of worrying about learning the “right way” at school. But with this “crudness” or “crudiness” DHH wants the controllers to respect, I actually think he is trying to phrase a concept both of us learned about, while getting our bachelor’s degree in Business Administration and Computer Science at the Copenhagen Business School: Normal form. Normal form is known concept throughout logic, language and mathematics theory, but from my education, I know it from database theory. It’s all about optimizing your database by normalizing your tables into a certain normal form, and I’d guess that’s what DHH wants us to do: To normalize our controllers.
I realize DHH is not too interested in databases – during the Rails core team Q&A he said in fact: “I don’t like databases. I pretty much use them as hashes.” – but I like the analogy, and I propose we start talking about normalization in this context, because really, normalization is just another word for beauty. However, beauty is a bit unspecific and it’s widely used to describe anything good in Rails, so why not instead say: I’ve normalized my controllers and action to the CRUD normal form. There are in fact things we can learn from traditional school paradigms such as relational algebra or object oriented design, or maybe it’s just general programming wisdom which has some how snuck into education, and one of those things is this: “If you think about it a bit harder, a simpler approach will appear.” (DHH). You do this when you normalize databases. You do this when draw UML diagrams. And now you should do it when you normalize controllers – think simpler, think CRUD!
But: CRUD is not a goal in itself, it’s an aspiration, a design technique, DHH emphasized, and normalizing (“crudding”) won’t be the answer to everything. Basically though, you can normalize anything, and DHH gave examples with the state of case having its own model and its own controller – this way, the CaseController was normalized, and didn’t have to had any add_state actions or something like that – instead, these actions was implemented in the StateController through the standard CRUD actions. At first, DHH explained at the Rails Core Q&A, he thought login was an example of actions that couldn’t be normalized, but Jamis Buck had the solution for this, implementing CRUD actions on a SessionController, since that’s basically what a login does; adding and removing stuff in the session.
Enough with the theory. The big revelation of the key note was a new API DHH started hacking away at two days before the key note; Active Resource. The API is basically all about describing things as resources, and as I understand it after discussing it with Geoffry Grosenbach and Chris McGrath, it’s basically an alternative to Action Webservice based on the REST concept. Since it’s still work in progress, I’m not really sure it’s going to work at all, but it seems like it will usable for both providing an API as well as consuming it. I guess DHH don’t want to repeat the work on the Basecamp API now that he is doing Sunrise, but also, he wants to emphasize that almost anything can be viewed as a resource. Active Resource will be released as a small, compact plugin as part of Rails 1.2.0, and basically, it sounds like that release will very much focus on the REST principles, and on making the Rails core smaller by pulling thing out in plugins.
The example DHH gave on using Active Resource was based on his notion on viewing XML basically as a hash. So perhaps your code would look like this:
Person = ActiveResource::Struct.new do |p| p.uri “http://www.example.com/people” p.credentials :name => “dhh”, :password => “secret” end matz = Person.find(1)
- and Active Resource will automatically wrap the XML response, which could look like this:
<person> <name>Matz</name> </person>
For now, we’ll just have to wait and see what turns up in Edge Rails and try it out.
Jaikus