Doing it Differently

I was recently asked about the goals of the Fluid community and how Infusion relates to other frameworks out there. Here’s my response:

Fluid was formed as a open source community back in 2007 to make a long-term impact on the usability and accessibility of the web. From the start, our goal has been to:

  1. Share new design methods that empower users to be co-creators, not just passive consumers of user interfaces
  2. Devise new development tools for building software that can adapt to individuals
  3. Foster an open source community that welcomes and includes “the rest of us;” the designers, testers, and non-geeks who otherwise wouldn’t get involved in open source

From our experience building real applications over the years, it became clear that today’s software development idioms don’t support this vision of user interfaces that can be easily adapted, transformed, and reconfigured. The software industry’s design patterns and “received wisdom” more often than not result in expensive, brittle, and hard-to-maintain user interfaces that don’t match the needs, preferences, and creativity of users.

That’s where Infusion fits in. We need new tools, new patterns, and new techniques for writing software. They need to be context-aware, configurable, and very loosely coupled. Infusion is the Fluid community’s long-term effort to produce these next-generation tools. But here’s the thing: we also know that these are big, ambitious, and challenging goals. Goals that take time, thought, and effort to achieve. Unlike most other frameworks out there, we’re trying to:

  • Address the stuff that doesn’t get done, gets left to the end, or is relegated to inexperienced developers
  • Change the economics of software development, where costs grow exponentially as a system gets larger and features increase
  • Make software automatically and seamlessly adapt to the unique needs and preferences of each individual user without requiring developers to re-program the system each time.

You can’t solve problems like that by appealing to what people already know. And the status quo doesn’t cut it; the vast majority of software is inaccessible or chronically difficult to use today. So, unlike the other guys, we have to do things differently.

That means taking our time. That means prioritizing the hard, failure-prone work of devising new development idioms over marketing and flash. And it means working quietly on our vision, even if it’s not going to make us famous. But it will make a better experience for users.

That’s the mission of Fluid Infusion, and we’re making progress on it every day. It’s a practical mission, not just theoretical or experimental. Infusion is used in a growing collection of large production applications such as CollectionSpace, uPortal, OER Commons, and the Global Public Inclusive Infrastructure. In the hands of real users, we get the feedback we need to recognize what works and what doesn’t, ensuring that Infusion continues to get faster and better over time.

We’re deep in the midst of working on our next release, Infusion 1.5. It will feature huge improvements to the Inversion of Control (IoC) system, making it easier to develop context-aware user interfaces with a minimum of code. And it will also include a new Model Transformation system, helping developers to adapt to and interoperate with diverse data formats and schemas.

Last weekend, Anne Jonas and the Participatory Culture Foundation invited me to attend a working group about video and Open Educational Resources (OER) at the Open Video Conference 2011 in New York City. The meetings included a diverse group of OER creators, developers, instructional designers, and teachers who work with media and education on the web. Mainstream producers from NPR’s RadioLab and PBS Kids were also present, ensuring that the group reflected perspectives from beyond the immediate world of OER advocates.

Each afternoon, we discussed many of the central issues of video and OER: the challenges of teaching with video, licensing considerations for sharing video content, tools for creation and dissemination, and production techniques for supporting large-scale webcasting solutions. For me, it was particularly interesting to hear from instructors and designers who wanted to make video a two-way conversation, where students don’t just consume pre-baked content but are actively engaged in creating their own media along the way. This echoes our vision for the Floe Project, where everyone can be involved in the process of adapting, enhancing, and deriving content in different formats and modalities.

There was also a lot of enthusiasm for the potential to create layered, synchronized learning experiences using entirely open web technology such as HTML5 video, JavaScript, and synchronized media. RadioLab’s Hypermedia Audio Player, built with Popcorn.js, provided a lot of inspiration and food for thought. Platforms and tools were a big issue for everyone; we spent a lot of creative time our sharing ideas, goals, and requirements for new content delivery platforms optimized for learning, remixing, and adapting video on the web.

An Inclusive OER Design Workshop

On the second day, I facilitated an inclusive OER design workshop where participants designed their own open educational curriculum and platforms that are optimized to the needs and preferences of individual learners. We started by talking about our ideas and preconceptions of accessibility, ultimately re-framing disability and accessibility in terms of usability and design–the capacity for a software system to accommodate the needs of the user. In this model, we all experience disability in different contexts and environments. Well-designed, personalizable user interfaces can enable diverse users to engage with learning in a way that respects their own needs, preferences, cultural values, and learning styles.

After talking about our own experiences of accessibility in open educational resources, we broke up into smaller groups to design, as Betty Carter would sing, the “Who, What, Why, Where, When [and How]?” of our OER curriculum and platforms.

Who?
Each group was tasked with the creation of a unique user persona, complete with their own goals, preferences, and learning needs. We gave our learners names and personalities to bring them closer to the design process, ensuring that our solution was grounded uniquely in their needs.

When and Where?
Once the identity of our learners was established, the design teams were asked to consider the environment and context in which their learners learn. Is it at home late at night where sound might disrupt others? In a busy classroom in collaboration with other students? While traveling? Using an older computer, lower bandwidth, or slow mobile device?

How?
Each team was also asked to consider the teaching methods and content delivery platforms for their OER content. Is the course primarily online or in person? Does it involve independent learning or regular group participation? What learning levels is the content targeted towards? How are students assessed and graded, if at all?

Why and What?
With the learner’s context, environment, and goals in mind, each team fleshed out an open educational resource and the details of its delivery to the learner. The resulting designs were remarkably creative, thoughtful, and innovative. Here’s a quick summary:

  • The first group built in-class resources that were specifically tailored to the physical and attentional demands of young learners, combining traditional teaching with the use of mobile social networking and at-home exercises driven by freely available open educational resources.
  • The second group, designing for rural lifelong learners, created library-based personalized learning packages where OER content was compiled and remixed based on the learner’s unique interests. Delivery was available over the phone using text-to-speech conversion, or on a DVD shipped by mail.
  • The third group designed a flexible video delivery platform that took effective web design techniques such as graceful degradation and progressive enhancement to the next level. This platform made it easy for learners to view content in text, audio, and video formats, adapting to the capabilities of the user’s device. The platform could deliver sophisticated formats such as synchronized media and HTML5 video when used with more advanced devices, and would always fall back to a baseline of plain text and HTML on older devices and lower bandwidth. More importantly, it let the learner choose the experience they preferred most.

Notes, Slides, and Next Steps

Our notes from the design exercise are available on the Video and OER Workshop Etherpad. I’m really excited that many of the ideas we came up with at this workshop are directly useful to our work on Floe. In some cases, they directly echo the designs James has been working on for our upcoming Floe iterations.

It’s going to be exciting to take these ideas and explore them with real OERs and platforms, designing new ways to interact and learn with rich video on the web. I’d like to thank Anne and the PCF for inviting me to participate, and the rest of the attendees of the workshop for their creative and engaging ideas. I look forward to continued collaboration!

I created a handful of slides to guide the workshop process. They’re available on Slideshare in case you’d like to try a similar design activity at your own event; ping me if you need them in an alternative format. Let me know what you think!

Lots has changed since I last posted about Fluid’s keyboard accessibility plugins for jQuery. Here’s a quick summary of what’s new:

We’ve donated our tabindex normalization functions to jQuery, and they’re available directly in jQuery 1.3. Here’s an example of how to use them:


$().attr("tabindex"); // Gets the tabindex of the first matched element.
$().attr("tabindex", -1); // Sets the tabindex value of all elements in this jQuery instance.

This now works consistently across all browsers in the jQuery way! There are some other tabindex-related conveniences in jQuery UI 1.7 core, too:


$().focusable(); // Returns true if the first matched element is currently focusable.
$().tabbable(); // Returns true if the first matched element can be focused using the Tab/Shift-Tab keys.

Thanks so much to Scott Gonzalez for helping us land these patches in jQuery!

In my previous blog post about keyboard accessibility, I hinted at a comprehensive keyboard accessibility library that makes it easy to support desktop-style navigation with the keyboard. This plugin now ships as part of our Fluid Infusion application framework. It also works as a standalone jQuery plugin if you don’t need the rest of Infusion’s great features.

If you’re interested in this plugin, here are a few links to get you started:

As always, comments, feedback, and suggestions are welcome.

World, Meet Infusion 1.0

The Fluid community shipped Infusion 1.0 a couple of weeks ago. Before making a splash with announcements about the release, we wanted to take some time to revisit our documentation and sample code to be sure they are really useful and comprehensive. Recognizing that it’s not enough just to ship a bundle of code, we try to provide a whole package of resources for developers and designers who are using Infusion. That means comprehensive API pages, tutorials to get you started, and concepts documentation to give you insights into the philosophy and design patterns we’ve built into Infusion. With this new documentation in place, now’s the time to share the news of Infusion 1.0’s release more widely.

Fluid Infusion is an application framework for building usable and accessible user interfaces with JavaScript. Built on top of jQuery, Infusion takes a different approach to client-side development. At heart, Infusion is an open architecture designed to put you back in control of your application’s user experience. It includes a growing collection of UI components—reusable interactions that go deeper than most widgets. Created by a community of developers and interaction designers, Infusion components are built from the ground up with accessibility in mind. All of our designs can be used with assistive technologies, are fully controllable with the keyboard, and can be transformed to suit your users’ personal needs.

Knowing that you can’t bottle good design, our components can be easily adapted and reworked to suit your creativity. We give you the ability to tweak more than just a few stylesheets—you can totally change the markup of a component, change its behaviour, or toss your own workflow and logic into the mix.

What’s an Application Framework?

Most JavaScript libraries fit into two categories: foundation toolkits and application frameworks. Foundation toolkits are probably the most familiar, providing all the basic tools required to manipulate the DOM, manage events, and make Ajax calls in a reliable, cross-browser way. jQuery and Prototype are probably the best-known examples. Application frameworks, on the other hand, have emerged more recently. With more complex interactions and more application logic moving from the server to the client, there is a need for tools to help manage growing code bases. Application frameworks such as Sproutcore and Dojo + Dojox often provide features such as data binding, support for the Model-View-Controller pattern, and HTML template rendering.

Infusion puts a unique spin on things: it takes a declarative and event-driven approach, promoting less code and greater flexibility. Built on top of jQuery, everything about Infusion is open: its architecture, source code, and community. Our approach to Model-View-Controller is different, too. Models and views are at the heart of Infusion, while controller code is conspicuously absent. Unlike most MVC web frameworks, we think it’s the job of the framework to take care of the glue, leaving you to focus on the stuff that makes your application tick.

Infusion’s client-side template renderer is completely unobtrusive, allowing you to dynamically render your user interface without having to mix up bits of code with your HTML. No code in your templates means more reuse, less chance for mistakes, and an easier job when it comes time to do a redesign. We also include a lightweight CSS framework that lets you mix and match styles to create beautiful and themeable user interfaces, providing pre-baked layouts, widgets and text styles to get you started. We even give you plugins and framework APIs to help ease the burden of creating user interfaces with JavaScript that will be accessible to a wide range of users.

Interoperability is huge for Infusion. We play nice with other JavaScript code, avoiding the conflicts that are common when combining different JavaScript libraries. This makes Infusion particularly well suited to building mashups, portals, and content management systems.

Fluid and jQuery

We love jQuery. Infusion wouldn’t have been possible without the simplicity and clarity of jQuery’s approach. We also didn’t want to reinvent the wheel, so jQuery is everywhere in Infusion. Recognizing that some applications need more, we created Infusion to complement jQuery and other JavaScript libraries. It’s not an either/or situation—Infusion is very modular, so you can pick and choose the features you need based on the complexity of your project. Go ahead and combine ordinary jQuery code with Infusion, or use the whole framework whenever you need robust data binding, unobtrusive markup generation, and MVC-style designs.

Fluid’s culture of collaboration and interoperability run deep. To that end, we are active contributors to jQuery UI, sharing our accessibility experience and code to help make jQuery even better. Every time we come up with a new accessibility improvement, we share it back with jQuery so that the whole community can benefit.

What’s Next?

This is just the beginning. With Infusion 1.0 out the door, we’ve got lots of new features and improvements on deck. Indeed, the past few weeks have been packed with tweaks, bug fixes, and features destined for the Infusion 1.1 release. We’re planning to ship this next release in early June. Beyond that, we’ll continue to grow our components and add new features to the framework.

We’re also active users of Infusion, building applications and helping other open source communities with their user interfaces. To this end, the Fluid community is embarking on a new project called Fluid Engage, in collaboration with museums and art galleries. We’ll be working alongside curators, education departments, and exhibit designers to help create mobile-friendly open Web solutions that bring a new level of interactivity and visitor engagement to the museum. Infusion will be the backbone of this effort, and Engage will undoubtedly drive new components and framework features back into Infusion. Keep an eye out for things like new mobile themes for the Fluid Skinning System, designed to provide a natural user experience and to repurpose content for mobile devices like the iPhone. We’ll also be shipping a new visualization library for Infusion, providing Canvas-based solutions for drawing rich, vector-based images and animations. If any of these features interests you, don’t hesitate to drop us a line if you’d like to lend a hand.

Give it a Spin and Let Us Know

We’re really excited to share Infusion with everyone. With the 1.0 release, Infusion offers a stable and reliable solution for building rich user experiences, supported by a dedicated and friendly community. We’ve got a healthy roadmap moving forward, and a growing community of users. With accessibility and usability baked in from the start, we’ve got you covered. Download the release, check out the documentation, dive in, and let us know what you think!

In preparing for the final release of Fluid Infusion 0.6 (as of writing, we are at “Bug Parade” stage, leading to code freeze for Monday), we found ourselves with the disagreeable requirement to make some incompatible API changes to a part of the framework. Not only why we had to do this, but what we did about it, are interesting.

The code in question was kept in the file jquery-keyboard-a11y.js, and has historically always had a “special status”. This holds the parts of our framework which we have always considered closest to being contributed to the wider jQuery community (who we are always eager to develop productive relationships with), as a plugin. This code is treated specially, in that special care is made to keep it as self-contained as possible, and in particular to keep it free of dependence on our standard framework base file Fluid.js, to ease its adoption outside our community.

Unfortunately, as of release 1.5, the jQuery UI project included a file ui.selectabe.js, which registers a plugin named “selectable” with the same name as one in our set. This is interesting, since it highlights what has been considered a weakness in the jQuery plugin model - that it does not support any infrastructure for namespacing, to ensure that loosely cooperating teams can continue to work in parallel without fear of treading on each other’s names. This partly reflects its origins - the jQuery “chained filter” idiom is admirably matched for expressing queries and primitive operations on the DOM, and has produced a revolutionary condensation in the amount of code necessary to perform these “bread and butter” tasks. The plugin model is less well suited to an idiom of construction - that is, when one is using the DOM as a “springboard” for the construction of some more complex “component” or tree of objects that is going to spend some durable lifetime managing it. This can be seen from the oddity of some code which constructs say a dialog, or a sortable - where *is* the dialog in the following call?

 $("#dialog-root").dialog({bgiframe: true});

Any “object” actually referring to the dialog is implicit - the jQuery standard, is that operations on a jQuery object return another jQuery object (barring the exceptions that they are queries for primitive values such as attributes or counts) - therefore, to interact with this “dialog” we must continue to use same-named plugin calls targetted at the same DOM node (another interesting oddity is that the constructed object is not tied to the lifetime of the invoking jQuery object, but to the durability of the DOM nodes addressed by it - this is by necessity, since jQuery objects have no durability).

As a quick aside to those who have not been following these chain of blogs avidly, the Fluid framework design recommendation, since before the 0.5 release, was for “that-ism“, a code structuring device originally recommended by Douglas Crockford. I made an earlier blog posting explaining our decision, and there is also a wiki page on How to define a Unit. In brief, the benefits of that-ism include greater reliability and predictability of code - in the months since our decision we have been very happy with it, with many contributors commenting that it has made our codebase easier to understand by reading. That-ism also interacts nicely with Javascript’s natural “detached function” idiom - for example it is very easy to write a line such as

        that.viewEl.click(that.edit);

without having to worry about awkward “this” re-dispatching through event cycles etc - the edit method has natural access to its own, user-defined, and limited, context, without the need for “this juggling”. The durability of the returned that from a constructor is also matched to the created object - since it is the created object.

In any case - the jQuery model is marvellous for encoding primitive DOM operations drawn from a fixed set, slightly odd for construction, but poor for namespacing - having lost our namespace for selectable our only option is to move out of the path of the elephant. However, there is no procedure how we can guarantee that further of our names will not collide in the future, so now is an excellent opportunity to think of a scheme to make sure that our users will never again suffer this kind of API incompatibility.

Also, over the lifetime of Fluid, jQuery have firmed up their recommendations and published the following page of Guidelines for plugins - which we could do better at meeting. In particular, they recommend that each thing designated a “plugin” use exactly one name in the plugin namespace, in an attempt to head off the namespacing issues I’ve mentioned.

So, this problem is an excellent opportunity. Can we, at the same time, improve our conformance with jQuery code idioms, solve our namespacing issues permanently, and at the same time improve jquery-keyboard-a11y.js in its agreement with the that-ism enjoyed by the rest of the Fluid codebase?

It sounds impossible, but actually we can. After a lengthy brainstorming session, during which we proved that a “natural” namespacing idiom (that is, one which allows function names to be written out as Javascript symbols, rather than as string) is impossible to apply together with a “this-ist” dispatching model, we came up with the concept of the “that-ist bridge”. This is a small 20-line “machine” which now currently sits at the top of jquery-keyboard-a11y.js, and does the work of “exposing”, not only the contents of that file, but in fact the entire Fluid framework (where it has potentially conformant arguments) as a single, gigantic jQuery UI plugin named fluid, with exactly the recommended jQuery UI argument semantics.

Here is an example of our old syntax, showing invocation as a jQuery UI plugin named selectable:

$(".my-nodes").selectable({direction: $.a11y.orientation.HORIZONTAL});

“On the ground”, this has now been rewritten to a that-ist, Fluid-standard construction, used as follows:

fluid.selectable(".my-nodes", {direction: $.a11y.orientation.HORIZONTAL});

This is now housed in the global fluid namespace owned by us, permanently heading off the potential for collisions in the future. However, owing to the miracle of the “that-ist bridge” machine, this function is now also accessible, for free, using the jQuery UI plugin syntax as follows:

$(".my-nodes").fluid("selectable", {direction: $.a11y.orientation.HORIZONTAL});

Essentially any function, which accepts a “jQueryable” as its first argument (that is, anything which can legally construct a jQuery object when used as an argument to $, that is, selector strings, DOM nodes, or jQuery objects themselves) will be automatically adapted by the “that-ist Bridge” to be invocable using the single, global, Fluid jQuery UI plugin. The arguments are permuted - the first argument to the function becomes the jQuery object itself which the plugin is invoked on, and the symbol for the name of the function becomes a string, the first argument passed to the plugin. The remaining arguments to the function may be passed in an array as the 2nd plugin argument, or if there is a single argument it can be sent directly.

The treatment of return values is also somewhat interesting. The jQuery standard is that jQuery operations return further jQueries - except where they don’t. It seems that the general exceptions are those which return primitives - so this rule has been formalised in the bridge code. The return value of the underlying Fluid function is examined for its type. If it is a primitive, or “falsy” value, it is return directly. If it is some other kind of value, it is assumed that it is some kind of “Fluidic that”, and the value is hidden - instead, the original jQuery this is returned, to allow the standard jQuery selector chaining idiom to work. However, as a courtesy, the specific jQuery object returned is decorated with an extra method that() by which the originally returned value can be retrieved.

This has been a big win all round - since at the same time we have been able to improve conformance both with our own coding standards, as well as jQuery’s. And further, we have now been able to extend to the contents of this file the protection of our version management strategy, first brought in in Fluid 0.5 - by means of a namespacing trick, multiple versions of the Fluid framework may be included into the same document, whilst at the same time not only not colliding in namespace, but even remaining simultaneously addressible from the same scope by specially aware code. Truly necessity is the mother of invention. Or else, a loaf of bread.

Finding things quickly

There are many ways of finding things in the DOM - sometimes, many ways of evaluating apparently the same expression. For example, CSS and JQuery allow you to find elements by id, using an expression of the form

  var myElement=$("#my-element-id");

as well as the apparently equivalent expression

  var myElement=$("[id=my-element-id]");

However, these expressions are different in many ways. One advantage of the latter is that it is more resistant to escaping issues - for example, the colon character : is actually a valid part of an XML id, but is not correctly handled in many escaping situations. JQuery will not accept it as part of a # expression, but is fine in an id specification. This was the basis of our adoption of the latter for the fluid.jById utility.

However, these types of selectors are treated very differently within the nuts-and-bolds of the jQuery selector engine. # selectors have a very special status, which enables numerous shortcuts including the judicious use of document.getElementById where possible. id selectors are just standard attribute value filters, and will perform a full scan of the DOM.

document.getElementById("my-id") 8.5µs
$(document.getElementById("my-id")) 24µs
$("[id=my-id]“) 12ms

These tests were done on Firefox 2 in a rather busy document of about 40K of HTML.

Note that the cost of simply wrapping a DOM element in a jQuery object is small, but still noticeable.

Cost of guarding

This immediately suggests a policy of falling back on document.getElementById for quick lookups - however, jQuery, being a mature framework, is doing some work for us here in insulating us from an awkward IE bug where document.getElementById is sometimes returning an element which has a match on *name* rather than a match on *id*. This is a rather awkward tradeoff - putting in a “guard branch” to check that the required id is actually present as an attribute slows down access for everyone to 22µs, with the option to default back to the jQuery scan. However, do we really want a library with the contract “give me the element with this id, unless there is something screwy about your document, in which case give me the element 1000 times slower”. Probably the user will not thank you in this case, and would prefer to be given the chance to fix their markup.

Quick access to DOM nodes

This brings us back to why any of these issues are particularly interesting in the first place. I am currently working on reforming the Fluid Reorderer component, not only from a structural but also a performance point of view. The behaviour of the jQuery droppable library is not quite what we would want, both from a performance as well as a behavioural point of view (might be the subject of a separate blog posting), but in fixing it we are faced with some crucial design decisions about how to arrange data structures such that they can be used for very quick access - ordinarily this is not so important, but a DnD library is going to be queried on every mouse move event, and so even timings in microseconds can begin to mount up.

There are two main options -

i) store a “reverse lookup” cache of jQuery.data id numbers onto DOM nodes, and work with data structures storing jQuery.data ids, or
ii) synthesise short unique ids onto DOM nodes that do not have them, and work with data structures storing DOM ids.

Route i) runs the risk of keeping these caches up to date, and in particular avoiding leaks due to “expired” DOM nodes continuing to hang around in the cache - but it would probably be faster at runtime. Route ii) will be a little slower (incurs the costs we have been talking about so far, in invoking a document.getElementById equivalent on going to the DOM) but is definitely leak-safe, and might also help others navigate around the DOM.

What to do

These are hard kinds of calls to make, and involve a consideration and weighting of different kinds of issues. Currently a reasonable tradeoff for fluid.jById seems to be to go towards document.getElementById, but to put in a guard branch with a hard failure if a “name” attribute is picked up by mistake. For “live” storage during drag-and-drop, the jQuery data id cache option appears preferable, since we will already be storing various other data on drop targets in addition to what can be discovered in the DOM.

jQuery.data is really pretty fast, I will leave you with a few more timings -

FF2 FF3
$(”[id=my-id]“) 12ms 5.1ms
bare document.getElementById() 8.5µs 3.2µs
document.getElementById() with guard 22µs 6.5µs
jQuery.data cache hit 2.9µs 1.9µs

In the interests of aiming towards slightly more bite-sized blog postings, I thought I would share with you some possibly unsuspected gems in a favorite JQuery method I kicked over recently.

Basic extending

jQuery.extend is more commonly seen as part of plugin code - the jQuery plugin model simply works by “extension” of the jQuery object itself to include new methods. For example, here is some code from the JQuery UI dialog plugin:

$.extend($.ui.dialog.overlay, {
	instances: [],
	events: $.map('focus,mousedown,mouseup,keydown,keypress,click'.split(','),
		function(e) { return e + '.dialog-overlay'; }).join(' '),
...

The extend call is taking the existing jQuery.ui.dialog.overlay object (initially set up to be a {}) and “mixing in” a set of properties and functions from an “immediate hash”.

Multiple arguments

So far, this would account for the powers of a 3-line function, and one which we have all probably independently written for ourselves (certainly in the historical forms of fluid.mixin and RSF.assign). However, where jQuery.extend really shines is in its extensions. Firstly, it will accept any number of arguments - which are just progressively mixed in on top of its first argument:

$.extend(target, source1, source2, .... sourcen);

will “blat” all the members from the source arguments serially to arrive on top of target.

Deep copy

However, the real money of jQuery.extend is in its “deepCopy” functionality. Supplying the boolean value of true as the first argument will not just copy properties laid directly on the “source” arguments, but recursively copy any properties it finds. Here is some code from the new Fluid core initialiseThat function:

      that.options = jQuery.extend(true, {}, fluid.defaults(componentName), userOptions);

This has replaced countless quantities of “options” manipulating code from around the different components, some of it quite fiddly and manual, with a single, clear, static policy in one line. The core JQuery documentation page for jQuery.extend explains this option, but in a way which might easily be missed at a quick reading. As many of the example show, it is typically used for merging “options” structures, but it is also invaluable as a plain “deep copy” operation, for example forming the basis of Fluid’s upcoming pure model idiom. Tricks like this help keep down our core library footprint.

Note on Javascript types

In such a staggeringly weakly-typed language as Javascript, this kind of useful “overloading” is generally impossible. However Javascript is at least blessed with the ability to always distinguish a handful of primitive types (string, boolean, number) from everything else, and so enables useful “Swiss army knife” methods like jQuery.extend - luckily it detectably has no meaning to try to be extending a boolean object. One way to perform this type detection is by use of the typeof operator, JQuery itself chooses to use the following test in this situation:

  if ( target.constructor == Boolean ) {

Reading through the JQuery source base is highly recommended for people with a few moments to spare, who like to know what people who know what they are doing look like :)

About this and that

This posting will be about the different styles of creating “components” or “objects” in Javascript, and which styles Fluid is planning to recommend and in what contexts.

Javascript has inherited an “infusion” of “object-oriented” features grafted at the last moment on its fairly minimal and clear (LISP-inspired) baseline. The resulting language simply has too many ways of doing the same thing, and numerous features that are downright dangerous and obscure.

Continuing our chats on the performance theme, Colin and I set out to try to find a simple set of recommendations that would lead to code that is not only safe, but readable, maintainable and performant. Particularly, the aim is to cater to requirements of more structured programming, by larger, looser teams sharing components over longer timescales, rather than the “one-man”, ephemeral programs for which Javascript is more obviously suited.

In this posting I will cover a full range of “componentisation” techniques available in Javascript — from simple namespacing, structural use of closures — “scope-ism”, blending into the new “that-ism” that Fluid will promote, and contrasted against the “traditional” object-oriented language features (”this-ism”) based on this and prototype that we will deprecate, as well as more old-fashioned but performant and clear styles (”arg-ism”) carried forward from “pre-object-oriented” languages.

Open and closed

Continue Reading »

Fearless JavaScript 2.0

Back in April, Eli Cochran and I organized a half-day workshop on JavaScript development techniques at the JA-SIG Spring conference in St. Paul, MN. Writing Fearless Javascript for Portlets, Widgets, and Portals was designed to give attendees a primer on various aspects of client-side user interface development, including JavaScript fundamentals, the use of toolkits such as jQuery, and DHTML accessibility.

The workshop explores what I’ve been referring to as “modern” JavaScript programming, for lack of a better term. In contrast to the previous generation of JavaScript programs, where small bits of interactivity were sprinkled on top of a largely static document, modern JavaScript involves the creation of richly interactive applications and components. These days, your code probably shares the page and Javascript’s notorious global namespace with other libraries and widgets. As a result, you need to do things a bit differently to ensure your code is self-contained and won’t conflict with other libraries. Fearless JavaScript gives you the techniques needed to thrive in the world of portals, plugins, and mash-ups.

We’ll be presenting a new edition of Fearless JavaScript at the Sakai Summer 2008 conference in Paris, France. The material has been significantly refined, and we’ve added another co-presenter: Nicolaas Matthijs from CARET at the University of Cambridge. Nico will be talking about how to create gadgets for Sakai using JSON-based data feeds. We’re working on some tutorial code that walks you through using Fluid components within a Sakai gadget. Cool stuff.

Nico attended the original Fearless JavaScript workshop in St. Paul, and had lots of interesting questions and suggestions for us. Afterwards, Nico and I spent an enjoyable couple of hours working together on some of his gadgets, tweaking their accessibility and talking about his designs. He’s doing some great work on MyCamTools, and I’m looking forward to sharing the stage with him and Eli for Fearless JavaScript 2.0.

If you’re in Paris for the Sakai conference, we’d love to see you at the workshop. If you can’t make it, we’re hoping to create a podcast of the event. Here are the details:

Fearless JavaScript
Presented by Colin Clark, Eli Cochran, and Nicolaas Matthijs
Monday, June 30
1:30 - 4:30 pm in Amphi 55A

Topics will include:

* Why JavaScript?
* Fundamentals of JavaScript
* Using jQuery
* JavaScript in Sakai
* Portal and mash-up friendliness
* Accessibility

Everyone is welcome to attend the workshop. It’s assumed that you have some understanding of at least one programming language, and that you’ll bring a laptop to follow along with the hands-on exercises.

See you there!

Performance and Design

Following up on Antranig’s recent post about performance, I’d like to address the issue of code design and its relationship to performance. Antranig’s article is very comprehensive and well-considered, and it provides us with a number of guidelines for balancing the tradeoffs between code quality and speed. However, I was surprised that he didn’t remind us the C.A.R. Hoare quote made famous by Donald Knuth:

“Premature optimization is the root of all evil.”

Antranig’s performance metrics are intended to help establish a gut feel about the cost of a particular operation. They’re low-level measurements, and as such they can’t take into account a fundamental variable: context. These performance metrics have very different consequences depending on the size, scale, and nature of the application. His examples are apt: intensive, highly recursive, up-front operations like template rendering show the full cost of JavaScript’s weak performance. Indeed, Antranig has used his research to good effect on our nascent client-side template renderer. In a relatively short amount of time, he was able to improve the performance of his low-level parsing algorithms by several orders of magnitude using regular expressions and fast string comparisons. Impressive stuff.

On the other hand, context matters a lot when it comes to user-facing behaviour, where timings may vary significantly based on the user’s choices. Many UI components, such as the Uploader, provide a fairly modal experience for the user. Such components undoubtedly have less stringent performance requirements, and our acceptance criteria should be determined by testing in real-world situations.

The risk with out of context performance measurements is the tendency to optimize prematurely and without accurate data. There’s only so much time in the day. Don’t lose the opportunity to add useful features to your application by starting in on time-intensive performance optimizations too early. Without good data, your hard work may only have a tiny impact on the overall perception of speediness. Worse yet, premature optimization can lead towards architectures that are poorly factored, redundant, and hard to maintain.

So how do we ensure good performance without compromising architectural quality?

  1. Write code with good design principles in mind
  2. Continually measure performance in real world situations
  3. Refine code incrementally to improve performance

Let’s take jQuery as an example. If you look at the first release of jQuery, you’ll find that it was mostly composed of small functions that are clear and easy to read. jQuery’s author, John Resig, has always done a very good job of carefully profiling his code with performance tests, and over time the code base has evolved in certain areas to be faster and, as a concequence, occasionally less readable. He took the time to build something real first, then he optimized strategically. This is exactly the example of how we should all handle performance optimizations: build it cleanly, then identify areas where performance optimizations are necessary. Optimization without real-world numbers is, well, evil.

Building on Antranig’s advice, here are some strategies to help ensure both good performance and a maintainable design in JavaScript:

Avoid deep inheritance hierarchies

Excess use of inheritance tends to be brittle, hard to reuse, and slow. In JavaScript, inheritance is prototypal: an object has a secret prototype link that points to its parent object. When a property isn’t found on an instance directly, the object’s prototype is searched, then the prototype’s prototype, and onwards up the inheritance chain. This can be extremely slow on objects with a long lineage. JavaScript provides more effective strategies for reuse, such as containment and dynamic mix-ins. You’re better off with a very shallow inheritance hierarchy, using these techniques to share code across objects instead.

Break code into small, independent parts

JavaScript is a functional language, and functions serve as the fundamental building block for all programs. Break complicated algorithms up into smaller functions that take only the data necessary to perform a given operation. Small functions are more easily tested, modified, and reused. What about the cost per function call that Antranig mentions? If you need to optimize for speed later, you can easily merge several functions back into one. Analyze frequent code paths and identify specific bottlenecks first, then selectively fold smaller functions into a larger one.

Don’t deeply nest functions

In JavaScript, functions can be nested inside other functions. This is a very powerful technique, since inner functions have access to the variables and scope of the outer function even after the outer function has finished executing. This is called closure, and it’s one of the best ways to encapsulate state and behaviour in JavaScript. The trick is to avoid deep nesting; don’t stick a function inside a function inside a function. Similar to the inheritance chain, each JavaScript function invocation brings with it a scope chain, providing access to variables defined in outer functions. If a reference to a particular variable isn’t found inside a function’s scope, the JavaScript runtime will climb the scope chain, searching each outer scope in turn to find the property. All this searching can get pretty slow. Limit yourself to a couple of layers of closure at the most. Here’s a slight contrived code example and an illustration of the scope chain in action:

Illustrated Code Example: Using a closure for event handling

  function showMessage(messageToDisplay) {
  	var todaysPie = "Banana creme pie";

	return function(event) {
		alert(messageToDisplay + " " + todaysPie);
		showPictureOfPie(event.target, todaysPie);
	}
  }

  var messageClickHandler = showMessage("Welcome to my pie shop. Today's pie is:")
  $(element).click(clickHandler);

Identify nameable units of behaviour and encapsulate them

On the client side, it’s really easy to let your application logic get all muddled up with your presentation code. Large, hard to maintain functions are often structured like this: 1) Perform some calculations; 2) fetch some data; 3) update the DOM. These are separate tasks, and your code will be significantly easier to read and reuse if you split these behaviours into independent units. The trick is to look at your code while you’re writing it and recognize “things” that are easily identified and named. Using a closure or an object, you can factor out pieces of the overall behaviour and data into a separate entity. Here’s an example of the various units of behaviour we identified within the Reorderer:

  • The Reorderer is responsible for binding events to DOM elements and providing end-user APIs
  • A Layout provides an awareness of visual layout and spatial characteristics: grids, lists, portlets within columns, and so on
  • The Mover is responsible for moving elements around in the DOM, deferring to the Layout for spatial information
  • A Permissions object defines the rules for valid drop targets and operations on a specific element
  • Keyboard selections and accessibility is provided by the jQuery keyboard-a11y plugin
  • MouseDragAndDrop encapsulates our use of jQuery UI for low-level drag and drop functionality

Use closures to encapsulate data and behaviour

Antranig covered this one really well in his post. Under many circumstances, you’ll pay a significantly lower cost to access data wrapped in a closure than within an object, and functional idioms tend to be more flexible and easier to maintain than object-oriented ones. This is particularly true in JavaScript, where there is no built-in support for namespaces or privacy. Just be careful not to nest your closures too deeply.

Never, ever cut and paste code

It almost feels silly to repeat this one here. One of the foundational principles of programming, regardless of the language you’re using, is DRY: Don’t Repeat Yourself. The bottom line is this: cut and pasted code will come back to bite you. Don’t do it. Antranig’s post hints at the idea that it’s okay to cut and past code in JavaScript. For all but the most extreme cases, I don’t buy it. If you find yourself tempted to cut and paste something, take the time to factor it into a function. It will be easier to update later, and much easier to test. Duplicate code hurts!

Older Posts »