Photo by kennymatic
In this blog post, I’d like to share my thoughts about what’s different (the good and the not-so-good) in SPA’s and why as a web developer, you should care about it. Of course, YMMV, so I encourage you to share your opinions in the comments!
The world is changing fast. People’s behaviors change more rapidly and today we use increasingly more and more cloud-based apps, accessible from devices that aren’t necessarily opened with a web browser or native desktop apps. We expect lower response times, snappy, intuitive interfaces and near-100% availability.
How can we, as developers deliver that?
Well, there’s a rule that states, “use the right tool for the job.” I believe applying this rule to web-dev results in Single-Page, API-based applications.
We’ve all seen terrible rails code bases. Models coupled to views, views littered by conditionals, tons of JS glue code to stitch pieces of HTML together to form a user interface. It doesn’t have to be that way. There exists several techniques which help decoupling presentation from the domain: Decorators / View Objects for instance, encapsulate code which deals with presentation in another class.
This however, does not solve the underlying problem: The frontend (browser) and backend (rails) are radically different environments, and thus require different tools.
Backend is a simple pipeline: a request comes in, the application does something, and a response comes back. But frontend is event-driven: multiple things happen simultaneously, hovering, clicking, scrolling, loading etc. Frontend is a user interface, dynamic, adapting, changing. By spitting back HTML from a rails pipeline, a lot of hacks and ugly JS code is required to emulate the responsiveness.
Decoupling domain and presentation has many advantages too: the API that powers a web-application can be used for native mobile apps as well. Every successful product will need to enter the mobile market sooner or later, so you might as well be prepared for it. It results in snappier interactions so that the page doesn’t need to be reloaded in order to see the result of an action. Since the API transfers raw JSON data, the amount of traffic can be reduced and caching is also easier and more effective. The biggest difference, however, is in the quality of code.
Working on this kind of project was a peculiar experience for me. A lot of things suddenly felt right for a dynamic web app. I didn’t need so many hacks and glue code to pass HTML around. There were less bugs in js code. Front-end coding started to be pleasant!
How often do you test your rails controllers? What about views? Testing is hard because things are jammed together in the rails world. You can design your application around small components, with little dependencies and small responsibilities. The framework I used - marionette - encourages that. Rails? Not so much! Testing and maintenance become much easier.
On the rails side, controllers become smaller. All presentation-related code goes away. It’s a big deal conceptually, as you only have to care about how to consume and deliver JSON data. Combine that with other handy patterns (service objects, form objects) and you have a big win.
I started thinking more about designing applications well, rather than following hard-beaten rails-way. No more working around fits-it-all framework to achieve the goal.
The back button is a common trouble spot in SPAs. You need to make sure it works as expected (check if the framework can handle it for you). Moreover, in most cases, refreshing the page should bring up the same view (this applies to links shared with others too).
In hindsight, it was absolutely worth it. Once you’re up-to-speed with front-end skills, you can be just as productive as when you’re using an all-rails stack. Plus, your code is a lot better. When you’re working in a team, it’s great too, as people can focus on only one side of the application, delivering better results.
What was surprising was that the switch really helped me advance in other areas of web development. By having focusing on both frontend or backend simultaneously, I learned to code each one a little better. This was a big step for me, and since then, I’ve been motivated to learn as much as I can about frontend (the area I’ve had less experience with).
Note that I’ve only used one technology (backbone + marionette as you’ll see) to develop simple applications. It would be interesting to know if the set of advantages and disadvantages is perhaps particular for this technology (I think I’ll be trying angular in the future).
Marionette complements backbone beautifully, by adding useful components, module management, conventions, and composite architecture. That last element is most important: marionette applications consists of modules that form hierarchies, which in turn comprise the whole interface. It also features ways for modules to communicate with each other in different ways to avoid coupled, spaghetti code. And lastly, everything in marionette revolves around events which are emitted by entities (models), views and controllers, fitting nicely in the browser environment. If you have a backbone application and are looking to make it better, you can check out my blog post, "Marionette.js and Backbone - a perfect match?".
Some of these components we use so often, that we extracted them into one gem—simply include js_stack in your asset pipeline and you get all the goodness.
The benefits of SPAs that I’ve seen are enormous, and I encourage every rails developer who hasn’t looked into them yet to do so.
You can start by choosing a JS framework and implementing your test app with it. Try to make all of the controllers return JSON, and see how slim they become. If you’re feeling adventurous, try coding frontend and backend in different repositories. The context-switching will be painful at first, but eventually it’ll become natural and reinforce the focus on the decoupling of domain, API and user interface.
For a really hardcore challenge, try implementing the API in different web framework. Anything that spits out JSON is fine (I’ve been experimenting a lot with Scala and Play Framework, personally). This exercise will open your mind to different approaches to the problem, and ultimately, help you become a better developer.
What’s your story with Single-Page Applications? Maybe you had different experiences than I did. Let me know in the comments or on Twitter!