

An Identity Map for Backbone.js - marcfasel
http://blog.shinetech.com/2012/12/24/an-identity-map-for-backbone-js/
At Shine, we’ve been working on a large Backbone.js application recently and found that identity issues relating to long-lived objects caused a number of subtle and not-so-subtle bugs. For us the solution was to introduce an identity map.
======
jashkenas
Neat little implementation. A couple quick thoughts:

* Identity maps aren't a panacea -- If you're just getting started, and you don't yet know that you "want" an identity map, you don't necessarily need one. There are a bunch of situations where having the ability to model multiple versions of the same resource is useful. For example, an "editing" version of the resource with changes that may or may not be applied to the canonical version ... or a "conflict" version of the resource that has been changed on the server, that you can reconcile with the local version.

* Backbone Collections already maintain a map of id-to-model information for you, and you can rely on them as an identity map ... if you don't use "new". Instead, something like this:
    
    
        Backbone.Collection.prototype.lookup = function(id) {
          return this.get(id) || new this.model({id: id});
        };
    
        // Then later, instead of `new` or `get`:
    
        Accounts.lookup(id);
        
    

... would provide a simple implementation of the same behavior, without having
to change the semantics of "new", or maintain an external id-to-object mapping
that makes it harder for garbage collection to work later.

There's also a version of the above function that you can add that does
"lookup or fetch from the server" -- another alternative is "lookup locally,
fetch from the server, or create on the server". Whatever you need for your
app.

------
mikeknoop
I've implemented something similar in the same manner (over-riding `new`). The
original idea came from here:
[http://backstage.soundcloud.com/2012/06/building-the-next-
so...](http://backstage.soundcloud.com/2012/06/building-the-next-soundcloud/)

One implementation detail I ran into is how to detect dupes. When you have
Backbone Models, this is easy: every model has an `id`. But say you want to
apply this same singleton behavior to a Backbone Collection, which don't have
natively have `id`s. I saw two options:

1\. Assign an `id` to the collection when instantiated (could just be a
string, so that you can force a singleton only when you desire it).

2\. De-dupe based on `instanceof` checks. The downside here is you always get
a singleton even if you might want a one-off instance of a collection.

Are there any other options? Can your Identiy Map handle collections?

------
dorkitude
This is clever!

My solution has always been something to the tune of:

    
    
        var kyle = Person.getByName("kyle");
    

But your solution is better in that the interface need not change (there could
be a lot of code to rewrite in my case, if the "new" keyword were already
being used everywhere).

I do like it that in your solution the interface is (or remains) elegant, but
I can't help but think, as a pythonista at heart, "explicit is better than
implicit". So I'm little freaked out by the idea that code reading:

    
    
        var kyle = new Person("kyle");
    

isn't actually constructing a new instance.

~~~
masklinn
Then again, the equivalent Python code does not at all guarantee it'll return
a new object, and it's a very good use case for returning objects from JS
constructors.

------
marbemac
Interesting. I threw my take on a Backbone identity map up on Github. 31 extra
lines of code. Just add a keepInSync: true attribute to models that should use
the identity map.

It's a modified version of this code:
<http://news.ycombinator.com/item?id=3276990>

<https://github.com/marbemac/backbone-identity-map>

------
fertaprico
Backbone-relational model solves this problem with a few additional features
(and last version it's compatible with Backbone 0.9.9):
<https://github.com/PaulUithol/Backbone-relational>

------
vmind
Nice approach, though it would seem to not be needed with Backbone 0.9.9, with
the new 'update: true' option for fetching collections. (If you have a central
data model for your application that is.)

