30-second Tutorial on Models

To Create a New Model

In your terminal:


cd project-name
sc-gen model contacts/contact

This creates:

 

  • The model file in clients/contacts/models/contact.js
  • The unit test in clients/contacts/tests/models/contact.js
  • A fixtures file in clients/contacts/fixtures/contact.js

 

To Create Some Models

The attributes you get from the server should be simple JSON hashes.  They must have at least two properties:

 

  • type: A string identifying the model type.  By default, use the class name.  In this case “Contact”.
  • guid: A unique identifier.  This will be used to auto-merge/update records in the future.

Here is an example of some JSON data:


var records = [
  { type: "Contact", firstName: "Charles", lastName: "Jolley", guid: "contact-1", favoriteNumber: "3" }
];

 

All models are kept in an in-memory database called the Store.  To add records to the Store, you just get these data hashes from your server in whatever way you like and add them to the store like so:

SC.Store.updateRecords(records);

records should be an array of one or more data hashes.  Note that you can call this method as often as you need.  If you pass in data hashes with a type/guid matching an existing record, then the hash will simply update the record.  Otherwise, one new record instance will be found for each item.

If you want to try the following examples without having to create a new app, you can simply add some sample records to the fixtures file created in Step 1 above.  These fixtures will be auto-loaded into the Store on app load.

To Get Records

In your app, you can retrieve some records from the store using finder functions.  This call will find all the contacts in the store (this does not contact your server, it just uses whatever is in the local datastore.  You should load your records into the store first.):

var recs = Contacts.Contact.findAll();

To Edit Records

Just set and get properties on them.  If the properties are string type, you don’t even need to declare them:


var rec = Contacts.Contact.findAll()[0];
rec.set(’firstName’, ‘Joe’); // changes the firstName to Joe.

If you have a property that is not a string but some other type, you can add a line to the Contact class declaring the type:


Contacts.Contact = SC.Record.extend({
  favoriteNumberType: Number
});

Now when you get/set the favoriteNumber property, the Contact record will automatically convert it to/from a number.  This works for dates and can even work for other model objects, but that is for another tutorial.

To Save Records

You can get back out the attributes hash of a record by getting the attributes property:


var rec = Contacts.Contact.findAll().first();
var attrs = rec.get('attributes');

This will be a JSON-compliant hash that you can serialize and send back to your server in your favorite way.

Conclusion

That’s it for part 1.  There is a lot more you can do with the model layer.  As usual, the in-source docs are best and can be views on the doc viewer page.

 

Downtime

Well that was fun.  SproutCore made it on Digg today, which was cool.  But it brought down my cheap-o dreamhost shared server that I was using as a placeholder until we launched.  We are now up on the Sproutit-sponsored VDS we had planned from the beginning and everything should be available again.

Sorry for the offline!

Understanding the IE DOM

Many developers I know don’t like working with IE because it is so “incompatible” with Firefox and Safari.  This is true, but what most people don’t know is that 90% of IE’s problems are actually isolated to just one part of it’s JavaScript implementation and if you work with that one part correctly, you can largely avoid the potholes that make cross-browser such a pain.

A Tail of Two Doms

The DOM is the in-memory representation of an HTML document.  Most people know the DOM from its familiar JavaScript API like insertBefore(), removeChild(), cloneNode() and so on.  But actually, the DOM is much more than that.  Whenever a web browser reads in an HTML document, it builds an in-memory representation of that document — a graph of objects called the “Document Object Tree”, but which people usually refer to as the “DOM”*.

Now the real DOM used by wedding browsers is not really JavaScript; it’s native code, written in C++.  This makes the browser very fast and parsing and displaying HTML but it presents a problem for the JavaScript.  How do JavaScript scripts get access to the objects in the DOM?  It turns out that IE and FireFox/Safari/Opera diverge significantly on this point and it is the single biggest cause of browser incompatibilities that I know.

The Peer Model

Intentional or not, both Webkit and Firefox as I understand handle this problem in a similar way.**  They create, in effect, a parallel tree of semi-pure JavaScript objects that match exactly the C++ DOM objects used to render and display the page.  The figure below shows how this works. (Using my handy Skitch whiteboard…)

(Interesting aside, btw, most browsers actually have a third parallel tree of peer objects called Display Tree or something like that.  This is a set of native objects written in C++ that actually handle drawing the DOM objects in your window.  A web page is really much more sophisticated than it looks!)

It turns out that the peer model for JavaScript is actually a very nice one because the DOM objects you see when you write JavaScript are real JavaScript objects.  They have prototypes, inherit methods, throw exceptions, and can even have their properties overridden.  This makes it easy to do nifty tricks like enhancing the root HTMLElement class to add the $() method like jQuery and Prototype do.  It also means that DOM objects tend to have largely the same behavior as other objects so you can reliably predict how they will behave in most situations.

The Wrapper Model

IE, on the other hand, takes a much different approach to exposing the DOM in JavaScript.  DOM objects in IE are essentially “wrapped” by a thin veneer in the JScript engine that makes it possible for you to query and set properties and call methods on these native C++ objects through script.  The figure below shows the difference with this model.

Now, actually, wrapping the DOM elements like this in IE does have its advantages.  In some ways you are much closer to the metal of the browser so to speak and therefore able to exert a bit more control.  The dreaded hasLayout property for example exposes some good internal information about how IE will treat the rendering of an element that would be useful in other browsers when trying to deal with complex layouts.  (The programming by side-effects model required to manipulate this property, of course, is another matter.)

On the downside, however, wrapping DOM elements makes IE subject to the effect of leaky abstractions.  Since DOM objects are not real JavaScript elements, sometimes they don’t behave just like you expect.  In fact, if you’ve ever hit one of these doozies, you’ve been bitten by the DOM-Wrapper IE bug:

 

  • You set a property on a DOM object and that property mysteriously changes to some other value; even if it is not part of the DOM’s published API.
  • You tried to modify the prototype of the DOM element (i.e. HTMLElement) and discover it doesn’t show up on existing DOM objects.
  • You added a method to the Function prototype, yet certain functions on DOM objects seem not to have them.
  • You try to iterate through the key/value pairs on a DOM element and certain keys you expect to see are not included (actually this one can happen in FF at times because of their own leaky-abstractions.)
  • You store a JS objects in some property on a DOM element and now it leaks when you leave the page. Yep, the dreaded IE memory leaks are caused by wrapping behavior in IE.

 

The list goes on and on.  Weird, seemingly unexplainable behavior suddenly makes sense when you realize the object you are working with is not JavaScript, even though it pretends to be so; it is a native C++ object only posing as one instead.

How to Program IE with Less Pain and More Joy

The models used by Firefox/Webkit and IE are plainly very different when it comes to the DOM.  How can we use this power to our advantage?  The answer is quite simple:  treat all DOM objects like foreign objects.  Forget that they are JavaScript in Firefox and Safari.  Don’t add properties or methods to DOM elements.  Don’t fiddle with their prototype definitions.  Only work with their published APIs.

Use the best practice followed by the browsers and create a peer tree of pure JavaScript objects that can mange your DOM elements for you.  These view objects can have all of your special high-level methods for manipulating the DOM build in and manage the DOM objects in your tree for you.  Conveniently, this also creates a nice abstraction layer you can use to hide other browser differences as well.  

This is the strategy used by SproutCore Views.  Each SC.View manages a single DOM object and sometimes a few of its children.  They reimplement much of the API actually used by the DOM.  This way DOM objects remain pure DOM elements manipulated by a pure JS layer defined by the view.

Unfortunately, most JS libraries today follow exactly the opposite approach.  Almost all of them try to modify the root prototypes of elements to add their own methods.  This isn’t really possible to do in IE since DOM objects are not real JavaScript so instead these libraries will try to infect each element they come in contact with with their methods to try to simulate the effect instead.  This is not only slow but leads to a wide variety of bugs.

Less DOM, more JS

So there you have it.  There of course are a lot of other minor differences between how the JavaScript language in FireFox and Safari and JScript in IE work, but most of them are easy to paper over.  The real tricky bugs that keep you up all night, however, are often driven from the differences in the DOM models.  To solve this problem, simply treat your DOM objects like foreign objects.  Follow the published APIs on these objects but avoid adding your own properties or enhancements on top.   

Or use a framework that does this for you like SproutCore. ;-)

Either way, if you understand this difference you’ll find debugging IE is not only easier but sometimes it a little bit fun.  Like learning a foreign dialect of your own native tongue; a little weird but mostly harmless and interesting,

 

* OK, for the pedants out there, technically the Document Object Model, or DOM, is the API defined by the W3C that the Document Object Tree (DOT?) conforms to.  Most people I know however simply refer to the Document Object Tree as the DOM, so I’m going to stick with that convention here as well.

** Also for the pedants: I am aware that both FireFox and Safari do not strictly keep a “peer” tree of JavaScript objects for all DOM elements in page.  However, this is the direction they appear to be moving conceptually and from a developer’s standpoint it’s easier to keep this mental model in the head than to deal with the actual complexity of the situation that is FireFox and Safari both blend the peer-tree and the wrapper models to some extent, mostly for historical reasons.  Either way if you follow my suggestion and always 

 

How to write a fast (and readable) method in JavaScript

Good methods should read like a story.  They should have an introduction, a climax, and a conclusion.  Here is what a good method might look like:

/**
Returns the first content object in the receivers content array whose key
matches the passed value.  
*/
findContentForValue: function(key, value) {
//
  // INTRODUCTION:  Collect data you will need into local variables.
  // Any data you might reference repeatedly should be collected here (such
// as the array length)
// Normalize your data here when possible to make the rest of the method
// flow...
  var content = Array.from(this.get('content')) ;  // The source content array
  var loc = content.get('length') ;  // The current search location.
  var ret = null ;  // The return value (or null if none found)
//
// CLIMAX:  Do the operation.
  while(!ret && (--loc >= 0)) {
    var obj = content.objectAt(loc) ;
    if (obj.get(key) === value) ret = obj;
  }
//
// CONCLUSION:  Cleanup and return the values.
  return ret ;
}

The Introduction

The introduction is where you collect all of your variables and setup your context.  A solid introduction is important to a good method because it both makes your method easier to read and improves performance.  

By declaring the variables you will work with up front, you help make clear to readers of your code what data you expect to work with.  This will prepare them to understand the rest of your code as it comes along.  It is also helpful to put commented explanations here describing what each method will do.  This way as a reader tries to digest your code, they will have a glossary to refer to when they see an unfamiliar variable.

If readability alone weren’t enough, JavaScript actually rewards you for using this style by making your code faster as well.  Every time you reference a variable (’foo’), JavaScript will search up a “scope” chain to find the value.  This chain begins with your current function and terminates with the “window” object, where global values will go.  By bringing all of the values you will be working with into local variable, you help to short-circuit this process for most calls.

The Climax

This is the part of your code that actual does the work.  Perform some processing, search through some data, whatever.  This code should generally try to work mostly with variable declared in your introduction and it should avoid returning early.  Instead, you should store the return variable somewhere and save it for your conclusion.

I’ve instituted a no-early-return policy for many years and often get a lot of pushback on it; but there are some good reasons for it.  I contend that early returns are one of the biggest barriers to maintaining code over the long term for two reasons.  First, early returns make your code a lot harder to follow.  There is nothing more frustrating than adding a console log or tracing some code only to have it return early before it gets to the part you wanted to investigate.  Second, early returns make it hard to re-factor your code.  How many times have you had to readjust a method because you needed to add some extra step to the process but some earlier code tried to exit before it ever got there?

That said, there are some good reasons to do an early return and I do use them in code when it makes sense.  For example, if you use a cached value to determine if a method needs to run at all, then an early return is fine.  I often put this code into the introduction-portion of the method in fact so that it is obvious to everyone when a method might not run at all.  Second, sometimes your code will have so many exit conditions that not using early returns will make the code harder to read.  This kind of code usually means you need to refactor anyway, but if it is unavoidable, early returns are preferrable to unreadable code.

The Conclusion

Conclusions should be simple.  They should not contain critical logic to your method and they should wrap up any loose ends so a reader can clearly see what they will get back when the function exits.  If you need to notify anyone of property changes or perform any other general housekeeping like that, do it here as well.  You should clearly indicate when you go into your cleanup phase, though, through comments so the reader knows they should not expect to see more application logic there.

My Conclusion

So that’s how you write a good method.  Pretend it is a story.  Introduce your variables at the beginning, do something interesting in the middle and return at the end.  Avoid referencing variables that are not in a local scope and avoid early returns.  If you do this, your JavaScript code will not only be far more readable, but it will perform better too.

 

SproutCore 0.9.4 ReleasedS

New release of the ruby gem today.  This gem includes a few important fixes for the SproutCore build tools as well as some enhancements to the JS framework.  The specific list is included below.

As usual, you should update the SproutCore gem if you want to get the latest build tools.  You can always get the very latest JavaScript code by running ’sproutcore freeze:edge’ from within your SproutCore project.

SproutCore 0.9.4 Changes

  • [FIX] Build system now generates index.html files for client bundles, even if they do not include .rhtml resources.
  • [FIX] Typos in the readme docs for the client generator.
  • Added automaticOutletFor() that will cause a view to be configured automatically instead of forcing you to use an outlets array.  Useful for when you are manually constructing your views.
  • Initial changes required to eventually implement improved observer notification system.
  • Improved documentation for a variety of classes
  • [FIX] Only fixtures ending in “.js” will now be loaded.  This allows you to include fixtures named .json or whatever and actually load them via XHR.
  • [FIX] The build system now ignored any rhtml files that does not appear in an lproj directory since this is where templates are stored.

 

How SproutCore loads views

I’ve been asked this question several times in the last few days so I thought I might help to put an explanation about how SproutCore handles binding HTML to JavaScript.  If you’ve ever tried to build a JavaScript app before, you probably know that the biggest cost when you load the browser is hooking up all of the JavaScript and event bindings to the HTML in you web page.  There are actually four things that are real performance hogs in a browser:

 

  1. Creating DOM.  If you want to build new HTML to replace existing HTML it will be 10-20x slower than simply having the HTML baked into the page on load in the first place. 
  2. Searching the DOM.  In general browsers are not super fast at finding elements in the DOM except for those named by IDs.  Even for those browsers with XPath support, the cost is nontrivial.
  3. Adding JS properties to DOM elements.  Almost all libraries out there today work by patching the HTMLElement prototype to add nifty utilities like $().  The only problem is that this trick does not work in IE, so instead you have to monkey patch every single DOM element when you touch it.  In IE6, that’s a 10msec penalty for every element.
  4. Binding to events.  Every time you add an event listener in the web browser, its another penalty.

 

Oddly enough most JS frameworks use techniques that hit all four of these bottlenecks, mostly because they want to “attach” to your HTML on page load.  If you’re adding just a few wiz-bang Ajaxy/Web2.0 effect this is not a problem, but once you start building entire applications with dozens or hundreds of views, these little costs add up.

The SproutCore Solution

The first versions of SproutCore actually faced these same problems as well.  In fact, I spent the better part of 6 months working through all of them.  Now SproutCore takes a decidedly non-traditional approach to avoid these issues.  Here is what happens when you build a SproutCore app:

 

  1. Static HTML is pre-generated.  Whenever possible, SproutCore views expect the HTML they will be managing to be pregenerated in the main document HTML.  The only time SproutCore views create new content is usually for collection views such as lists, grids, and tables.  By using this approach, SproutCore can use the most efficient code path in the browser (parsing on page load) to build out any DOM that will be required by the app.
  2. HTML is consumed on demand.  Most HTML and JS views are not needed right when a page loads.  It might be a hidden dialog or popup for example, that will not be used until later in the app.  Rather than finding all of these DOM elements right away, most HTML is stored in a single div called “resources”, which is pulled out of the main document as soon as it loads.  The SproutCore views and the DOM they use are consumed only when they are actually needed by your application.  
  3. Views manage DOM; DOM is not to be modified.  SproutCore views wrap DOM objects and reproduce most of the common DOM API you might use.  The idea is that you can generally work with SC.View objects and let them take care of the DOM elements for you.  The view’s in turn, take great pains to avoid actually adding properties to the DOM elements, avoiding the heavy performance penalty that comes along with it.
  4. Events are managed at the window level.  Instead of listening for an onclick() handler on 50 different elements on your page, SproutCore apps list to exactly 6 events on the window object instead.  SproutCore code then takes care of routing those events to the proper SC.View instance to handle the event.  Views themselves do not need to register for events to receive them; they just implement the appropriately named responder methods.  This means you can respond to as many events as you want on your page and you won’t pay any performance penalty on page load.

 

Overall SproutCore views definitely favor performance over convenience.  To make views convenient as well, SproutCore has the view builder system which uses to Ruby code to generate both the HTML and JavaScript for your views so you don’t have to.  This generally makes views both easy to use and performant.

 

New About Page/FAQ

Check out the updated about page.  I know there are some typos I need to fix in the morning, but in the meantime please leave feedback if you think the questions are not answered well enough and/or there are other basic introductory questions you think we should answer here.

 

Important: Action Required to Make Your Apps work in IE

UPDATE: I have released a new SproutCore gem (0.9.3) that includes these updated templates.  Update to make sure new apps you create include this fix.

I am beginning to re-enable IE support for SproutCore now.  Unfortunately I found a bug in the templates for clients and foundations that has now probably made its way into all of your code.  Please do the following in your projects to make sure this is not a problem for you:

  1. For each client or framework, open the core.js file.
  2. Look at the last line just before the });  
  3. If it has a trailing comma, delete it.  The last item in a hash should never have a comma trailing it.

This has been fixed in the templates so new clients and frameworks you create will not have this problem.  The SproutCore frameworks, sample apps and built in apps also have this fix.

By the way, the test runner and docs apps now work in IE7.  All unit tests for SproutCore pass except for the view-level ones.

Everything Old Is New Again: Why Client-Server is the Future of the Web

I’ve been talking to people a lot recently about the future of the web as I’ve worked on SproutCore.  I think most people agree on at least two things:

  1. Future web apps will be expected to be more “app-like”.  That is fast, fluid, and feature-rich. (the 3Fs of the next web)  Because of Ajax people are less and less willing to wait for their browser to refresh just to change a setting or edit some data.   
  2. No one likes plugins.  This future must somehow be built primarily on “web native” technologies - HTML, JavaScript, and CSS with Flash lending an assist where necessary.

As web apps creep towards more desktop-like behavior, they are quickly approaching that uncanny valley, where some switch will go off in users minds and they will suddenly expect web apps to have all the attributes of a desktop app.  Reasonable or not, its up to developers to figure out how to make this happen.

Here’s the fundamental problem:  web apps tend to be slow because they often live mostly in the server.  You take an action, wait on the server to respond, take another action, wait on the server to respond.  etc.  This is just a form of the old “terminal” approach used by mainframes.  Like the mainframes, the performance of an app like this is necessarily limited;  you simply will not be able to make this lag go away.

A lot of people say that Ajax is the solution to this.  In some ways it is but for most apps I’ve seen, Ajax is actually just a way to optimize this terminal behavior a bit.  Instead of refreshing the entire page for each click, you only update a part of it.  (By the way, did you know that mainframe terminals had their own version of Ajax?  It was called the IBM 3270.  The IBM 3270’s primary benefit was-you guessed it-partial screen updates.  It revolutionized mainframe computing…until the PC came along.)

So clearly we’ve seen this pattern before.  Users want a richer, faster more fluid experience than our old terminal-like technology can provide.  Tools like Ajax extend the life of our old model somewhat but they are too limited to deliver the kinds of experiences people will ultimately want.  So how do we solve this?

I propose that we look to the same solution IBM and friends came up with: client-server.

Client-server computing simply means that instead of building one app on the server and projecting it to the browser, you build two complete apps - one on the client and the other on the server - that both share your business logic and can operate on their own, sharing data when needed.  This allows the client to do most things with your data without consulting the server, hence delivering on the 3Fs.  In this case, the client will be written in Javascript and running in your web browser, but that does not change the model.

Thanks to more bandwidth, smarter browsers and faster PCs, the client-server model on the web is finally possible again, and without the major drawback that plagued itin the past.  Before you had to download and install clients onto every machine which was difficult to do and expensive to maintain.  Now, a 200K compressed “web app” of HTML, JS, and CSS can download and start running in just a few seconds.  And for the most part we don’t have to worry about cross-platform issues like before.

But not everything is peaches and cream.  For starters, writing an app in Javascript on the web is akin to writing C on the desktop: it is just one level above the “bare metal”.  When you start building full client apps in the browser, even simple things like displaying a list of items efficiently, can quickly consume endless hours of mind-numbing work to get it right.

The productivity issue can be solved pretty easily though.  You just need a framework that will do a lot of these basic tasks for you.  A good framework that leverages the natural strengths of Javascript and gets you 80% of the feature you need but stays out of your way for the other 20% you need to build can actually make writing these apps easy and a lot of fun.  

These frameworks are coming (SproutCore is one of these, of course), so I’m not to worried about that.  The even bigger challenge for client-server will not be a technical one, but a people one.  Many people in the web world do not have much experience with the client-server model.  Those that do consider this new-old pattern to be counter to the nature of the web.  Adopting this new approach requires some really mind-bending work that many people naturally resist.

In the end though, the fact is that the growing demands from users for fast, fuild, and feature-rich (3Fs) is going to demand that people begin to adopt this model.  Once the frameworks mature that make it easy to build these apps, then the pressure will really be on.  Expect to hear a lot of war stories as technical teams work through this philosophical shift and then expect some amazing work from those that get it early on.

The trends of history are clear.  Client-server and terminal-style technologies rotate in dominance every 15 years or so and client-server’s time has come.  The smart money is on client-server — coming soon to a browser near you.

 

Emulating Cocoa in JavaScript

The #1 thing I learned at the JS Meetup in San Francisco last week is that everyone seems to want Cocoa on the web.  I know of at least five frameworks now that try to essentially bring Cocoa to the web.  (Only SproutCore is open source so far afaik).

Cocoa is a great framework.  It makes writing applications on the desktop not only easy but fun.  There are a lot of good reasons to copy Cocoa for the web and a few really bad ones.  Here’s why I think it’s good:

 

  1. Cocoa is hackable.  Cocoa’s greatest strength is that it does everything the right out of the box 80% of the time, but because of how its late-binding object system works, it’s easy to hack it to do pretty much anything that you want.  Other frameworks, especially those with static bindings like Java and C++ are not nearly as easy to hack which is why they instead have to try to do everything, leading me to my next point…
  2. Cocoa is small.  Compared to the Swing APIs or to MFC, Cocoa is really a very small framework.  It has a handful of controls that can be configured to do most of what you want.  Since it is so hackable, Cocoa can get away with this.  Obviously on the web small is important for performance.
  3. Cocoa is clean.  Possibly the best reason to copy Cocoa is that for a 20 year old framework, the Cocoa team has done an outstanding job at keeping their API’s clean and consistent.  Using the same design patterns everywhere in a framework makes a huge difference to its usability.  Once you learn how to do things one way, you can assume they will work that way everywhere.

 

All of these things are good reasons to copy Cocoa for the web.  In many ways it already has built into its design some of the very things that are important to a web-based application.  However, not all in sunshine and roses with Cocoa, especially when it comes to bringing the framework to the web.  For example:

 

  1. Cocoa is built on Objective-C.  And fundamentally, it is built on C, a very static, strong typed language that leaves a lot to the developer to handle, including memory management.  A significant chunk of Cocoa’s functionality (i.e. most of Foundation) goes into overcoming this limitation with C.  Of course, JavaScript is a highly dynamic language with late binding and memory management built right in.  So copying a lot of this to the web is simply wasted space and processor cycles.
  2. Cocoa has cruft.  Like I said, for a 20-year old framework, Cocoa is pretty clean, but it does have some cruft built up.  For example, powerful new features such as bindings and automated garbage collection were just introduced in the last five years.  Bindings in particular make a number of older design patterns still supported by the framework unnecessary.  No doubt, if the team were starting from scratch today, building Cocoa with these new features from the beginning would yield and much smaller more concise framework.

 

So Cocoa is a great framework.  In many ways it has the kinds of things you would want to build apps on the web, which is a great reason to use it as inspiration.  That said, there are a couple of really terrible reasons why you might try to clone Cocoa as well, which unfortunately is what most of the frameworks I’ve seen so far seem to do.  Here’s what I hear from developers a lot of the time:

 

  • I don’t like JavaScript.  It’s true, JavaScript has a bad rep.  But like it or not, JavaScript is the third most widely distributed language on the planet.  It’s built into every web browser and it forms a fundamental part of the fabric of the web.  Not only that, but once you get to know it, JavaScript is actually one of the most dynamic, powerful languages to ever achieve mass adoption.  If you have ever wished you could just build things in smalltalk, objective-c, lisp, ruby, or python in the web browser, then you might be surprised to find most of the stuff you love about these languages is actually in JavaScript.
  • I really love Cocoa.  This comes frequently from people who have been building Cocoa apps for a long time and want to reuse the knowledge they’ve built up for their leap to the web.  Unfortunately, Cocoa was designed to overcome specific limitations with running on desktop machines and writing code in C that simply do not exist in the web world.  The reality is, not everything you learned from Cocoa is relevant for the web.  

Building a Cocoa-like framework for either of these reasons inevitably leads to a framework that tries to clone Cocoa method for method in spite of the fact that it is not being used in the same way.  This yields a framework that works against the grain of the web browser, not with it.  A framework that will do a lot of extra work unnecessarily just to maintain some abstraction, that will in the end break down at some point anyway due to the principle of leaky abstractions.  Ironically, these complications usually end up making Cocoa clones more difficult to use and less fun to code in; exactly the opposite of the intended effect.

Cocoa is a great framework.  It has a lot of lessons to teach us about building applications on the web, but the appropriate response to Cocoa is to be inspired by it, not to copy it.  SproutCore, for example, borrows many design patterns from Cocoa including MVC, Bindings, Delegates, Timers, Run Loops, and more.  But it doesn’t try to clone Cocoa method for method.  For example, SproutCore uses the built in Array class (with some enhancements), instead of trying to have an NSArray and NSMutableArray (which would both have to be mutable anyway).

The idea is to capture the essence of Cocoa (easy and fun to use), while still embracing the native tools of the web (i.e. JavaScipt), to yield a framework that feels at home on the web.  And that is the right way to bring Cocoa to the web.