Decoupling Backbone Apps From WebSockets

I’ve been doing a lot of work with web sockets lately, in my Backbone applications. And I’ve fallen in to a pattern that I really like, where my Backbone application doesn’t actually know anything about web sockets. All it knows is that I’m using an event aggregator (like I always do) and that it publishes and subscribes to various events. The web sockets, then, sit off to the side. They’re decoupled from my actual application and I can replace the socket implementation without having to worry about my app’s functionality.

A Web Socket Library

Now you could write your own web sockets implementation. But I don’t recommend this. It’s notoriously difficult to get it to work across all of the browsers that you’ll have to support and frankly, not worth your time. Instead I’d recommend using an existing socket library. I’ve used these and can highly recommend all of them:

  • Socket.IO: The defacto standard for web sockets libraries. It primarily runs on NodeJS, but there are back-end servers for several other languages available as well. It falls back to long-polling, AJAX, and several other implementations that work in nearly every browser.
  • SignalR: A long-polling, web sockets, AJAX adaptive system for .NET. It’s Socket.IO for .NET.
  • Pusher: A third-party web sockets server. This is great for hosted sites (like Heroku) and for high scalability, fast. I learned how to use web sockets and converted a very chatty app from AJAX calls to PusherApp in less than an hour, a few years ago. There are libraries for PusherApp in many different development languages, like Ruby, .NET, Python, etc. I’ve only used the Ruby library, but it was dirt simple. They also have an article on working with Backbone and Pusher.

And yes, I realize that there are more libraries than just these. I’ve only used these, so they are the ones I’m mentioning. And I love all three of these web socket libraries. If I was forced to pick a favorite, it would be Socket.IO but only because I love working with NodeJS. But I do have an affinity for Pusher, since it’s the place that got me started with Websockets.

All three of these libraries are easy to use, and can easily be adapted to this example, though. Don’t feel like you’re going to make a wrong choice either. After all, the purpose of this article is to show you how the choice you’ve made doesn’t matter that much.

Decoupling Web Sockets

When I build apps with web sockets for communication, I don’t want my application to actually know anything about the sockets. I don’t want to mix that responsibility all throughout the code, for a number of reasons. If my need for sockets changes, for example, having many places to update the use of them would become a pain. If I want to get rid of sockets entirely or use another form of communication in addition to web sockets, having to go and add a bunch of extra code in all of the places that need the new communication would be awful. There’s also a high likelihood of code duplication, hidden problems and workflow, and hard to test code when we couple our web sockets implementation to our application code.

The simple solution that I’ve found for this is to abstract the web sockets away from our application. There are several ways to do this, one of which is to replace the Backbone.sync method in a Backbone app with something like Backbone.IOBind. This plugin replaces the sync method with a version that communicates over web sockets. That means your fetch, save and destroy methods would all move over web sockets instead of AJAX calls. If you’re using Socket.IO and you want to have your data access methods working this way, I recommend checking out Backbone.IOBind.

Another way to do this, though, is to move the web sockets code away from the application entirely. We can easily set up an adapter objects that translates between our web sockets implementation and our actual application.

A SocketAdapter

There are two basic things that you’ll need to build a socket adapter in the manner that I like. a web sockets setup and an event aggregator. Pick a web sockets library – any of them will do. For this example, I’ll be using Socket.IO. As for an event aggregator, I’ve got my default setup with Backbone.Marionette which provides one for us. Or you can pick any of a number of other pub/sub libraries for JavaScript.

Here’s the trick to decoupling the application code from the web sockets library: all of the events that the web socket publishes will be forwarded to the event aggregator, and your application will only pay attention to the event aggregator. For example:

  HIT = new Backbone.Marionette.Application();
  // ... other settings here




  // Socket.io Adapter
  // -----------------
  
  // This adapter forwards all socket.io events
  // to the application's event aggregator. The
  // intention of this is to decouple the specific
  // websockets implementation from the application's
  // use of it.

  var socket;

  var initialize = function() {
    socket = io.connect(HIT.socketUrl);

    socket.on("connect", function() {
      SocketAdapter.connected = true;
      HIT.vent.trigger("socket:connected");
    });

    socket.on("someData", function(data){
      HIT.vent.trigger("someData", data);
    });

    socket.on("disconnect", function() {
      SocketAdapter.connected = false;
      HIT.vent.trigger("socket:disconnected");
    });

    socket.on("error", function(err){
      console.log("ERROR: ", err);
    });

  };

  HIT.addInitializer(initialize);


  // Handle the event, start the app and the socket adapter

  HIT.vent.on("someData", function(data){
    alert("some data came through!");
  });

  HIT.start();

In this case we’re listening for an event called “someData” on the socket library. When that event fires, we’re just forwarding the event in to our application’s event aggregator. Our application listens for the necessary events from it’s event aggregator, and does it’s thing.

From there, you just extend the adapter to listen to your specific events, and continue to forward them on. In some cases, you can even create very generic socket event handlers so that you don’t have to constantly add new ones. In other cases, you might need to add a very specific event handler and have it do some manipulation of the data that it receives before forwarding it on to the application. No matter the case, though, you now have a single place in your application where this needs to happen.

Yes, it’s really that simple.

But, Why?

Decoupling and all that, of course. But really, it just makes our lives as developers easier. Having the web sockets and application code decoupled like this does add a little bit of overhead in both the run time execution of the code, and in the mental effort to keep track of all the moving parts. But the slicing of the individual parts down in to single responsibilities makes it easier to understand each part, and in some cases can make it easier to see the machine as a whole.

We’ve also made the choice of a web sockets library somewhat irrelevant. Did you pick Socket.IO and realize that you now need something hosted so that you can scale faster? No problem – just replace the socket adapter with an implementation that uses Pusher. Did you choose Pusher and now realize that you don’t want to pay for a hosted solution in your .NET system? No problem, just replace the Pusher implementation with SignalR.

When we’re testing our applications, we don’t have to worry about mocking or stubbing the web sockets, either. Rather than going through the pain of dealing with the web sockets API that we’ve chosen, we can simply fire off events from our application’s event aggregator and verify the results of firing those events. Removing the web sockets library from our tests will make the tests easier to work with, cleaner to read and write, and probably run a little faster too.

On that note, we can also simulate web sockets events in to our application. In a recent client project, for example, I had to simulate a list of devices with addresses receiving events from Socket.IO in my development environment. This project involved some hardware integration, and the only place where the hardware was available was a server in Germany. I didn’t have access to it here in Texas, except by deploying the app and running it there. So in my development environment, I used a setInterval to publish an event through my event aggregator every 1 second. The events I published contained valid but slightly random data to simulate what I would be receiving from the actual web sockets server. With this in place, I was able to write my app and deploy it to the real server with a fair amount of confidence. It worked nearly every time (except that time where we changed how the web sockets data was being pre-processed by our adapter).

Only One Of Many Options

There are likely a thousand or more ways that you can integrate a web sockets system in to your application. I’ve shown you how to do one of them and linked to another (Backbone.IOBind). But don’t think that you have to do it the way that I like to do it. This is my preference based on the style of event-driven architecture that I like to write. The main point that you should take away from this article is not that you can build an event aggregator adapter for web sockets, but that you should decouple your web sockets from your application in a manner that makes it easier to maintain and change both your application and the web sockets implementation, independently of each other.


Post Footer automatically generated by Add Post Footer Plugin for wordpress.

About Derick Bailey

Derick Bailey is an entrepreneur, problem solver (and creator? :P ), software developer, screecaster, writer, blogger, speaker and technology leader in central Texas (north of Austin). He runs SignalLeaf.com - the amazingly awesome podcast audio hosting service that everyone should be using, and WatchMeCode.net where he throws down the JavaScript gauntlets to get you up to speed. He has been a professional software developer since the late 90's, and has been writing code since the late 80's. Find me on twitter: @derickbailey, @mutedsolutions, @backbonejsclass Find me on the web: SignalLeaf, WatchMeCode, Kendo UI blog, MarionetteJS, My Github profile, On Google+.
This entry was posted in Backbone, Javascript, Marionette, Pusher, SignalR, Socket.IO, Web Sockets. Bookmark the permalink. Follow any comments here with the RSS feed for this post.
  • Marcus Efraimsson

    Sounds reasonable. I like it!

  • Johnny

    Great post!

  • Anonymous

    Behold the awesome backbone-fu that is Derick Bailey.

  • John Teague

    SignalR only supports websockets on Windows 8 / IIS 8 

    I only bring it up, because I’m not sure everyone understands that. I know it’s not important to the concepts you’re discussing. (in other words, sorry if it looks like I’m trolling)

    • http://mutedsolutions.com Derick Bailey

      oh, i thought it supported them all over the place. :P

      either way, the idea of the socketadapter class still works. i’ve done one project with signalr like this, and am about to start another that will work the same way :)

      • John Teague

        Right. It’s off-topic I know.  It’s not SignalR actually, but IIS.  IIS < 8.0 does not support Websockets.  The only I know to support websockets on windows 2008 is to run node in a separate process.  It works fine, but need to watch server reboots.

  • Wwwboy

    Derick, why do you use vent object to rise events?
    You can use Application to rise events – simply inherit Events to Application
    I use it in my projects – it’s shorter :)

    • http://mutedsolutions.com Derick Bailey

      shorter is irrelevant. clean separation of concerns is more important. my application objects have their own set of events and their own responsibilities.

      but if you want to do it that way, nothing stopping you :)

  • http://twitter.com/akashbad Akash Badshah

    Great article! I am thinking of using signalr and backbone for an asp .net backend. I am new to all of these, do you have any tips on ramping up quickly on these frameworks?

  • zivkovic_milan

    Great post, Derick, totally like it. thanks

  • Michael Fasani

    I’m currently working on a stock trading app and I would like to use Backbone for the presentation layer.

    The problem I have is that the connection either WebSockets or Ajax is being handled by a custom script within the data providers code so having a URL in my Backbone collection is not really possible.

    Their code offers an OnUpdate function that fires every time it receives new data, I am going to assume it’s similar to the above. It also has connection and disconnection events.

    Assuming the above still stands true, I can create custom events for connection, OnUpdate and disconnection which will fire inside the script given to me.

    I will clone the backbone events object and then pass that too my app and to their script and I should in theory be able to keep it as simple as a bunch of trigger and a listen events.

    I think this will work really well for me unless you have furthered changed your thinking on this subject??

  • dufia

    I love you