Patrick Roberts has written a fascinating post on Responsive User Interfaces. It’s easy to make a specific application responsive, through careful coding and by limiting what the user can do. An architecture for doing this, with arbitrary functionality, is one of the holy grails of GUI frameworks. Patrick’s post is a step towards this.
Patrick defines responsive as “the UI never locks up and provides at least partial results ASAP, not that every operation is completed instantaneously”. His design uses a UI thread that runs performs fast operations, and pushes slow operations onto a queue. A background thread runs these operations in priority order.
In his second post, Patrick refines the queue to handle superseded job items. This is important in a UI, where, for example, scrolling a list item out of the visible region of the list makes it unnecessary to figure out how to display it. It requires some finesse, because a naive implementation never gets around to displaying any of the items that the user is scrolling through. (A lot of work went into solving this particular case in the Laszlo implementation of lists.)
Patrick’s queue is just a step towards the responsiveness grail, and not the grail itself, because it still requires hand-coding to decide whether to perform each action immediately or place it on the queue, and to factor long-lasting tasks into subtasks that can display incremental progress — although maybe MVC usually takes care of the latter?
GTD can be thought of as a really sophisticated priority queue, and a decision procedure for deciding what to execute immediately and what to place in the queue. Each item in the queue has metadata: whether it has multiple steps, whether it requires additional information, its priority, external deadlines, and the context that the item requires: people, place, time, and energy. (GTD includes other storage structures too, and uses very different terms. I’m playing up the queue, and assimilating it to my own system, in order to make my point here.) When time is available, an item is selected from the queue according to the match between the current context and the item context, and then according to relative properties such as item priorities and external deadlines. For instance, I do my busywork tasks late in the day or when I’m otherwise feeling not at my sharpest; there’s some tasks I only do when I’m in California or when I’ve got a coworker on the phone; and there’s some that I’m only willing to start when I know that I’ve got a few uninterrupted hours in front of me. Beyond that, I choose according to whether there’s an external commitment and then by how important they are.
Here’s the idea I’m toying with: Use a queue like the GTD queue, and items with metadata, to schedule actions an application framework. The idea of matching task context with current context brings together some of the context-dependent actions that a computer performs. For example, indexing is a lower-priority task, but one that doesn’t require the user and doesn’t require an available time commitment to be worth starting; this is like my busywork. Synching, checking mail, and sending queued messages require a network connection; this is like my being in California or on the phone with a coworker. I also like the idea of adding metadata to an action, and using this to schedule it. In the GUI frameworks that I’m familiar with, the only metadata associated with an action is how to undo it (and what to call it in the Undo menu item). If the metadata also includes some of the same kinds of information that tasks in a project plan included, such as resources, dependencies, deadlines, and time estimates, then a GTD-style decision procedure can be used to move actions between a GUI thread, a background thread, and a Roberts-style queue.
There’s an obvious connection to blackboard systems and to AI planners such as Soar here. In fact, we can take a leaf from AI to solve the problem of how to supersede tasks, as in the scrolling case. The idea is that tasks have super-tasks, and cancelling a super-task cancels its subtasks. (This is like a goal tree in planning; a process thread or child process in an operating system; and a project milestone or a milestone task in project management.) In the scrolling case, the task of rendering a list item is a subtask of displaying the visible content of the list. Once the list has scrolled again, the extension of the visible content has changed, and any subtasks of the task of displaying the content of the old position should be cancelled. (A smart system would pool the tasks, so that it could restart them or leave them running if they’re also subtasks of a new task — in the scrolling case, if the new position includes the same list item.)
Although the Roberts queue and the GTD system are similar, they serve different purposes. The Roberts queue was designed to optimize responsiveness — the time between the user event that initiates the action, and the initial feedback that the action is proceeding. The GTD system was designed to optimize productivity — the throughput of the system, and the portion of that throughput dedicated to important items. Responsiveness and productivity are duals. A responsive application is easier to use productively, because it reduces input stuttering and it allows for tighter OODA cycles. And a productive person has an easier time being responsive, because (1) their backlog is smaller, and (2) they can tell you what their backlog is, and whether the task of responding to you is in it.