In my last article, I covered the basics of what a DSL is, and what they’re useful for. This week, I’m going to talk about what a DSL to manipulate the desktop should be like, what solutions exist already, and what we could do to improve them.
Last time, I discussed how users have a set of tasks that they perform often - web, email, file management - and how those tasks can be broken down into a collection of ‘task primitives’. Let’s take a closer look at how the user actually works with them.
User tasks tend to fall into one of two groups:
- One-shot tasks, where the tasks launches, does something, and stops. They don’t hang around when they’re not doing something useful. Examples include downloading mail, resizing photos, and generating reports from a database.
- Persistent tasks, where the task hangs around and keeps doing useful things, as and when required. Examples include text editing, IM conversations, and RSS reading.

Apple’s Automator is a great example of how one-shot tasks can be made into applications of their own. Using Automator, it’s easy to string together a series of tasks that execute one after the other, performing useful work until the chain ends. However, it’s impossible to create a complex, persistent application, like a web browser or alarm clock. This is not a bad thing, though - for what it does, Automator is the best in its class.
Automator is able to do what it does because it makes use of the Open Scripting Architecture, which is the OS-wide scripting framework that allows applications to publish scriptable actions they can perform. In other words, there exists a huge library of one-shot tasks ready for use. Some of the more graphically impressive ones are photo manipulation: resizing, applying filters, adding borders, cropping, and so on. Chaining a set of these one-shot tasks allows the user to create powerful macros.

But what about applications that need to persist? Let’s extend the idea of one-shot photo manipulation and consider an application that, when launched, sticks around and processes photos as they come, not photos that it was initially told to work with. Such an application exists: it’s called Picturesque, by Acqualia Software, and it happened to win an Apple Design Award for its ease of use and simplicity. This app simply presents a drop area where users can drop photos, which expands into a picture manipulation workspace. Users make the changes they want, and then save the photo. The process repeats until the user quits the application. In the meantime, the application occasionally checks for updates in the background.

We can immediately see that there are two tracks of tasks going on here: things the user instructs the application to do, and things the application will do on its own. The things the user directs the application to do tend to be one-shot tasks, or a chain of them. One of the important one-shot tasks that every application needs is ‘quit’. When a task is complete, the application goes back to waiting for more information from the user, or stops.
What we’re seeing here is the essence of GUI programming: there is a main loop, foreground tasks, and background tasks. A persistent task is either a repetition of independent tasks, or it is the application as a whole. With this in mind, all that we have to do now is select the one-shot tasks that compose our application’s behaviour, and work out how our interface interact with the tasks. (I’m completely ignoring things like data manipulation, or the problem of designing very complex tasks, like creating a slideshow presentation. This is just a very broad overview.)
So now that we know how our application is going to be composed, how do we express this in a DSL? Well, one already exists. It’s AppleScript, and it works quite well: entire applications can be written in it, and it’s as powerful as any other language on the system, with the added bonus of easily getting other applications to provide services. But AppleScript has an issue: it’s text. And writing text that turns into an application’s behaviour is less intuitive than visualising the workflow of the application’s functions - that’s why Automator was written in the first place.
So what can we do? Next week, I’ll be looking at ways to visually design complex workflows, and we’ll see if we can design an entire application visually.
Further reading: