Sproutcore and Rails both use the MVC pattern to organize their code bases, so their architecture must be the same right? Well, not quite. There are actually several differences between the Sproutcore MVC pattern and the Rails MVC pattern that trip people up when they're first starting to work in Sproutcore. This post is my attempt to lay out the two patterns so that their differences can be seen and appreciated.
Note: Although I'm using Rails as the example server side pattern, this actually has much more to do with server side MVC VS client side MVC. So just about anything that I say about Rails can be applied to .NET MVC, Django, etc.
I'm going to assume that most of the people reading this article are already familiar with the basic architecture of a Rails application. The following diagram shows (roughly) how a request goes through the Rails stack.
So there are a couple of key things to notice in the way that the request comes through the stack.
First, notice that there is only a single point of entry for the system. All requests are going to come into the system by the browser hitting a route, which the system parses and and does something with. The user might have clicked a button, clicked a link, browsed a certain distance down the page, etc, but the system doesn't know, and it doesn't care. All it knows and cares about is the route which the request comes in with, and then it figures out what to do with it.
Second, notice that there is only a single point of exit for the system. The system takes the route given, collects all the information that it needs, and generates a big blob of something. It could be HTML, JSON, JavaScript, XML, etc but whatever it is, the system's job is to cobble it together, and give that big blob back to the web server. Whatever the request, the response is going to be a blob of something going back to the browser.
Rails and other server side frameworks set up their MVC pattern to work this way because they're trying to deal with the fact that HTTP is a stateless protocol. Unlike the traditional MVC pattern developed in Smalltalk, the application itself (particularly the views) can not really have state. Because of this, there is no true rendering involved on the server. It's just going to receive in a request, and dump out some set of data that is going to get rendered by somebody else.
For most of us who learned MVC from Rails or some other server side framework this is MVC. It's all that we know. But in reality, this is a simplified version of the traditional MVC framework, and when we're no longer constrained by a stateless protocol we can take full advantage of the full pattern. Which is exactly what Sproutcore does with it's MVC.
The Sproutcore MVC framework is close to Martin Fowler's Passive View, but even closer to Cocoa's implementation of MVC. Instead of receiving a route, and generating a blob of something, the system responds to events by modifying the state of the system. Let's look at how that is structured:
In order to make this a bit more concrete, let's look at a specific example as well. Imagine that we're working with some sort of system with a volume control, and let's imagine that the increase volume button is pressed. What would that look like?
Note: In Sproutcore a click is actually a mousedown followed by a mouseup. For simplicity, we're just going to look at the mouseup part, since this is where the actions would really take place.
Notice that the entire system now has state. In the typical server MVC like Rails, the only state that is maintained is in the model layer, and that's through a persistence store like MySQL. This is necessary on the server because you have to rebuild the entire system with each request, but on the client it isn't. Everything is generally kept in memory, and you only have to interact with a persistence store when you can't keep everything in RAM, or when you want to save the system's state.
Also, since you don't have to rebuild the entire system with each request, each layer has a current state in memory, and the job of the system is to propagate the appropriate changes given the action of the user. This allows us to build richer UIs that respond differently when they are in different states much more easily. As such, the system's job is no longer primarily about generating output, maintaining and updating it's state.
When I first started working on the client side the only MVC that I knew was the one from Rails, and I didn't even know that I needed to change the way that I think about MVC in order to get how something like Sproutcore functioned. Hopefully this post has at least pointed you in the right direction. If your looking for more information, I would recommend reading through Cocoa's documentation on it's design patterns (particularly the MVC section), and then look through some larger Sproutcore apps like Tasks, or OtherInbox.
Although some have attempted to bring the server side model of MVC into the client (Backbone.js's controllers for example "provide methods for routing client-side URL fragments, and connecting them to actions and events"), in the long term I think we will be better served if we learn to use the client MVC pattern for our client side apps, and the server MVC pattern for our server apps. It certainly can take some getting used to, but since we have state on our clients I think we should take advantage of it.