11 ms·
Backbone has made me a better programmer
- xyzzyb 14y agoI actually prefer the second (complicated) example: everything that happens on the success of the call is right there. If it were to grow more complicated than that I'd move it to its own function and perhaps break it into a few functions: not into several objects. I find firing events to be useful when I'm writing code that's not meant to be directly accessed, e.g. a jQuery plugin.
- asolove 14y agoSo you have some change, either an xhr or a dom event. You want it to trigger a bunch of other changes somewhere else. One approach is to call functions (or call functions that call functions...) that directly make that change. This method is fairly clear to read but it becomes messy when more logic gets involved. The Backbone approach is actually similar to writing a really good jQuery plugin. When the change happens, you convert the raw xhr or dom event into a custom event that is in the language of your domain model. Then anyone who wants can do what they want with it: views can update themselves, other models can update their data and check it with validations, throwing other events, so that changes propagate naturally through the system. If you aren't familiar with Backbone or MVC this code initially appears to be spaghetti: why does this one event result in functions all over being called, seemingly randomly, even though they're never called directly? But after a bit of practice, you get used to the pattern. And I find it an excellent way of structuring large front-end applications with lots of reusable behavior. My mental model of such applications is a directed graph connected by events. Each object has a set of events it is interested in and listening to, and a set of events it is responsible for and firing.
- xyzzyb 14y agoOh for sure. As soon as my code will be touching multiple, disparate parts of an application I'll look to events. But I'm be wary of code that uses events for everything.
- MatthewPhillips 14y agoThe "everything is an event" paradigm is a bit overused. There is overhead to event libraries. You should really only use them when you think an object will be observed in more than one place. Otherwise an obj.onsuccess works just fine.
- xyzzyb 14y agoThat's where I'm coming from here. It's great Backbone encourages event driven objects, but don't hammer everything with it.
- crusso 14y agoRight. What the author of the article ignores is the tradeoff you make when you spread triggered behavior all over your code. When something goes wrong, debugging is a lot more difficult and race conditions sprout up unexpectedly. Event driven, decentralized programming requires new rules and discipline in how resources are accessed. Sometimes a big ugly function where everything happens is a lot easier to deal with than a wild goose chase through a dozen different places in the code (and a cascade of subsequent triggers).
- gruseom 14y agoAgreed. And it doesn't have to be ugly, either.
- novaleaf 14y agoi think it's nice to see some javascript design patterns!
- franze 14y agoi think design patterns are either A) a lack of necessary abstraction - or - B) a sign of unnecessary complexity
- lmm 14y agoThis. I remember reading a definition of a design pattern as "a structured way of working around a language deficiency".
- mattgreenrocks 14y agoPowerful languages don't force you to decouple your code. Disciplined use of patterns can help. But all our minds are warped from thinking web programming has to be different somehow from the desktop programming of old, and that concepts like SRP, LoD, and coupling don't matter.
- novaleaf 14y agoto me, design patterns are how a team designs on the general way of doing a certain activity, and avoid doing it wrong. maybe unneeded if you are solo, and I agree that "you should know why the best practice is best" but I strongly feel these are very helpful not only for teams, but for learning.
- davidw 14y agoI think a real example might be better. I did not find the 4 lines of code difficult to read.
- mattmanser 14y agoOT: I keep trying to get into backbone but I just get driven crazy by `get` and `set`. Inspecting your object feels like a world of pain, which is no fun when I'm playing with code. And it also makes it feel like you're not programming js any more. Quite a few years back an old company I used to work for had a similar framework and perhaps it's just latent hatred for that rather annoying framework. I know it's a limitation of the present js because you can't make getters and setters, but it just completely kills my enthusiasm for backbone, which otherwise seems great. Are there any alternatives out there using Object.defineProperty instead? I know it's still not really web ready, but it'd be far more fun to play with.
- jashkenas 14y ago> perhaps it's just latent hatred for that rather annoying framework ... hopefully ;) The reason why you need `set` is so that you know when to trigger `change` events. Getters and setters aren't going to fly if you need to support Internet Explorer. One alternative is the Angular.js tradeoff, where you're setting regular properties on vanilla objects and arrays ... but then Angular is going in behind the scenes and traversing all your objects and computing the diffs for you, every time a change might occur. ... in the end, you start to appreciate the transparency of avoiding getters and setters in JavaScript. It's a very nice thing that whenever I write `obj.a = b` -- I can know that that operation has no side effects, and won't trigger any outside-of-the-box behavior. Conversely, whenever I write `model.set('owner', 'Moe')`, it's nice to know that this is the point at which the rest of the app will react to that change.
- whalesalad 14y agoThanks for this short and logical answer.
- mattmanser 14y agoI didn't make it clear, but Object.defineProperty with getters and setters gets rid of angular.js's traversal needs (I assume, having only looked at angular quite a while ago). There's a few different ways I can think of doing it, I'm just wondering if anyone has yet. And it also gets rid of the need to hide all your properties in an attributes collection. I'm not sure why you think that's good because it doesn't fire events. And if you really need ignore properties, you could do something like this: var Person = {}; Person.prototype = new Model; var bill = Person.create({ name : "Bill", email : "bill@example.com" }); //adds all using defineProperty and a watcher in get, set functions alert(bill.name); //Woo, alerts "Bill", not undefined! bill.name = "Bob"; //event fires person.special = "blah"; //wouldn't be watched as it's been added after creation person.addProperty("special2", "blah2"); //would be watched person.special2 = "blah3"; //events now fire with 'normal' access var person2 = Person.create({ name : "Bill", email : "bill@example.com", special : "thing" }, { ignore : ["special"]}); //special is not watched You could even do the opposite and tell it exactly which properties to even bother watching. There's a reason getters and setters have been added to js, and it's for exactly this kind of thing!
- jpk 14y agoBackbone is one of those libraries/frameworks/whatever that avoids magic. It's just a pile of reusable parts that make building big javascript applications easier. One can't say the same about, say, Rails. There's a lot of magic in Rails. Not that magic is a bad thing. Magic is what makes Rails good at what it's good at. The downside, though, is that magic-ful frameworks often obscure language mechanics that an inexperienced user of the language would do well to understand. Thus, Rails is awesome for a programmer who's already good at Ruby, but super frustrating for someone learning Ruby. On the other hand, Backbone makes idiomatic use of javascript and lays it on the table in a magic-less way. So not only does a new javascript programmer not have to deal with confounding magic, they can also learn from how Backbone uses javascript, and apply that knowledge outside the scope of the library. I'd never thought of it this way, but I think this is probably one of the most important distinctions between opinionated, magic-y frameworks, and things like Backbone.
- knowtheory 14y agoThe thing I've enjoyed most about Backbone, is that it's given me a sane conceptual point for learning browser APIs, and libs. Using Backbone in no way obviates the need to learn about how browsers work in the end, but it does make it a hell of a lot less painful for you to engage in that process. also +1 for literate code as a mechanism for learning more about what Backbone's responsibilities and defaults are.
- jongold 14y agoTotally agree with this post - I was a 'JavaScript =~ jQuery' guy before I picked up Backbone - writing hopelessly average jQuery spaghetti (with the best of intentions - I'm a designer and had never looked at JS as a programming language. Backbone has totally changed all of that - learnt so much about design patterns in such a short space of time - shout out to Addy Osmani for writing such down-to-earth, approachable content.
- kenkam 14y agoI also agree, although instead of Backbone I recently found that Twitter Bootstrap's javascript files offer similar insights as to how to structure code in an javascript-style object oriented manner. For example: https://github.com/twitter/bootstrap/blob/master/js/bootstrap-typeahead.js https://github.com/twitter/bootstrap/blob/master/js/bootstra...
- MatthewPhillips 14y agoPlease don't learn anything from that code.
- politician 14y agoThe code seems reasonable; could you explain why it's not?
- kevincennis 14y agoAside from the always controversy-inducing lack of semicolons and the slightly unintuitive leading bang for the IIFE, I don't really see what's wrong with this code.
- MatthewPhillips 14y agoSomething doesn't have to be wrong to be bad learning material. That code is chock full of unconventional js. For example, why they declare their objects like this: var Typeahead = ... Typeahead.prototype = { constructor: Typeahead ... rather than the usual function Typeahead() { ... Typeahead.prototype = { ... is a mystery to me.
- Kototama 14y agoI'm also enjoying backbone.js since a few weeks and it helps me write new code without too many callbacks and keep a clean separation between the UI and the data. I also pushed some Emacs Yasnippets templates for backbone.js today, feel free to contribute: https://github.com/kototama/backbone-underscore-snippets https://github.com/kototama/backbone-underscore-snippets
- hasenj 14y agoI didn't really like backbone at all. It was a pain. It didn't offer anything to help you build complex UI. I had to use backbone to build a mildly complicated UI - not so complex, mind you, just something that's supposed to be somewhat interactive. Backbone was no help at all. Its "views" don't really offer anything. Just about 2 weeks ago I discovered knockout.js, and I felt stupid for spending days building something that would probably take an afternoon to do with knockout.js. Then, a week later I discovered angular.js and felt even more stupid. Now I really dislike backbone.js
- marquis 14y agoYes! Not to hijack this thread but I hated building web interfaces with javascript, struggling with cross-browser support for anything remotely non-standard. We've been using Angular.js for the last month to build a very beautiful, complex interface and I'm loving every minute of it. As long as the framework doesn't change too drastically over time I know we'll be able to keep what we've built for its 2-3 year lifetime and fingers crossed that IE14 and Safari 7 don't break too much of it.
- MatthewPhillips 14y agoAngular.js doesn't really solve the hard parts of writing web applications either. The hard part is structure. Not data binding. I don't need a framework to automatically update an <input> for me, input.value = val isn't costing me sleep at night. What we need to make web applications easier are equivalents to things like UIPageViewController in iOS or Activities in Android. Real views that do real things. It seems that JS frameworks only give you the very top level base View class that does almost nothing.
- marquis 14y agoI think that these views are going to happen, especially as the Angular-UI project moves forward. The documentation of Angular needs a lot of work, but the fundamentals are sound and I think we might have a framework that genuinely gets us building apps instead of struggling with jquery.
- jpallen 14y agoUnit testing will also force to decouple your code in a similar way. In the first example it is impossible test individually test all the things the code should do without worrying about everything else that is going on (e.g. you need make sure all the elements exist on the page). By moving to an event trigger like you suggest, you can then test that each listener does the correct thing independently of the others. You can have a separate test for 'selector' and 'yet-another-selector' and they don't need to know about each other. As an added benefit you don't need to mock out your ajax call either. Instead you can just fire a "DataModel:update" event in the unit test. I've only recently grokked this aspect of unit testing and I feel like it's made my code an order of magnitude better and more maintainable. Thinking first about how to write code in a decoupled manner also makes unit testing really easy. After having tried unsuccessfully for years to test my code it was a revelation when I that it was because my code was bad that it was hard to test, not that testing is itself hard. Edit: I've tried to illustrate my thoughts more clearly with a copy-cat post to show the parallels between the two: http://news.ycombinator.com/item?id=4427842 http://news.ycombinator.com/item?id=4427842
- mmcnickle 14y agoI've been using TDD for server-side code for some time now, but I struggled with it for javascript; I thought unit testing javascript was a myth. It was only when I started using backbone that I realised that I was writing horrible, terrible code.
- Void_ 14y agoDon't thank Backbone. It merely uses some of patterns that desktop applications have been using for years. If you really want to be a better programmer, I suggest you learn Cocoa, or other well written desktop framework.
- robinduckett 14y agoBackbone didn't make me a better programmer, dealing with it's bullshit has.
- sekou 14y agoI'm making my way through Jeffery Way's fantastic jQuery series. This looks similar to a Publish/Subscribe concept, also jQuery deferreds are apparently another good way to avoid putting too much code into a success callback.
- jparishy 14y agoI'm really glad that Backbone has helped you become a better programmer; that's great! But it's worth nothing that this is really a trickle down effect from the creators and maintainers of Backbone making use of great design patterns and using effective programming practices. We should all strive to learn from great code in many languages using the design patterns and practices of many libraries :) *edit: typo
- jb55 14y agoWhen we started using Backbone it was good for awhile until there was so much code duplication all over the place. We decided to build a small declarative API on top of backbone that allows us to easily compose views by mixing in common functionality. It looks something like this: AlbumsView = bQuery.view() .set("el", "#albums-view") .init((opts={})-> @readOnly = opts.readOnly or no @app = opts.app ) .use(Mixins.bq.init('albums')) .use(Mixins.bq.collection tag: "#album-list" createView: (m) -> AlbumView = Views.AlbumView(readOnly: @readOnly) new AlbumView { model: m, app: @app } ) .use(Mixins.bq.filterable pred: (album, ftext) -> album.get('title').indexOf(ftext) is 0 filterTag: "#filter" collectionTag: "#album-list" ) .on("click #addNew", -> @collection.create title: "New Album" type: "Album" ) .make() For example, the Mixins.bq.collection plugin abstracts away the common task of adding and removing subviews when new things are added the collection. The filterable plugin abstracts away the common task of filtering collections. Our custom init plugin sets up all the events common to all of our views. In the end make() just returns a BackboneView with all the events set up properly. It has saved us so much time we figure people may actually want to use this as well, we just have to write the documentation and some plugins now :) https://github.com/jb55/bquery https://github.com/jb55/bquery
- jarek-foksa 14y agoWhat's the point of this excessive chaining? I use CoffeeScript a lot, but your code looks unreadable to me.
- jb55 14y agoChained method calls is analogous to function composition from bQueryView to bQueryView. You could write it this way if you don't like the look of it syntactically: bqView = bQuery.view() bqView.set(...) bqView.on(...) MyBackboneView = bqView.make()
- eranation 14y agoI think code verbosity (which anyone can read and understand) is highly underestimated these days. I don't think writing less lines of code is any good if you need to explain to people what you did (yes, even smart people sometimes don't figure it out right away if they didn't use a similar library / concept before, and you don't always have smart people reading your code anyway, we all know that) If you optimize your code to avoid any duplication, you are probably wasting more time writing / extending libraries, doing pull requests than getting working software done. Refactoring, and good design is critical, helpful, almost mandatory, but if your feature is not out there on time because you over refactored / engineered your code, and some other startup get's it out there faster, no user will care. users don't do view source before they pay you.
- seivan 14y agoMay I suggest Batman.js :)
- Kiro 14y agoAm I the only one who still makes websites with very little JS in them? One jQuery thing here and there. Using Backbone would be overkill and to be honest I can't think of one hypothetical project where I would need it.
- powatom 14y agoA lot of JS tends to be required when you're building a big, dynamic web application, or your website needs lots of modules and lovely little widgets. If you can avoid writing a lot of JS, then that's great - but HTML / CSS alone can't provide the features that a lot of users are expecting.
- suyash 14y agoBackbone has only given you the tools to make your code better, you have made yourself whatever you are.
- powatom 14y agoTL;DR - This was originally a reply to another commenter. There seems to be a lot of people accusing Backbone of failing to provide things that it has never claimed to provide. This is a bit of a rant so apologies in advance! Obviously YMMV but I've been batting these criticisms of Backbone away left, right, and center recently. To summarise: If you need a framework, then Backbone is not what you're looking for. Use something else, because in all likelihood Backbone will not give you the tools you're looking for. Backbone solves a different problem. ==== The only real 'major' problem with Backbone.js is that people for some reason think it's a framework. It is not, and as far as I'm aware it has never claimed, or attempted, to be one. The real, underlying problems that Backbone attempts to solve are the following: 1: Unstructured, spaghetti JS code. 2: Complicated DOM traversal / outrageously convoluted jQuery selectors. 3: Total lack of templating. 4: Generally crap organisation of your application. Customers / users are constantly requesting more dynamic pages. You know that form which adds a new item to the Foo list? Why does it have to refresh the entire page? Why can't I drag and drop stuff like I can with every other application I use on my computer? Customers are realising that they CAN do cool stuff in their browser now, and you better believe you're going to get a call asking you to turn a previously read-only site into a fully dynamic web app. So you do what every other dev does and rewrite the whole thing from scratch using a proper framework and it's all nicely designed and fully specced out. Or not. What actually happens is your customer doesn't have enough money for a re-write. They want all the existing features, but they want the development phased. Your boss / colleague / dog wouldn't let you re-write the damn thing anyway because they assume that it's just a case of cut + paste from another application somebody who no longer works there wrote 10 years ago. So you do it step by step. You do it page by page / feature by feature. That page which displayed a list of items now displays new items automatically, you don't need to refresh the page! Adding a new item is a simple AJAX call back to the server. Notifications? Done! And then a bug is found. Suddenly you realise you have no real way of isolating your model from the DOM. You're hiding data in hidden input fields so you can retrieve it via jQuery later and do something with it - maybe some AJAX request to the server. It takes you a day to fix a bug that should only take 5 minutes. It takes you a month to add a new feature that should only take a few days. It seems like only in web development do developers have this (when you think about it) really, truly, WEIRD approach to building applications. We let the data provider build our user interface. We don't bother with models - just hide data in the DOM and get it back when a user clicks a button. Need to represent the same data in two different ways? Build a new View in your rails app and add a ton of logic to change how it looks based on the model's data. Why do we have an MVC framework server side and then forget all about it on the client-side? When you think about a web application PROPERLY, the insanity becomes obvious. In what other development domain do we allow the data provider (the server) to render the user interface? Why do we discard models and proper encapsulation? Why do we weave logic into views which should really live in a model / controller? What the hell have we been doing to ourselves? A lot of web app developers think they're building the following: Server (Model / Controllers) - GIMME DEM HTMLZ -> Browser(View) What they SHOULD be thinking about building is: Server (Data Provider / API) <-- DATA TRANSPORT --> Client (Model / View / Controller) The fact that you're using HTML and JS to develop an application is merely incidental. Your server provides you with some data - it's insanity to also let it define what that data should look like when it arrives client-side. Backbone.js aims to solve THESE problems. It is not an application framework. It gives you a few basic objects and hopes a light bulb flickers on above your head. Suddenly you realise that hey - you CAN isolate your models from your views. You CAN have multiple views per model. You CAN have proper event handling, just like you can in every other non-web application you've ever written. Hurrah! Need to extend your model? Easy! How about displaying the same model - once as a full page, once as a widget in a sidebar? Simple! Need to update the view when your model gets updated? Piece of cake! Backbone is a solution to a lack of structure. It is not a framework. There is no convention, no 'right way' to do things. Backbone is exactly what the name suggests: a spine for your application. Everything else - your framework, your error handling system, your security mechanisms - these are all left for you to figure out yourself. You can pick a framework built on top of Backbone, or you can figure one out for yourself. Backbone doesn't magically turn your web app into a modular, extensible system - but try to build one WITHOUT Backbone or something similar and see how far you get before you realise you've got serious problems. > Nested views and automatic view updates. Not Backbone's problem. It doesn't even attempt to solve this issue as far as I'm aware. Solve it yourself, or use something which does. > How would you display a list of items in backbone? What do you do when an element is removed/added? How is this Backbone's problem? How would you do it in any other programming language aside from JS? Port it to JS, and your problem's solved. > How do you update a view when an element changes? It SHOULD just be as simple as calling your render() method? If your rendering code is incapable of not fucking this up, then it's your own fault. At the end of the day - Backbone is not there to hold your hand. If you can't figure the above problems out on your own, then Backbone is probably not for you. Backbone is even agnostic about how exactly you draw your views onto the page. Want to stick a shit-ton of logic in your template? Fine - but leave Backbone out of it - that's between you and your templating engine! Backbone gives you a solid foundation. Everything else is just arms and legs.
- rjzzleep 14y agowhen I realized that in the end backbone is just javascript and suffers from the same inheritence problems due to its crappy prototype object model. And you manually have to deal with event disposal when destroying views in backbone. just google backbone ghost views, I realized maybe it wasn't the best thing for the job after all. edit: the top comment mentions mixins, good stuff https://github.com/jb55/bquery https://github.com/jb55/bquery but personally i can't wait until we get a proper replacement for javascript, like dart maybe.