Valio.fi deep dive #1: Understanding our JavaScript philosophy

In this first part of my series of postings on the Valio.fi project, I’ll discuss some design aspects of our use of JavaScript. We outlined these principles in the TechDays presentation, but the guidelines are worth repeating in print as well.

What drove us to this?

imageFirst, let us reiterate the project background and goals.

When the concept of the site was born, high-fidelity user interface and visual appeal were high on the priority list. As you can see by browsing the site, particularly recipe search and articles, a hefty amount of work has been done to make the content look good. This includes contributions from artists, copywriters and photographers.

Once we had all this good-looking content, the challenge moved on to the viewing experience: How can we make it as enjoyable as possible for the user to browse the content? There had to be that certain feeling of abundance, and some of that comes from speed: new content has to be available so fast you think you can never consume it all.

But it wasn’t just viewing the content, it was also about entering it. For example, the recipe editor. Few home cooks have written down exact instructions on how to prepare the dishes they have invented. Sure, many write down the ingredients, but it’s a real effort to produce a concise set of instructions, in followable order, on how to reproduce the dish.

What kind of user interface would provide a reasonable approach to this? A set of text boxes would work, but be very clumsy in terms of reordering entered content. A textarea might be acceptable, but then dividing the instructions into clearly printable steps would involve splitting on line feeds or other semi-technical tricks, likely to mislead the user or produce unwanted results.

Client-side scripting shouldn’t be your first option

Both examples above added up to this: We wanted faster search-based browsing, which called for a client-side implementation. And we wanted drag-and-drop rearrangeability for recipe entry, as other options would simply have been too unusable.

After all the debate, there was a valid case for a JS-driven user interface. It wasn’t our first idea, nor was it an obvious choice to make. But in the end we did make that choice, and again a few more times along the way. Here are some of the aspects that affected our decisions:

  • Why do we want this? (see above)
  • Would it be possible to implement a reasonably usable non-JavaScript version?
  • If yes, would it involve a reasonable amount of work compared to the user benefit?
  • What proportion of users would suffer from the lack of JavaScript support?

Different cases, different reasons

I’ll present a few use cases for JavaScript on the site and try to give an idea on the arguments behind the decisions.

image

1) Features where JavaScript support is completely optional, just providing a better UI

For example, login to the site. The login function is available in the footer bar – if you don’t have JavaScript, the login function just acts as a link to a login page with a standard HTML form. If JS is enabled, it renders a “toast” window, allowing you to log in within the context of the page.

This kind of use of JavaScript is trivial to defend: it harms nobody, so the only real effect is the effort of writing and maintaining it (and testing the non-JS version, which tends to be forgotten). The vast majority of the site’s JavaScript usage falls under this category; little tricks to make the site look better and work smoother.

2) Features where a reasonable JavaScriptless implementation is not doable

The recipe editor is a prime example here. While it would be possible to conceive a UI that would work without JavaScript, it would be a stretch to call it usable. The recipe editor requires a lot of complex data input and fairly sophisticated input guidance. For example, we know the available units of an ingredient only after the ingredient has been selected. The selection list is long enough to make <select> population  quite unwieldy (not to mention the UI of the selection itself!).

imageWhile there definitely are quite a few users without JavaScript support, what percentage of them would be likely to use JavaScriptless user agents to add recipes? We deemed this portion of users small enough to ignore. Sounds harsh, but it is, ultimately, a business decision.

Many projects fear these decisions, and thus paralyze themselves with JS improvements: “if we cannot build a complete, perfect graceful degradation story, we can’t use JavaScript at all”.

3) Features where the JavaScriptless implementation is vastly simpler in terms of features

imageSearches are the most prominent example here. We provide a decent search without JavaScript, but it’s far from the visual glory of the JS version. It is not even functionally equivalent. For example, the JS version allows multiple search criteria from the same category (for example, you could select to search for recipes with meat AND cheese), while the pure HTML version only enables searching by one option in each category.

Such restrictions were not always technically necessary. We could have created the search interface with lots of multi-select controls or massive checkbox groups, and thus replicate the user experience. However, we often found the simpler option more usable. For example, without JavaScript, we could not show real-time numbers of matches for each filter. Thus, the user would essentially be searching blindly, perhaps ending with zero results more often than desired.

4) Features where we just didn’t want to bother with the scriptless implementation

image

Finally, there are the features which could have been implemented without scripting but were not – usually simply because we didn’t have the time or considered something else more important. Perhaps the most visible example of this was the recipe scaling feature, allowing you to change the number of portions for any recipe.

Superficially, it’s just two buttons that scale the recipe up or down. Behind the scenes, a whole lot of things happen when scaling. We use a JSON request to get the scaled recipe ingredients from the backend and then render it on the page using jQuery templating.

We could relatively easily add an HTTP GET based approach to scaling, providing links for +/- and then using querystring arguments for conveying the portion count. That might be something we’re looking at later on.

TANSTAAFL

All the sweetness from JavaScript doesn’t come without it problems, though. In exchange for bypassing some of the HTML basic form controls, we hit the following issues:

  • Accessibility degradation; impactwise ranging from mild (drag and drop without a mouse?) to severe (you just cannot scale a recipe without JavaScript support)
  • More code means more bugs; to provide a JavaScript-based UI with pure HTML fallback often means coding some things almost twice.
  • Increased complexity in terms of testing; it’s very difficult to get all the happy and unhappy paths tested, both for JS and HTML.
  • Increased attack surface from a security standpoint; while JavaScript itself rarely presents a security hazard, the additional APIs must also be checked for security issues, DoS opportunities and whatnot.
  • Considerably higher skill demands for team members; few backend developers understand the requirements for a decent JavaScript API, and while learnable on the go, it is expensive.

All in all, there are quite a few hurdles that need to be considered. Accessibility is a very relevant and real question, but it’s a business one. We wouldn’t have that problem in an ideal world, but since few projects have the resources to actually deliver fully usable pure-HTML experiences, most will practically have to find a compromise.

Unacceptable reasons for dissing JavaScript

While at it, I want to mention a couple of common reasons I hear for not using client-based technology.

  • “We can’t make it work the same for everybody” – probably true, but it’s also a cop out. Check with your business owner if that’s really what you need to do.
  • “We can’t make it work the same across all the browsers” – partially true, but if your understanding comes from times before jQuery et al., do refresh yourself. Getting CSS layout to work across browsers is much harder.
  • “JavaScript is not a proper programming language” – this is a colored statement coming from somebody with a limited definition of “proper”, typically involving static typing and class-based inheritance. Rest assured, the expressiveness of JavaScript will not be the limiting factor in your project.
  • “JavaScript doesn’t perform well enough” – True in a very specific sense, but an insufficient reason for complete dismissal of client-side scripting. There are scenarios where scripting performance can kill your site. Large DOM manipulations in particular can be a headache on older browsers. You need to test, test and test. But with some work and skill, you can do a lot even with IE 6 – and most uses of JavaScript will encounter no performance issues whatsoever.

Conclusion

I want to end the story with a concluding note: There is a lot of power in JavaScript. As usual, not everything works – or is easy to do. But if you are building a web solution where the user experience matters, you will be doing yourself a disservice if you didn’t even think about the possibilities provided by client-side programming on the web.

For a larger project, you would do well to devise a consistent, premeditated decision making framework for evaluating your JavaScript scenarios. Each instance of JavaScript use should provide reasonable benefit to offset the technical cost and possible accessibility issues. With that design-time check in place, client-side scripting can improve your site drastically.

April 18, 2011 · Jouni Heikniemi · 2 Comments
Tags: ,  · Posted in: Web

2 Responses

  1. Jukka Puranen - April 19, 2011

    Great post and also the presentation at techdays was excelent. I was impressed in the way this project was executed. It's a shame you rarely see such "prim and proper" excecution in Finland, or so it seems to me at least.

    Also your remark about "subpar javascript skills of backend developers" hit its mark and set me on path of seriously improving my javascript skills. :-D

    Anyways, was it so that the views for this site are not done with any asp.net MVC view engine?

    I faintly recall you mentioning that since the frontend is completely detached from the backend the customer can use any technology they want to modify the outlook of the site.

  2. Jouni Heikniemi - April 19, 2011

    Jukka: Thanks for the kind words, glad to hear you got some learning kicks out of our talk :-)

    About the views: We use the Razor view engine in the solution; Razor ships with ASP.NET MVC 3.

    But as you recall, we also support building customized front-end applications for campaigns and similar situations. The custom fronts can either have no view engine whatsoever (using just pure HTML) or even have a backend of their own through iframing and similar techniques. In the latter case, one could use e.g. PHP to extend the site, and of course, we impose no limitations on the underlying implementation. You could use echo statements, portlets or a templating engine just as you desire.

    I will blog about this custom front-end app model in more detail at some point. For an example running right now, check out the Kotiruoka competition on the site: http://www.valio.fi/kotiruoka/. That one has absolutely zero lines of dedicated back-end code.

Leave a Reply