Sunday, May 6, 2007

404 Should Be method_missing

The number one post on this blog returned by googling my own name is a post where I explain how my favorite bit of Ruby I ever wrote made my Rails controller emulate method_missing. A prominent blogger has privately described to me an amazing bit of code where he emulated method_missing in Java. I think method_missing may be the single best thing about Ruby, and you have to wonder why, when building Web apps, people don't say to themselves, "Look, we should never return a 404 error page. We should catch any 404 and implement it with some equivalent to method_missing."

Really gotta wonder about that.

4 comments:

  1. 99% of the time though, the correct behavior of method_missing is to throw an exception. That's what a 404 really is. You sent an object (/articles/1) a message (GET) and an exception is raised.

    Perhaps there should be a distinction between a null object and a message an object doesn't understand. In my example above, the 404 could mean either that the object doesn't exist, or it does exist but doesn't implement that particular message.

    Actually I just looked up the HTTP status codes and it looks like 405 would be the appropriate response if an object doesn't implement a particular method.

    Okay after doing some more thinking I just don't follow you. There are a number of HTTP status codes that are used to convey information to the client. 404 means that they made a request to an object that didn't exist. Why wouldn't you want to use that?

    p.s. I hate your captcha. I never get it on the first try.

    ReplyDelete
  2. Well, Blogger sucks, it's true, but hey, it's free.

    Anyhoo - when you're linking to something, it can be an API, it can be an Active Resource, it can also be just some random article. In a blogging site, it can be both. This means your user could be a program or a human. You get an invalid request of some kind, it automatically goes to the server equivalent of method_missing, which analyzes the user agent. Bots and WS clients get error codes, humans get an apology page with autoloaded results of a search based on their invalid request.

    The problem with the Active Resource model, a URL is a message passed to an object, is that the message-passing mechanism is exposed. This breaks encapsulation. So if your goal is to build whole interconnected systems of Active Resource "objects" on the Web, that system's going to be way more fragile than would be ideal. Objects can never really pass messages internally because there is no protection. The message-passing mechanism doesn't have the ability to bury things several layers deep. At any moment a call to an object calling an object calling an object can in fact just be some user typing a string. And that user can be friendly, or malicious; they can be smart or dumb.

    This means that Active Resource, for all its ambition to turn the Web into a gigantor-fied Smalltalk virtual machine, really makes it much more like object-oriented Perl. Now very few people still love Perl, but I'm one of them; even so, though, Perl's OO paradigm isn't ideal, and it isn't the greatest thing about Perl. In fact it's very far from the greatest thing about Perl, and it's very far from ideal. I'm not talking binoculars far. This is like Hubble telescope far. An OO paradigm without any ability to enforce encapsulation at all doesn't really give rise to incredible code.

    Anyway, I hope I answered your question. I definitely answered the big question on my mind, which had been, what am I going to say at OSCON that I haven't said already? That's it right there. Active Resource could have totally bitten off more than it could chew, and duplicated OO Perl where it intended to duplicate Smalltalk.

    ReplyDelete
  3. Bots and WS clients get error codes, humans get an apology page with autoloaded results of a search based on their invalid request.

    Okay, so I guess you just want 404 pages to be more helpful. Conceptually those two responses are the same though.

    The problem with the Active Resource model, a URL is a message passed to an object, is that the message-passing mechanism is exposed.

    Actually, exposing the message-passing mechanism is precisely what makes the ARes model work in the first place.

    The web model doesn't break encapsulation, it inverts it. When we talk about encapsulation, we usually mean that we expose an API and don't let anyone directly modify data. What happens when we approach it from the opposite end? Expose data to clients, but don't let them directly modify the API. All of a sudden we have a model that works beautifully on the web. When a browser sends a message to an object, it'll get the response which may contain links to a bunch of other objects. And the browser knows how it can communicate with those objects already, instead of getting an object with a shitload of possible messages (that the browser, bless its heart, doesn't understand). Then it becomes a matter of who you know rather than what you know. Any object can implement the limited, fixed API however it wants, and then becomes even more useful by letting the client know of other objects that may be of use.

    Rich APIs can be awesome when you've got a rich client. When you can't control or extend the client though, life becomes easier when you restrict the API and expose the data. Objects end up being small and very focused. Often they're not useful on their own. But they can link you to other objects, and in the end you have a network of objects forming a very powerful system.

    ReplyDelete
  4. Then it becomes a matter of who you know rather than what you know.

    That in and of itself does not sound so good.

    Objects end up being small and very focused. Often they're not useful on their own. But they can link you to other objects, and in the end you have a network of objects forming a very powerful system.

    OK. On the one hand, you have this tradition of clunky RPC attempts that fail, and you have huge XML object-transfer methods, and then over here you have JSON, which just works, and Web mashups, which can be great. So obviously what you have on the Web is this sort of loose coupling thing, and loose coupling is a good thing.

    So far so good. But it places a ceiling on the complexity of things like mashups, and while many mashups are useful, the average mashup is a trivial waste of time that only entertains other programmers. You look at something like Basecamp, widgets exist for updating Basecamp without a browser, that's great, in that case loose coupling and lightweight protocols give you tons of tiny things that all do one job well.

    Put it a few years down the line, though. At some point, browsers may become fast enough that JavaScript will give you C-like performance. At that point you want to be able to do something more complex. We'll have to build on top of the whole URL thing, and we won't find it an ideal foundation. Imagine when it's time for the next generation of apps, and we're building genuinely complex systems on top of an OO model like Active Resource. It'll be like building Smalltalk out of Perl. Try doing that without going insane. It's easy to say we'll tackle that problem when we get to it, but if you see it coming, you might as well plan for it.

    Okay, so I guess you just want 404 pages to be more helpful. Conceptually those two responses are the same though.

    No no no. You don't understand at all. method_missing is a tool for programmers. The 99% use case for method_missing might be throwing an exception, but the huge selling point for method_missing is Rails. Why is method_missing a good idea? Why should I bother to include method_missing when I'm building a new language? Because of Rails.

    The point isn't just that exception handling in a Web app should be invisible to users. The point is that if you build a method_missing into a server, some next DHH will come along and build something useful with it.

    ReplyDelete

Note: Only a member of this blog may post a comment.