Coding the Angular Tutorial App in Backbone(blog.42floors.com) |
Coding the Angular Tutorial App in Backbone(blog.42floors.com) |
This is an extremely common (neccesary?) tradeoff. Think Rails vs. Sinatra or Django vs. Flask. Django gives you a great off-the-shelf backend that's perfectly suitable for most jobs. But I don't want to go under the hood to bend Django to fit an atypical project, and for those I'll use a minimal framework like Flask.
My issue with Angular is that I really want to avoid looking under the hood because the complexity is so high. Backbone is just a small, modular, well-documented library that invites you to look under the hood. If Angular doesn't fit my project, I'm happy to have Backbone in my toolkit, and I know the additional boilerplate up front will pay off down the road. Yes, it'll force me to think more up front about how to organize and architect my app, and that's not a bad thing.
My favorite part of Marionette is that it has opinions about things like model/view management -- so it avoids a lot of boilerplate -- but it can almost always be molded/tweaked to fit your specific needs (animations, lazy loading, views partially rendered on the server). It lets you 1) mix and match pieces build to work with Backbone (ModelBinder for declarative model-view bindings, Relational for client-side relations, etc.), 2) scale state change management up and down as appropriate for your app (via model changes, controller interactions, route events), and does not force you into a fully single-page architecture if you don't want it.
Anyway, I think Marionette is a pretty great way to write small, modular, readable code without sacrificing high-level abstractions.
Backbone is terribly devious in that it tricks you into thinking that it is unrestrictive and unopinionated. Backbone manages state with mutable models and model change callbacks, so Backbone's opinion naturally is that models and change callbacks are a good way to organize your application. "I want to write hundreds of callbacks to keep everything in sync" said no UI developer ever.
"I want to write a bunch of gross code to perform dirty checking of objects to keep everything in sync" said no UI developer ever.
That's the point of libraries and frameworks. They do the repetitive or "ugly" or "hard" things that we don't want to do over and over.
Except that this is in no way an equivalent comparison. With Backbone, you actually have to write the hundreds of callbacks in your application code.
Whereas with Angular, you attach a value to a scope, and declare it in a template. In that case, the framework actually does take care of the 'ugly' for you.
Backbone keeps the ugly in front of your face, it just gives you a slightly neater way to organize it (i.e. as compared to jQuery soup).
I can do that with a framework that doesn't presume the best path from 0-F. The reason I like Backbone is because it treats me like a developer who knows how to architect an application.
But CRUD is a solved problem that's easy to implement, and view / controller code ends up being the bulk of your application. I'd rather my framework give me a little help there.
CRUD is even kind of an anti-pattern, because it prevents you from doing relations in your relational database.
Please explain how doing CRUD operations -- which is, after all, what SQL INSERT, SELECT, UPDATE, and DELETE statements are -- prevents you from doing relations in your relational database. Because that's a seriously wierd claim.
I'm not sure I get this. How are the two things connected? i.e. why can't CRUD honour relations? (Django's admin does auto-CRUD and handles relationships moderately well - at least to one level of nesting)
I love angular as much as the next person, but comparing two frameworks by LoC does not do much to move the discussion along.
It's not worth a comparison.
[0] https://github.com/marionettejs/backbone.marionette/blob/mas...
[1] https://github.com/marionettejs/backbone.marionette/blob/mas...
[2] https://github.com/marionettejs/backbone.marionette/blob/mas...
I think another good comparison to make that is missing from both demo application stacks is testing. It becomes increasingly difficult to test backbone with the side effects of having jQuery selectors, html elements and general DOM operations directly in your view models. One of the great advantages of angular is it's attempt to make invert your thinking about dom binding compared to other frameworks. Meaning it tries to keep the DOM and the MVVM separated so there aren't unintended side effects if you add or change html node ids or classes. Backbone more tightly couples you to a specific html model and makes testing your javascript code complex and coupled to also looking for changes to the physical DOM during tests.
In the end, the more complex problems see to cause equal headaches in both frameworks, but at least angular give you less lines of headaches.
Lines of Javascript: 92
Lines of Javascript(without ember-data model definition): 63
I mean I don't want to spend time learning a framework that might be dead 2 years from now (remember prototype ?). I really don't see a fit for Angular in my practice. However I'm not sure if I'm just saying that because of pure ignorance. Most of my client side code is pretty much jquery (that I try to keep organized), and it works most of the time. Then I see people referring to that practice as "jquery soup" and I'm starting to think I'm doing it wrong.
A lot of the web apps I write consist of pages with ajax sprinkled here and there (where it makes sense). I think a framework like Ember, Angular or Backbone is an overkill in my case. I don't write SPAs, but then again I see people using it everywhere these days.
Honestly, for my scenario I feel that a framework such as Knockout or ReactJs is a lot more "fitting". I'm sure other devs have been where I am, I wonder what you guys think.
But people judge an app by its cover, so what can we do.
That said, lines of code is really the wrong metric to gauge the merits of the frameworks. Fewer lines of code may mean better abstractions, but it also may mean more 'magic'.
A metric that may be more useful would be to have one developer write half the project and have another finish and then compare the time they take to the time they take to do the same project with angular.
I see what you're getting at with "magic" abstractions, but it's like comparing Python and C. I don't know everything that happens under the hood in Python off the top of my head, but I also don't care. I could learn it if I needed to (e.g. needing to use the FFI, or if I find a framework bug). Not knowing is not the same as not being able to know.
I do agree that LOC for a _non trivial_ application is a reasonable measure, though I disagree that Angular:Backbone is Python:C.
[1]: Serious performance optimization is the exception here, but in building CRUD apps, this honestly did come up infrequently, and usually the right thing to do was to improve algorithmic complexity or fix slow DB queries, not fix python constructs that were unexpectedly slow.
[2]: I haven't spent much time with Angular specifically, but definitely remember this being difficult in other automatically bound frameworks, like Meteor in its initial release.
We could say that a Hello World code in Java is 5 times bigger than in Python, and both has it's pros and cons. Same thing happen with tools and frameworks.
LOC is certainly a useful metric in this case. It doesn't necessarily mean one framework is superior than the other but can and should be used when comparing frameworks.
If I had to choose between frameworks, tools or languages. LOC is not the reason why I would choose A or B. Another thing is comparing one of the following: support, active community, features, future improvements, documentation.
They are, but one of the things that makes Angular so powerful is that it kinda defines its own DSL. Most of your work may not even be in javascript, but in the enhanced HTML that Angular defines for you (and which you can expand by making more directives).
An example of this would be restating the DOM tagName on each view instantiation. This appeared to also be done with the className, which didn't appear to change (Although I admit I didn't look particularly hard).
There were some other areas that looked like they could be optimized by removing unnecessary glue. The render function in PhonesFilterView looks to be doing a lot of work to choose the selected option. Unless I'm reading it wrong, you could just pass in this.model.get('sortBy') to the JST and let it do the comparison to select the correct value. Quick value compare instead of a model compare.
I appreciate the work that goes into these types of comparisons, I'm still lead to believe that it shows more about how well you know a framework than it does about the framework itself.
Thanks for posting OP, it was an interesting exercise.
Your point is totally valid about some of the extra stuff I did. The one thing that irked me is that I added some lines because I didn't like the data structure, like the stuff in your example. In real life I would go change the data, but I felt like that might be slippery slope. For example if I changed the data for the phones show view I could have just done a loop over a 10 line template instead of the ridiculously long ~100 line template (although the Angular peeps could have also done the same thing).
In the end I decided to stick with the data provided by Angular and just massage it when necessary. It increased the line count and added complexity, but it made it feel like a Backbone app to me.
So it does take 240% more lines of code to do sort of the same thing as the angular tutorial, but the angular library is 1000% as big. If my math's correct.
(disclaimer: I like Angular, and for big projects like the one I've worked on, both backbone and angular, I really prefer angular. If bandwidth is a major concern though, and you know how big your app's going to end up, consider library size)
Each step I reduced the code size by 50-75%, particularly the boilerplate of tying user interaction events to updating the logical model in JS. Angular's automatic 2-way data binding was definitely the selling point for me on the framework.
I'll admit I don't really like Backbone much though.
Angular is probably easier for a lot of people though
Point being, having the code be in the library where it is stable, tested, documented, standard, etc is the whole point.
You've made three points which I can't see much fault with. Why the hate?
The code is very far from terrible. Go look at Marionette's source on github - you'll find it's extremely easy to understand and reason about. Now try and do the same with Angular or Ember...
2 years ago I jumped ship from KnockoutJS to AngularJS. Backbone was also quite hyped out around the same time. All three of them are still around and frankly speaking it wouldn't have been a problem for me if the one I picked died by now. The skills I learned in Knockout helped me quickly learn Angular.
Think of it this way, learning on its own, regardless of what you're learning is valuable. My suggesstion, take a day and examine whatever frameworks you've heard of and pick one and learn it.
Possibly the biggest advantage of Angular is what it does for code organization. With JQuery, you've got to organize it yourself, and while some things are easily organized, others can easily turn into a big mess.
Angular is very big on separation of concerns, modules, dependency injection, etc. Basically, what Angular does, is provide a lot of mature code organization concepts that have been common place on the server-side for ages, to browser-side code. Javascript has long been the domain of little ad-hoc scripts. Stuff like JQuery makes it easier to work with fairly standalone libraries, whereas Angular does for the browser what frameworks like Spring and Wicket did for the server.
Is it what you need? Depends on whether Spring and Wicket are what you need.
3 months ago I'd never touched any of them, at least not successfully. Then I got a project to build an app-like mobile website for my company on top of Drupal. I spent a few days trying to figure out how to fake it with jQuery and prefetching, all the while knowing that one of these frameworks was the better way to go. I spent a morning spinning up a couple of JSON feeds in Drupal and the afternoon learning enough Angular to get something to show up on the page, and I think it's fair to say that in the 2 months since that day my developmental worldview (and my productivity) has shifted considerably.
Regardless of how long Angular sticks around (though I suspect it'll be a little while), what I've learned from working with it nonstop for the last 2 months has definitely made me a better developer overall.
And each has their own strengths and unique opinions. My preference is Ember, but it's just that, a preference.
Another point is that with all those libraries, how do you sanely manage the security and quality of your application? With the exception of just a few - almost every Backbone add-on library I've tried is badly programmed (un-SOLID / weird JS / no tests), not documented enough, and unmaintained solo-projects that just so happen to be on GitHub.
As a slightly hyperbolic example, imagine comparing code that uses the filesystem with code that directly writes bytes to the disk - sure, it's probably only 5x more code but nobody would seriously entertain doing it...
I'm willing to bet that there's going to be a bug somewhere in that 800kb of code that is truly going to fuck up your day.
At least that 2.4x amount of code _could_ have more straight forward bugs.
Backbone is a library. You can use it or ignore it, combine it with other stuff, you call Backbone code and use its objects, and it does some limited but well-defined stuff. It's easy to combine with other libraries, and you don't have to use Backbone's feature everywhere if you don't want to.
Angular, on the other hand, is a framework. It shapes everything you do. It bootstraps your application for you, and calls your code when it needs your input. It imposes a totally different way of working and thinking on you. What it does for you is far bigger than what Backbone does for you. It doesn't play nice with libraries that haven't been written for use with Angular.
Really, the difference is like writing a basic Java program where you write the main() and you call some libraries; and using a webframework that handles tons of stuff for you and you just write the controllers, services and views.
Point [2] means, to use a different renderer you need to replace Marionette's internal renderer completely like it's a global (globals are bad).
I think you can get pretty far with batched REST, but I'd like to see some way to query graphs in an easier way.
[0] http://restcookbook.com/Basics/hateoas/
RESTful Web APIs (2013)[1] is a very, very good book about this stuff. The book has a mailing list with some good discussion about this stuff [2].
[1] http://www.amazon.com/RESTful-Web-APIs-Leonard-Richardson/dp... [2] https://groups.google.com/forum/?fromgroups=#!searchin/colle...
I'm still exploring this stuff myself so maybe I am wrong or misunderstanding you.