The following talk was from the September 26, 2013 SoMA Tech Talk event hosted at Thumbtack.
Chris Mueller – Migration Patterns from Backbone to AngularJS
00:12 Chris Mueller: Yeah, thanks for coming. So we’ve been using a lot of Backbone here, and about six months ago decided to try Angular. It turns out Angular was really awesome and made our development really, really fast. So we’ve learned a few things along the way, migrating between Backbone and Angular. So I tried to distill those into a few patterns, those learnings into a few patterns. So these are the things I want to talk about; HTML. So Angular has this concept of HTML, is the HTML, which is really cool. So we’ll get into that. Zach did a lot of talking about data binding, which was awesome. I’ll mention that briefly. Angular’s concept of models is just JSON generally. It turns out it’s really great. I came up with this phrase “micro-interactions”; I’ll tell you about that. And then, I think Angular is also just great for collaborating within a large team. So I’m gonna talk about that too.
01:16 CM: So the little case study that I want to use is this application called Shrink, and so Shrink is something we have internally that notifies us of when things go terribly wrong. So it’s an alerting utility. Just giving you this context, you know, where the examples come from later. So the idea is that if something terribly wrong happens on the website, we trigger an alert in Shrink, and Shrink is this little API, right, and it’s got a database of things that have gone wrong, and Shrink then says, “Hey, something went wrong,” and it starts pestering everyone on the engineering team that something went wrong, and yells at us until we fix it. Turns out it’s really annoying to be pestered all the time, so there’s also this concept of silencing an alert. It’s kind of like hitting ‘snooze’ on your alarm clock for a little while. So we can silence things for a few minutes or a few hours or sometimes a few weeks if it turns out that’s relevant.
02:14 CM: You can also assign someone to a particular alert. So if Steve broke something, I can assign him to fix it. And when he fixes it, he can click ‘fix’. So there’s… We have two interfaces to this whole system right now. One is IRC, and the other one is the web interphase. So the web interphase was in Backbone… Looks like this; pretty simple. Just basically shows you the alerts that are currently firing. If there’s a stack trace like here, it’ll show you the relevant stack trace. Great. So that’s a little bit about Shrink. We’ll talk more about it.
03:51 CM: If you are writing stuff like this, Laconic is a great library; highly recommended. So afterwards, this is very dim and very small, but you can see that the HTML has expanded greatly. And so now when you read the HTML document, you know exactly what’s going on in the HTML. It’s really great. So here’s a little zoom in; looks something like this. So you see at the very beginning, we saw that ul class was alerts. Same thing we had before, but now inside, there’s an ngRepeat directive, right? So now we’re starting to repeat over all of the currently firing alerts and outputting information that’s relevant about them, like their title in the stack trace and maybe an action to click them on this ngClick. Okay.
04:36 CM: So another great thing about migrating from Angular to… To Angular from Backbone, is that you get rid of all of this… Yeah, you get rid of this exactly, yeah. You don’t have to worry about this anymore, which it turns out is really great. If you’ve written a lot of Underscore, a lot of Backbone, you’re used to calling dot bind or dot bindAll. And you write a lot of that, and you write a lot of dot on. So you write a code that looks like this. This is the old Backbone from Shrink. So you can see in the initialize, we’re setting up some bindings here, doing the bindAll trick to handle this.
05:22 CM: We’re looking at just sort of the collection of alerts. When it’s changed, we’re re-rendering the entire list of alerts. For better or for worse, we’re re-rendering all of it. And then, if there’s some sort of error, we handle that nicely as well. So of course, afterwards, you don’t have to worry about all that. As Zach said, you can just kind of write your HTML, and let Angular handle the data binding for you. It’s really great. So the HTTP GET in this case, which is what fetches new alerts from the server, is going to trigger this digest cycle. So that whenever the data changes, the interface will change. So, we can use just the data-binding syntax with braces. So, another great thing about Angular is that we found we don’t really need all of Backbone’s heavy-weight model layer; that raw JSON is pretty good at representing data. And then, you can do all the manipulations you need in the controller layer or the filter layer.
06:30 CM: So, one of the other unfortunate things about Backbone, in my opinion, is that Backbone has AJAX and HTTP deeply embedded into the concept of a model and a collection. That makes it a little harder to test. It kind of gets away from the separation of concerns that I think Angular really benefits from; dependency injection, that sort of thing. And then you end up doing a lot of this kind of stuff or like this fix or silence. These are methods on the model, the alert model. So if you wanna fix an alert, the old Backbone class had this dot FIX on it. Well, dot FIX would issue an HTTP call to the server to say, “Hey, fix the thing.” So, it’s using $.ajax. So, you have all this like, implicit dependencies on HTTP and AJAX deep in your model. It’s not great. Angular takes HTTP out of the model. HTTP has its own service, and then if you wanna update a model, you just issue HTTP calls and then rewrite your JSON. It’s a lot better. And you get away from these kind of messy methods that sort of glue onto your models.
07:53 CM: So, I’m not totally sure about this, the bottom point on the slide, but it does seem like traditional MVC as it were, is kind of this heavy-weight model approach, and I think that there’s stuff beyond like traditional MVC. Like some people talk about this move model, some people talk about command patterns, and I think Angular is kind of introducing a new paradigm here as well, which is a little different than traditional MVC, and it’s good.
08:21 CM: Okay, here’s another example of cruft that accumulated on to model layer. So, like the stack trace, you wanna like render it nicely and figure out where line breaks are and all this kind of stuff. So, we had a method on the model that was to do all that. But it turns out, that’s really the responsibility of the view layer because only the view really cares about what it looks like, right? So, it’s better to build that as a filter. Same thing with date-related stuff. So, why not just give a date object or a timestamp [08:54] ____ to the view, like to a filter, and have it figure out how it should be rendered in the current locale. So, it turns out we didn’t need all of this stuff that was on the model layer, generally. We just needed JSON, and the rest, we can do in the view and the controller layer. So that’s great.
09:17 CM: So, yeah, this micro-interactions… I’m not really sure the best way to talk about these, but I was thinking about it, and like, you end up when you’re building a sort of complex interface, you have all these little bits of the interface that are sort of changing, kind of temporarily in response to user needs, right? So, in the Shrink interface for example, this interface is collapsed, right, the 10-minute, one-day, one-hour, and one-week, and three-hour… That’s strange, three hours is later?
09:45 CM: Well, anyway, that’s usually collapsed, and when you click the bell, that opens up, and then you can choose what amount of time you want to silence this for. So, that opening and collapsing of a menu is a fairly common paradigm, right? We’re doing this kind of stuff all the time. So, I’m calling these kinds of things micro-interactions. So, the way that it’s often done in jQuery land or Backbone land is that you have something that looks like this. This would be on the view layer, you might respond to a click event, the event will be passed into this function, we prevent the default click from happening, and then we look for the right part of the DOM to manipulate and maybe trigger a class of some kind. So, the problem with this is now, the true state of micro-interaction is in the DOM, right?
10:39 CM: The only way to know the current state of this menu is to look for this class name open in the DOM which kind of defeats the whole purpose of having a model. So, that kind of sucks. So then, if you wanna do this properly in Backbone, what you have to do is create models for every little micro-interaction that you have to represent the current state of that interaction which is just really heavyweight if you’ve written a lot of Backbone. It’s a lot of code. Thankfully, Angular makes this really trivial to do, right? So, if you’re using some sort of directive or, say, an ngRepeat or something with child scope, you can just do things locally that don’t bubble up to parent scopes and maintain the state of the world and the model where it belongs. So, here, this is very trivial, right?
11:32 CM: NgClick triggers open to be the opposite of what it was before. So now, the scope, this local scope, assuming this is an ngRepeat or something like this, has this open, and then we can just trigger a class open on the parent ally here. The great thing about this is then if some other part of the system wants to know the state of this little micro-interaction, they can just look at the scope, right? So, if we wanna trigger a different class in some other part of this view, that becomes very easy. So I think Angular makes this… It makes it easier to do this the right way which means that you end up writing better code and more maintainable code. Yeah, so I think I kind of said all of this stuff, but directives do a great job of abstracting this away, right? Directives have isolate scope, so you can pull all this into one place without worrying about the model layer sort of leaking out into other parts of the application. Yeah, so that’s all good.
13:25 CM: Great, so I think… Yeah, these are the five points I wanted to talk about. And so with Shrink… I re-wrote Shrink recently and this is the diff of what happens.
13:41 CM: So it’s a lot of red.
13:44 CM: This is only… Shrink’s like 500, 600 lines total in Backbone, and now it’s about 200 lines. So Angular has been great for us. So yeah, we’ll save all the questions till the end, and I think Ari is up next, yeah? So, thanks guys.