13 ms·
Step by step from jQuery to Backbone
- lifeisstillgood 14y agoBrilliant - as someone who has recently taken the same steps (and into Marionette) there is a lot of half way info out there and not nearly enough complete tutorials. I am writing one myself - so would be interested to hear the good and bad points of this as much as the OP
- danso 14y agoGreat work...it calls to mind a longform guide that Sam Clay wrote in converting NewsBlur's spaghetti code to Backbone: http://www.ofbrooklyn.com/2012/11/13/backbonification-migrating-javascript-to-backbone/ http://www.ofbrooklyn.com/2012/11/13/backbonification-migrat...
- kjbekkelund 14y agoIf you have any questions regarding the blog post, just let me know :)
- kmthompson 14y agoThis is fantastic! Thank you for taking the time to write this.
- Jare 14y agoI have one: clearInput(), which clears the textarea, is tied directly to the addition of a new status, not to the submission of a new status via that textarea. Any other piece of the app that adds a new status (from other users, from automated systems, whatever) would clear what I'm typing. I can't imagine why you'd do that.
- kjbekkelund 14y agoHaha, of course. I guess it was just a moments blackout — I was probably just too focused on making Backbone easily understandable. There might be some strangeness in there, but hopefully most readers have a better understanding of Backbone after reading it. And I don't have time to change it now either way.
- paduc 14y agoNot a question but thanks a lot! I've been writing backbone applications for more than a year and I still learned a couple things thanks to your rundown. Also I'm totally going to use this to teach BB to my next recruits.
- jpb0104 14y agoMore great Backbone information: http://addyosmani.github.com/backbone-fundamentals/ http://addyosmani.github.com/backbone-fundamentals/
- freethejazz 14y agoI remember seeing this last July or August, but I lost it. So glad it resurfaced!
- andreypopp 14y agoI'm kinda scared that it turns out there's twice as much code in the final result. I understand, that this example is just for educational purposes but, I think, the conclusion that it's better to leave this jQuery-based piece code "as-is" is much more educational.
- aidos 14y agoI think it's more about showing people how this stuff works at a digestible level. I'm currently reworking something in Angular (I was only part way into the build). It took me a couple of days to get up and running but now I'm there it's paying itself off. The code is far more modular, easier to understand and I'm turning it out way faster. Toy examples will always just be that, but they're needed in order to learn.
- rdcapasso 14y agoThis is just fantastically put together. Thank you for doing this.
- sophacles 14y agoThis is a nicely written post, and uses nice idioms for backbone development. I would like to note though, that the justification for the increase in LOC count feels a little weak. I understand and agree with it, however before I really grokked what Backbone enabled I probably would have been a bit wary of that - it really just looks like extra work. I would suggest a follow up, that traces adding some functionality or widget use through both the original code and the newly refactored code, to highlight the power of backbone and make it clear. (I'm suggesting this from the original author, because the post I just read was pretty well written and seeing the same style in the in-depth guide would be pretty nice :) ).
- nerdfiles 14y ago1. Looks great in [Zen Mode](https://github.com/kjbekkelund/writings/edit/master/published/understanding-backbone.md#fullscreen_blob_contents https://github.com/kjbekkelund/writings/edit/master/publishe...). 2. Looks great in [Prose](http://prose.io/#kjbekkelund/writings/blob/master/published/understanding-backbone.md http://prose.io/#kjbekkelund/writings/blob/master/published/...)
- jcampbell1 14y agoIs it just me, or did reasonable jQuery get refactored into broken code? In the jQuery code, the status is added after the sever acknowledges receipt. In the backbone code, you are adding an element rendering it to the page, and then the model is doing some automagic synchronization. Unless there is some serious magic in the Backbone model, things can get completely out of sync. This looks like one hell of a bastardization of MVC. It seems the view is really a controller+view, and the model does the sync in a way that requires coupling the view to the model to handle any sort of error. Edit: I could be wrong here, but can someone show me how to fix the Backbone code to handle an error correctly? Error handling can be added to the jQuery code by adding 'error:function() { // do something simple },'
- sophacles 14y agoThere are a couple things you could do: 1) You can pass a {wait:True} as the second argument to collection.create(), and the add event won't be fired until after a successful sync. If you want error code, you add error:funciton(){..} to the create options hash. 2) You can change the event listened for from 'add', to 'sync', and still have the error handling code in the options hash. 3) You can manually create the model, call save() and have the success callback be code to add the model to the collection, and the error code do something else. In all of these, you'd just have to add a function to the view to indicate error, and do what you want to handle it. (Depending on the specifics, this could be for the NewStatusView or for the StatusesView..)
- jcampbell1 14y agoMy thoughts: > 1) You can pass a {wait:True} as the second argument to collection.create(), and the add event won't be fired until after a successful sync. If you want error code, you add error:funciton(){..} to the create options hash. This is problematic. Now you completely lose the "add" event, so if you wanted to do something like add a spinner while the request is in flight, that is not possible. > 2) You can change the event listened for from 'add', to 'sync', and still have the error handling code in the options hash. But now you are asking about the sync status from a collection. It doesn't seem relevant to ask a collection about it's sync status when you are interested in the status of a form submission. > 3) You can manually create the model, call save() and have the success callback be code to add the model to the collection, and the error code do something else. This seems to be the best option to me. It puts the success, error, and model all in the same frame, which puts us in the same place as the original jQuery. The jQuery code was far more elegant that the author would have you believe. At the core, you are handling a user interaction which comes in units of a "submission". The jquery code, wraps a "submit" into a singe activation frame and handles it. The backbone wraps this "submit" unit up, passes it through a collection, some automated saving, and now you have no way to reason about what comes out the other end. When you submit 5 times, and have 2 failures, what do you do? What is a collection going to know? I recognize the problem with the original jquery, but this ain't the right solution.
- scr4ve 14y agoI wonder why Backbone is getting so much attention. For small tasks, jQuery is completely sufficient (as in this example as others have noted). If you're going to develop applications on a larger scale, Dojo is a way better alternative in most cases IMO. It comes with modularization, build tools, i18n etc... Backbone is somewhere in the middle, neither highlevel nor lowlevel JS. I really don't see a spot where Backbone significantly outperforms either Dojo or jQuery. Can anyone tell me what's so special about it?
- swah 14y agoIMHO, one big advantage is that with Backbone you're still in jQuery world, where most cool things happen (because its so widespread).
- jashkenas 14y agoSince it gets asked so very frequently, I've tried to put together an answer in the FAQ here: http://backbonejs.org/#FAQ-why-backbone http://backbonejs.org/#FAQ-why-backbone
- nlh 14y agoThank you for the FAQ Jeremy - helpful to this Backbone newb. I won't ask you directly for the answers to this since it wouldn't be polite for you to answer (or would it?), but I feel like a lot of that FAQ is specifically addressing different frameworks' way of doing things, which is totally fine. Would someone mind extrapolating a bit and let me know which frameworks / features he's referring to in each point? I assume the 2-way data binding and "nifty demos" piece is about Meteor and Derby, and the "stuffing application logic into your HTML" refers to Knockout, but I'm a bit lost on the others. Just trying to grow my awareness of the landscape....
- ganarajpr 14y agoI am going to attempt to answer you : Here are the list of points from the FAQ : The focus is on supplying you with helpful methods to manipulate and query your data, not on HTML widgets (angular) or reinventing the JavaScript object model (Ember). Backbone does not force you to use a single template engine (Ember). Views can bind to HTML constructed in your favorite way. It's smaller. There's fewer kilobytes for your browser or phone to download, and less conceptual surface area. You can read and understand the source in an afternoon (Ember and Angular). It doesn't depend on stuffing application logic into your HTML (angular / knockout). There's no embedded JavaScript, template logic, or binding hookup code in data- or ng- attributes, and no need to invent your own HTML tags (angular). Synchronous events are used as the fundamental building block, not a difficult-to-reason-about run loop (Ember), or by constantly polling and traversing your data structures to hunt for changes (Angular). And if you want a specific event to be aynchronous and aggregated, no problem. Backbone scales well, from embedded widgets to massive apps. Backbone is a library, not a framework, and plays well with others. You can embed Backbone widgets in Dojo apps without trouble, or use Backbone models as the data backing for D3 visualizations (to pick two entirely random examples). "Two way data-binding" is avoided. While it certainly makes for a nifty demo (Angular & Knockout), and works for the most basic CRUD, it doesn't tend to be terribly useful in your real-world app. Sometimes you want to update on every keypress, sometimes on blur, sometimes when the panel is closed, and sometimes when the "save" button is clicked. In almost all cases, simply serializing the form to JSON is faster and easier. All that aside, if your heart is set, go for it. There's no built-in performance penalty for choosing to structure your code with Backbone. And if you do want to optimize further, thin models and templates with flexible granularity make it easy squeeze every last drop of potential performance out of, say, IE8. I have marked the individual points he pointed out with the relevant MVC framework out there.. I might have missed out on some but it looks like ( atleast to me! ), jashkenas feels the greatest threat to Backbone currently is Angular.. And I think he is right about it.. Backbone is currently ruling the throne of Front End MVC frameworks, but it looks like its rule is ending soonish...
- romaniv 14y agoI am familiar with two general approaches to creating unreadable and unmanageable software. The first one is to take logically unrelated operations and combine them into one giant blob via shared/global variables and god objects/methods. This is what commonly known as spaghetti code. The second one it to take every piece of functionality and shatter it into tiny pieces, so no unit of code represents anything anymore. This can be done with endless callbacks or layers of abstraction, and it can be made worse by complex frameworks with a lot of "magic" taking place or a lot of boilerplate being required. I don't know any common name for this, but let's call it mush coding. It looks like the post describes how to convert moderately readable spaghetti code into unreadable mush code. (I would claim that a person not familiar with JQuery could easily understand the initial code, while a person not keenly familiar with Backbone would be completely lost in the final version.) If most of your methods are longer than 100 lines, something is probably wrong. If most of your methods are shorter than 3 lines, something is probably wrong as well.
- STRML 14y agoWhile in principle I agree with you, the article references an extremely simple application for the sake of example. In reality, you would never build an application this simple in this manner. An article showing how to do this with a real webapp from beginning to end would nearly be book-sized. When building an actual webapp, the Backbone method is going to be much easier to extend, test, and understand versus jQuery spaghetti.
- christiangenco 14y agoPrecisely the point I was going to make. This is a condensed example of translating jQuery-like thinking to backbone-like thinking. To quote kjbekkelund: > [The backbone] code is more maintainable, easier to reuse and extend, and easier to test.
- abw 14y ago> I don't know any common name for this, but let's call it mush coding. "Ravioli Code"
- 14y ago
- AlexMcP 14y agoI think it's important to note that if this code never grows or changes, then this refactor is totally unnecessary. It DOES add code, and it DOES almost over-decompose the structure. The payoff, however, is if more features or behaviors were in the pipeline (and when aren't they?). This really sets you up to gracefully manage more complexity by having sensical places to put more code, instead of writing a few more $(document).ready callbacks to ship something on time. Backbone.js might not be the right tool for the contrived example, but I've come to expect a sacrifice of real-world applicability for smaller, digestible chunks. That the synthesis is up to you is ok, I think.
- BillGoates 14y agoSeparating DOM and data I can understand, but I am not convinced Backbone is the right way to do it. My code would look more like: function postdata(url, data, callback) { $.ajax({ url: '/status', type: 'POST', dataType: 'json', data: data, success: function (received) { callback(received); } }); } var statusform; (function(pub) { var status = "" pub.init = init; function init() { $('#new-status form').submit(function(e) { submitdata(); e.preventDefault(); }); } function submitdata() { var data = { text: getfieldvalue("textarea") }; if (!data.text) { return; } postdata("/status", data, function(received) { status = received.status; drawscreen(); }); } function getfieldvalue(fieldname) { return $('#new-status').find(fieldname).val(); } function drawscreen() { if (status) { $('#statuses').append('<li>' + status + '</li>'); $('#new-status').find('textarea').val(''); status = ""; } } }) (statusform); $(document).onload(statusform.init); Note 1: This code sample is untested, but should give a good enough idea what I am trying to do. Note 2: For extra type safety, use typescript interfaces to model data.
- gknoy 14y agoApologies for off-topic, but how does one post code, or do quoted text on HN? I've seen it done here and a few other places, but haven't been able to find documentation on how.
- cristoperb 14y ago"Text after a blank line that is indented by two or more spaces is reproduced verbatim. (This is intended for code.)" http://news.ycombinator.com/formatdoc http://news.ycombinator.com/formatdoc
- pacomerh 14y agoI really like the approach of translating from jQuery. Even if you don't end up using Backbone for everything, it really gives you an idea of what to do with it. I read Backbone tutorials before, and you learn how to do things, but with not much language context. Looking at the alternative ways to do one thing is way more useful.
- taproot 14y agoAgreed, I really enjoyed working through this, haven't come across anything giving the the same level of context to, not only the why, but the how you got there side of things as well. I wonder if the author would be interested in writing up something about unit tests / tdd in the same sort of fashion.
- hayksaakian 14y agoI was nodding my head until about half way through. Thinking that I could apply this logic to client side storage was fine until he proposed that persistance would be automatically handled by Backbone's ajax. At that point, backbone gives you less flexibility for more code. No thanks.
- nijiko 14y agoI don't see any benefit of using backbone, not only do you create a mess and spend hours trying to learn, refactor, and clean it up, but it also means the next person has to understand it just as you do, and agree with the way you implemented it and trust me because backbone is really flexible and there is no real structure (look at examples there are about 90 million different ways to implement this) they will not agree. A simple jQuery or Promise ajax call is a lot less hassle, and your own simple 30~40 line solution for whatever backbone provides is way less time spent with backbone and worrying about it's memory leaks and what the next developer will mess up. Note: I worked with backbone for an entire year almost, two months shy, and it's benefit never showed itself. We were constantly having to finagle the codebase and ended up writing our own MVC framework because of model issues, routing issues, or just generic data-handling issues that you /will/ inevitably run into. I never understood what people see in this terrible framework. It definitely isn't worth the wasted time especially in the startup agile-centric world where every minute is spent money.
- jonny_eh 14y agoWhy do I get the feeling this could have been done much more easily with angular.js?
- henkap 14y agoI want to see a similar post for angular!