00:00:24.690
I'd like to introduce myself a little bit first. My name is Sarah Mei, and I am a JavaScript and Ruby developer at Pivotal Labs in San Francisco. I've been at Pivotal Labs for about two years.
00:00:31.000
Pivotal is a consulting company, which means that I see a lot of different projects coming through. Before I was at Pivotal, I could spend a year, a year and a half on one project, and now my average project lasts about two months. In the last year, I've had five different projects using Backbone, one using Ember.js, and two that didn't use anything at all.
00:00:44.170
So I've seen a lot of different ways that Backbone is used. Backbone is a lightweight framework, which is both a blessing and a curse. It makes it different from Rails, which is very opinionated; there's a right place and a wrong place to put your code. One of the advantages of that is that you, as a Rails developer, can go from one Rails app to the next and have some confidence about where the code is going to be.
00:01:08.590
However, Backbone is not that way. Every Backbone project I've been involved with has completely different code, part of which is due to the fact that Backbone is fairly new technology. We haven't established a lot of well-established patterns for using it, and part of it is that Ruby developers in general aren't very well-versed in JavaScript, myself included.
00:01:36.579
What I'm going to cover today is a bit about what Backbone is, a little about the history of the relationship between JavaScript and Rails, and then we're going to look at some differences in terminology, what Backbone offers, and I'll present two different patterns that I've seen for using Backbone in real apps. I will also be publishing these slides along with the annotated source code later this week, and you can find that on Twitter, so don't worry about taking exhaustive notes.
00:01:54.610
To start, I’d like to conduct a little poll: How many people have worked on a Rails app that used Backbone.js? (A good portion of the room raised their hands.) How many people are here just to find out what Backbone is? (Seems like a lot of the same hands got raised, which is interesting.) And how many of you are here to find out whether your patterns of Backbone usage look anything like mine? (You see the same people keep raising their hands.)
00:02:19.690
So, let's start with a bit about what Backbone is. It is not an MVC framework for JavaScript, although you will see a lot of people refer to it that way and it gets lumped in with many other frameworks that follow a more traditional MVC structure. This can be very confusing for us as Rails developers because the components of the MVC—Model, View, and Controller—are different from what we think of in Rails.
00:02:34.049
So, let's put MVC aside for a moment and think of Backbone as a set of compartments where you can organize different types of code. Unfortunately, the names of the compartments in Backbone and the names in Rails are similar but don't serve the same function, which can add to the confusion.
00:02:52.229
The first thing to know is that Backbone doesn’t have anything called controllers, which is one reason why it’s not an MVC framework—there's no 'C' in Backbone's 'MVC'. However, it does have Models, Templates, and Views. In Rails, we have Models, Views, and Controllers. Before we dive into this comparison of terminology, it's important to discuss why you would want to bridge the gap between these two frameworks and understand two different frameworks if you’re already familiar with one.
00:03:17.299
The basic idea is better organization of your JavaScript code. I want to unpack that a bit and discuss how we arrived at the point where we need a framework to sort this out. Let's look at the evolution of our relationship with JavaScript which also reflects my own experiences as a JavaScript developer working with Rails. I think many developers go through similar phases.
00:03:59.980
The first phase is the 'No JavaScript' phase. This is where you use the JavaScript helpers that Rails provides. When I first arrived at Rails in 2006 after coming from a J2EE background, I found the JavaScript helpers quite amazing and almost magical! I could write Ruby, and it would generate JavaScript seamlessly. For example, if you include a specific tag in your Rails view, you would get a piece of rendered HTML in your form, like the unobtrusive Rails 3 version that adds AJAX functionality to form submissions.
00:04:32.460
The magic really kicked in when you could create a link that would fetch data from the server and update part of your page without a full refresh. This approach works well for simple interactions in many apps and can be sufficient in many cases. However, to be honest, I tend to think of Rails helpers like scaffolding; great for quick setups but not something I'd implement in a real app. We’ve reached a point where JavaScript needs to be a first-class citizen in our web applications.
00:05:10.940
This evolution is largely driven by the 'Web 2.0' phenomenon, which, among other things, increased demands for interactivity that Rails JavaScript helpers can't easily provide. For instance, when you want to update two different DOM elements with different content upon a single request, chances are you'd need to begin writing actual JavaScript. When you reach that point, it’s often easier to start using jQuery directly.
00:05:36.990
This brings us to phase two: the 'jQuery Explosion' phase. Here, you convert your Rails helper calls into actual JavaScript. This 'explosion' creates a situation where the top of your views is filled with jQuery calls, plugin invocations, and AJAX requests, leading to a cluttered and unwieldy structure.
00:05:56.560
As you accumulate more AJAX calls, your views become messier and harder to maintain or test. This code becomes difficult to manage, especially when testing, because you’re usually forced to conduct slow integration tests to verify your JavaScript functionality.
00:06:18.750
This brings us to phase three: the evolution towards using page objects. In this pattern, instead of having all your functions scattered at the top of each view, you organize your JavaScript into reusable, unit-testable functions contained within a JavaScript object relevant to a specific page. For example, this means creating a page object that encapsulates the previously scattered JavaScript into a tidy, adaptable unit.
00:06:48.840
As your application grows, you might split the page class into subcomponents. This reorganization allows for each component to manage its own behavior and state, resulting in a much cleaner architecture—easier testing and improved readability as well.
00:07:05.090
However, as your product managers request increasingly dynamic user experiences, such as instant updates to the shopping cart or related product information displayed without refreshes, you'll realize that this pattern has its limitations. To address this, many teams begin considering client-side rendering using frameworks like Handlebars or Mustache.
00:07:34.680
Client-side rendering introduces its own complications, such as the need for renewed knowledge about when updates should occur. As your events multiply in complexity—especially in a nested structure—you may find that it becomes cumbersome to manage these interactions.
00:08:07.159
You might realize you need an event system to properly manage inter-component communications. Additionally, developers start to wish for a mechanism to synchronize model objects between the server and client as well.
00:08:14.670
Up until this point, you tend to write repetitive Ajax calls for CRUD operations against your RESTful API. If there’s an increase in interactivity requested by product owners, you’ll be pushed to look for more structure to hold everything together.
00:08:48.799
The evolution toward frameworks like Backbone arises from these complications. There are many frameworks available that attempt to solve these issues—each with its own approach. Personally, I think that as developers, we've collectively reached the same JavaScript wall, and we're finding various solutions to break through.
00:09:14.930
Backbone provides a decent balance through semi-automatic model mirroring, which we will explain more later. It accesses concepts of models and collections akin to Rails' models and gives you views that handle DOM events without traditional MVC separation.
00:09:33.960
It's essential to understand these parallels and differences, as this can get quite nuanced. While Backbone mimics some Rails functionalities, the definitions of components can diverge widely. A Backbone view is more akin to a controller—it controls a specific part of the DOM and responds to user actions.
00:09:50.810
Most of the time, when you’re implementing Backbone templates, it’s less about just rendering HTML and far more about orchestrating a full package of DOM interaction—event handling and lifecycle management.
00:10:07.230
Perhaps part of the challenge is that many Backbone docs cater to seasoned JavaScript developers who can neglect the Rails newcomers. As a Rails-oriented speaker, my aim is to bridge that divide and clarify how JavaScript frameworks function in the context of a Rails environment.
00:10:37.470
So, let’s take a moment to breathe and reset here. We've talked about how we arrived at a place where we need robust frameworks and when you might want to employ one.
00:10:48.139
Now, I want to illustrate how Rails apps I’ve witnessed successfully integrated Backbone and share two distinctive patterns of its application.
00:10:58.340
The first one pertains to Greenfield applications, which is a concept I frequently encounter in many new Rails projects. Here, Rails typically functions primarily as an API server, meaning that we often render everything client-side, relying significantly on JavaScript for the user interface.
00:11:20.640
This approach can be significantly labor-intensive compared to server-side rendering of HTML pages, as you must deliver rich interfaces entirely through API calls. Nonetheless, we've observed numerous clients who want to offer a single responsive site alongside diverse native mobile applications.
00:11:43.190
When executing this hybrid approach, it becomes clear that most of your back-end logic can remain unchanged. An interactive JavaScript client and mobile apps typically share several data requirements. Consequently, employing a RESTful API serving up JSON data is usually sufficient for both.
00:12:03.444
For these projects, the view structure often remains simplistic. You may still need a Rails layout for the head and body, but within the body, you generally only require a defined div with an ID corresponding to your JavaScript application.
00:12:27.279
When looking at the Rails views, this is often all you see—a single controller that loads an index template into a layout, rendering very little actual view logic but merely passing data through the controller methods.
00:12:48.750
Instead of rendering views and sending strings back to the browser, you may simply return a JSON object. This approach could involve additional layering, such as decorators, to further enhance the JSON output being delivered.
00:13:10.020
Moving over to the JavaScript side, we still start with an 'app' object that acts as a simple initialization tool. This resides in its own file and acts as the primary JavaScript that initiates functionality on the view.
00:13:33.319
Usually, this object will encompass model constructors and view constructors, in addition to an initialize method. This way, when loading the application on a page, you'll have one shot to prepare the state you need for the initial render.
00:14:00.150
Typically, this includes creating a model instance representing the current user and establishing a view that governs the navigation bar, which is a common pattern for managing global state in the application.
00:14:20.179
As we delve deeper, I want to provide an overview of the user model, which extends from Backbone's model and performs essential functions, like determining the URL for the corresponding RESTful API endpoints.
00:14:45.380
This encapsulation saves from much of the boilerplate, making it easier to perform the standard CRUD operations through attribute manipulation. Any changes made to the user object can automatically determine the necessary network requests without additional coding overhead.
00:15:06.360
As the data flows from the server, it initializes the model attributes directly from the JSON. This process connects the power of Rails data management with Backbone dynamic models.
00:15:29.440
Next, we’ll look at the navigation bar view, which also extends from Backbone view. Knowing this makes it straightforward to create views that manage specific areas of the user interface.
00:15:52.140
The view can monitor DOM elements, listen for events, and execute specific functionality, such as rendering when a triggering action occurs. In our example, the navigation bar preparation would typically incorporate DOM events you'd be concerned about, along with event handlers linked to model or component updates.
00:16:10.350
Within the 'initialize' section, we often bind vital events pertaining to model changes, ensuring that updates drive any necessary re-renders, which keeps everything synchronized.
00:16:29.420
As we roll through the key rendering methods, you'll find that this modular approach allows us to efficiently manage updates without cluttering the application's code, using clear encapsulation and well-defined events.
00:16:52.289
Nevertheless, we need to consider how these components interact as different events may trigger various changes throughout your application. Handle these components with care, ensuring efficient interaction.
00:17:14.360
I want to emphasize that there is no universal approach to managing these transitions, which leads to many diverse strategies used for managing state across different views in Backbone.
00:17:37.059
The ideas tend to follow a common principle where you think about the views as designated representatives of different portions in your application’s interface. Each view orchestrates user interaction, processing the subsequent output through event-driven actions.
00:18:01.480
Ultimately, you’ll want to leverage Backbone's router for potential solutions to improve navigational handling. The router provides a solid foundation to help handle page changes via hash-based URLs.
00:18:23.029
After handling various designs through Backbone, I think it's essential to explore the potential pitfalls that arise when managing elements in a multidimensional state, both for capacity and maintainability.
00:18:43.179
Up until this point, we’ve journeyed through how Rails and Backbone often come together in distinct patterns as you migrate your application towards a more dynamic user interface experience.
00:19:07.040
I'd like to contrast this with existing applications that embody a more traditional server-side rendering approach, with the hope of introducing within that structure a more fluid client-side experience.
00:19:27.850
Essentially, if you find yourself facing pressure from product managers who wish to modernize an app while managing a predominantly server-side rendered app, consider how Backbone can complement that experience.
00:19:49.360
In these cases, you can start implementing Backbone as a layer on top of existing markup—this is where its lightweight design can significantly reduce friction during the transition towards a client-sider experience.
00:20:07.440
By strategically overlaying Backbone on existing templates, you can reduce extensive rewrites. Instead of reinventing the wheel entirely, you can incrementally improve and enhance interactivity.
00:20:27.680
I’ve had great success with apps using existing markup and appending Backbone functionality onto those components, which demonstrates the framework’s adaptability and ease of integration.
00:20:51.760
As we look to manage these pieces effectively, it's often easier to set the groundwork for future development by blending frameworks instead of outright discarding previous methods entirely.
00:21:12.390
Utilizing existing templates alongside newly developed Backbone views creates a seamless transition that enhances usability without compromising any performance or user engagement expectations.
00:21:32.780
This flexible infrastructure can guide your application in a measurable, manageable way as you grow, adapting to more complex interactivity requests from users and product management.
00:21:52.490
Ultimately, careful strategic planning can lead to a successful integration phase, where both server-side rendering and client-side JavaScript coexist, enriching the application.
00:22:12.950
In summary, Backbone is a strong choice during app refactor processes and evolutionary changes, particularly if you want to gradually incorporate more client-side dynamics without losing the essence of existing structures.
00:22:31.950
While I long experienced success with Backbone, I also recognize that many other frameworks come with distinct features that may better suit specific project requirements, such as Ember or Meteor.
00:22:48.970
However, my enthusiasm for using Backbone lies in its adaptability, especially for existing applications transitioning toward improved interactivity.
00:23:03.820
JavaScript frameworks increasingly gravitate toward offering more structured coding environments. Given my Rails background, I find this trend beneficial—it reflects a push toward improved development practices in the JavaScript domain.
00:23:19.820
There is still a notable need for flexibility during implementation. When factoring in existing architectures, accommodating team structure, and collaborating with less JavaScript-savvy developers can all contribute to how a project evolves while using Backbone.
00:23:34.870
Ultimately, these efforts combine to yield a modernized application, where careful attention to architecture and component interaction leads to success in product development timelines.
00:23:50.880
With that said, I’d like to open the floor for questions! Thank you very much for your attention and participation.