4 ms·
Nice post. I'd like to briefly respond to the bit about the difference between Spine, which generates pseudo-GUIDs for models created on the client, later overw
by jashkenas 15y ago
Nice post. I'd like to briefly respond to the bit about the difference between Spine, which generates pseudo-GUIDs for models created on the client, later overwriting them if the server responds with a real id; and Backbone, which has a "cid" (client ID) for every model regardless of the canonical server ID.
The reason why Backbone provides a persistent client id for the duration of every application session is so that if you need to reference model ids in your generated HTML, you always have something to hang your hat on. If I have '<article data-cid="c530">' ... I can always look up that article, regardless of if the Ajax request to create it on the server has finished or not. With Spine's approach: '<article data-id="D6FD9261-A603-43F7-A1B2-5879E8C7926B">' ... I'm not sure if that id is a real one, or if it's temporary, and can't be used to communicate with the server.
Optimistically (asynchronously, in Alex's terms) doing client-side model logic is tricky enough in the first place, without having to worry about creating an association based off a model's temporary id. I think that having a clear line between a client-only ID and the model's canonical ID is a nice distinction to have.
- phzbOx 15y agoWould using only a CID be a solution? From the server perspective, it stores the real ID and the CID given by the client. In the extremely rare case where CID could be duplicated, the server could send back an error with an unique CID and the client would update itself. That way, we're sure the ID is always unique on the server, but the client simply use a cid. In fact, the 'cid' could even be abstracted away by calling it ID. I.e. the server has 2 ids, the server one and the client one.. the client doesn't need to know the server-side one.
- roc 15y ago> "In the extremely rare case where CID could be duplicated, the server could send back an error with an unique CID and the client would update itself." That's exactly the catch. If you still need to consider CID collisions and write code to handle a potentially-different canonical server ID, there's no conceptual or complexity savings. You're not doing 'only' a CID; you're doing all the same work.
- phzbOx 15y agoWell, I don't want to go into deep maths but the chance of creating the same cID is infinitesimal.. so one doesn't have to manage this case graciously. I.e. Just refresh the page or make a soft refresh (clear the models and re-send the data from the db, which isn't huge since that part is already coded for the initial loading). It's not the same as if it had 1/10 chance and you had to be clever to fix it. I mean, even without this problem, it happens from time to time that the best software needs to refresh because of a small bug.
- roc 15y agoThat might be a practical improvement for some applications. But at a framework level I don't see any clear reason to prefer that approach. Particularly as the savings evaporate for any applications that can't handle collisions 'less than graciously'. And, personally, it still 'smells' to me. I know that's not an objective argument, but there it is. It feels like a particularly leaky abstraction that will end up causing more trouble than it spares. edit: clarified sarcasm that looked ambiguous on second glance.
- jashkenas 15y agoSure, if you want to get fancy you can always do something fancier. But in many apps, your server-side IDs are auto-incrementing MySQL or Postgres ids, or even a Flickr-style ticketing ID server. You really don't want your DB to be worrying about what are essentially transient JS/HTML references.
- danmaz74 15y agoCouldn't you just allocate a pool of IDs to each session (open client), and let the client generate real, unique IDs directly using them? This way you wouldn't need collision detection, synchronization, etc. You only need a big enough IDs space, or a way to reuse IDs of the pool that weren't actually used by the client (by including them in new pools).
- nazar 15y agoI am afraid that would create a mess in a db(its just my guess). Though your idea sounds nice to my ears. The hardest part would be if session runs out of id-s I guess. One can never allocate optimal pool of IDs for every user, there are always going to be "bad cases".
- danmaz74 15y agoIf the id space is big enough, not having optimal pools wouldn't be a problem. And if you are near the exhaustion of a pool, just request a new one...
- bchallenor 15y agoThat's what (N)Hibernate calls the hilo algorithm. Compared with GUIDs, it has the advantage that IDs are somewhat sequential. (Random keys are terrible for index fragmentation.) http://stackoverflow.com/questions/282099/whats-the-hi-lo-algorithm http://stackoverflow.com/questions/282099/whats-the-hi-lo-al...
- dnagir 15y agoThe use of temporary GUIDs might be ok when those are used INTERNALLY only and not exposed outside. What happens with Spine, though, is that those IDs are used in a URL. So in the example I get the URL for the newly created page: http://spine-rails3.herokuapp.com/#/pages/34B3CC88-32CC-4D08-B0CD-AE5248A87269 http://spine-rails3.herokuapp.com/#/pages/34B3CC88-32CC-4D08... Who of you can actually access it? That isn't right. The GUIDs should be internal only. This leads us to the complexity of the "Async" UI in general. In order to redirect (navigate) user to a proper URL you DO need to wait for the response from the server. But the real async UI should just allow user to do something else. It doesn't mean it should not WAIT for the server response.
- Detrus 15y agoBut from reading the article he says that with Spine, using either the temp or final ID in your app will work. It seems to handle the temp to final ID linking under the hood. That's assuming I'm reading the article correctly.
- dnagir 15y agoThat is notncorrect. GUID is only preserved within one single page. Go to the example, create a page. Copy the link and open in a new tab. You will see.