Awesome article, but be careful of tying your JavaScript applications (SPI, in the essay's parlance) too tightly to specific URLs and HTTP requests, as demonstrated in his Roweis example:
Raganwald explains that moving to "#institutions/42" will make 2 GET requests, one for the institution, and one for the M&E list.
But there's no real reason to cargo-cult a traditional Railsish-request-response-webpage interface onto an entirely client-side application. Now, besides the fact that making 2 HTTP requests for a single institution is less than ideal, what happens if you want to load a handful of institutions in the background, without changing the URL? What happens if you'd like to not repeat the institution request if the data has already been loaded once?
Compare this to the equivalent with full-blown models, using something like Backbone.js:
// Load the initial data.
Institutions.fetch();
// Only load the data if it's not already present.
if (Institutions.isEmpty()) Institutions.fetch();
Being able to work with model data in sophisticated ways is the heart of JavaScript applications -- if you omit models from a JS app, it might feel like a simplification at the beginning, but as soon as you want to perform an interesting computation, optimization, or rendering trick, you'll start to regret it.
Exactly why I advocate PVC for anything beyond aping a web app. I wouldn't say there's _no_ reason to ape a web interface, but I hope I pointed out the drawbacks. I think we're in violent agreement. FWIW, I think you'll see backbone integration with Roweis, but it'll be easy to transition from (¬M)VC to PVC. We're deliberately trying to make Roweis easy to migrate, so having written the above, you ought to be able to switch to a proxy with ease.
Now for your points. You say that making two HTTP requests is less than ideal. Well, that's exactly the point of decoupling the RESTful server and the application. If you control both, of course you can create a single RESTful call that delivers both sets of data. In which case both PVC and (¬M)VC can make one request instead of two.
Caching is as an example of the strength of PVC. I'd also add things like long polling. Let's say we poll for updates to an institution. A change to its name ought to be reflected in a list of institutions along with any page or pages showing the details of the institution, plus any other entity that refers to the institution by name.
A model or proxy for a model resource can handle long polling and all of the appropriate views can listen to it for changes so they can update themselves accordingly. (¬M)VC cannot handle that case at all.
Violent agreement, indeed. Can you talk a little about the nature of the application that you're extracting Roweis from? Is there something about it that makes it especially well suited to the (¬M)VC style?
This is a client project, and the client has professed a strong desire to build additional applications working with the domain data, and possibly even to migrate the UI portion of whatever we build to a different web application platform that plays nicely with their existing management tool chain.
This suggested building a simple RESTful domain logic server that will support the development of independent applications, and a separate application server that can be deprecated if need be. The client's IT team are comfortable with Javascript, so we decided to build the application side in Javascript. One choice was node.js, another was to push the UI down into the browser.
As it happens, there is no requirement for more UX than a web application would deliver, so we are essentially delivering the "application server" inside the browser. We can obviously do a lot in the browser that can't be done with an application server, but we want to be 100% sure that they can port the application interface to a web platform if they wish.
Thus, the cargo cult mentality of making a JS app that works just like a web app. We're building it specifically to be understood by a programmer with web development experience.
Our genuine hope is that making it easy to port back to an application server will also make it easy for the client to extend and modify just the way it is. If integration with something like backbone is easy, they might just find themselves adding the kind of functionality you espouse on their own.
Just now seeing this post. I'll jump in and be controversial and say with the right control structures and design, Models are entirely unnecessary. You can perform interesting computations, optimizations, rendering tricks without needing Models at all.
I would argue that MVC will only bury your application in complexity - even with a really great design and code base. Your example has shown just how stateful MVC really is. And statefulness, in my experience at least, introduces complexity - particularly when trying to perform interesting computations, optimizations, or rendering tricks.
(¬M)VC, PVC are both too conservative. I prefer (¬Model)-View-Collection.
I had to read this in a bit of a hurry (on my way out the door) but I would've liked to see an abstract up front in the essay (essentially the last paragraph first).
Also, for doing a JS based SPI, what's the preferred solution for a RESTful domain logic server? Is there a framework out there that simply doesn't contain the concept of a view/template?
But before implementing a 100% pure, view-free server, consider that delivering an HTML view for each resource can be handy for testing and administrative tasks. It's the exact same information one might get from JSON or XML or YAML, but it's still nice sometimes to be able to fire upa standard browser window and do stuff on the server directly.
I think view-free is a bit of a misnomer. Even in sinatra, you could consider JSON as a "view". You can still test that too with browser plugins like "REST client" for firefox or htty on the command-line.
What it forces you do to is make sure your API is very clean, very succinct and exposes all critical portions of the backend.
Really all we're talking about is the model being a REST service instead of a database model.
Not weird, timing is sometimes everything. Sometimes a perfectly good essay is submitted after everyone goes to bed, or they are too busy to read a long item so they don't vote one way or the other. If the post fails to get that crucial push of votes in the first hour, it dies.
The exact same thing resubmitted first thing on a Monday morning gets an entirely different reception. I guess that's just how things go, I hope people don't take this resubmission as spammy behaviour or as trying to steal karma from you :-)
". I guess that's just how things go, I hope people don't take this resubmission as spammy behaviour or as trying to steal karma from you :-)"
Oh, sure!
No, actually I was just surprised the URL dupe-matcher didn't catch it. I see now they have a minor difference, though it indicates how easy it would be for someone to bluff the dupe finder if they wanted to.
Mainly, though, I'm glad there's discussion on your post.
Usually when you submit something that's already been submitted semi-recently, it'll send you to that submission and up vote it automatically. It matches the URL
I'm not sure if theres a timeframe for this - I've seen it on something as long as a few months.
I actual favor this model in many cases. I've always thought that MVC was still too tightly integrated for my tastes.
Why should we treat our internal applications as any different than our interaction with external ones? I realize this is "self-contained" but the same logic applies.
But there's no real reason to cargo-cult a traditional Railsish-request-response-webpage interface onto an entirely client-side application. Now, besides the fact that making 2 HTTP requests for a single institution is less than ideal, what happens if you want to load a handful of institutions in the background, without changing the URL? What happens if you'd like to not repeat the institution request if the data has already been loaded once?
Compare this to the equivalent with full-blown models, using something like Backbone.js:
Being able to work with model data in sophisticated ways is the heart of JavaScript applications -- if you omit models from a JS app, it might feel like a simplification at the beginning, but as soon as you want to perform an interesting computation, optimization, or rendering trick, you'll start to regret it.