Adobe Releases Adam and Eve

It was with some shock that I read (via Slashdot) about Adobe's Open Source presentation engine (and layout system). In my experience, very few companies take much stock in writing generic systems that leverage the body of computer science.

So, I was quite pleased to read Sean Parent's comments:

The most ambitious library, Adam, stems from the intuition that the logic behind a simple human interface can be distilled to a function:


f(x) -> x'

The code providing this functionality accounts for a third of Adobe's code base and nearly half of the bugs found during development. Obviously these functions are not so simple, at least not as currently expressed. The apparent complexity is due to a high degree of interconnected variables. Event handling code alone does not have enough context for solving such systems.

The next jaw-dropping tidbit came a few lines later:

Still, I am convinced that writing correct, high performance, and feature rich systems can be orders of magnitude simpler than it currently is. By my estimate, 70% of Adobe's current code base could be better represented declaratively. The remaining imperative logic could be largely generic - reused both within and across Adobe's applications. Realizing even a fraction of this potential would open up a world of opportunities. I strongly suspect the proportions are similar throughout the industry.

The website provides an overview of exactly what has been released:

Adam is a modeling engine and declarative language for describing constraints and relationships on a collection of value, typically the parameters to an application command. When bound to a human interface (HI) Adam provides the logic that controls the HI behavior. Adam is similar in concept to a spreadsheet or a forms manager. Values are set and dependent values are recalculated. Adam provides facilities to resolve interrelated dependencies and to track those dependencies, beyond what a spreadsheet provides.

Eve consists of a declarative language and layout engine for constructing an HI. The layout engine in Eve takes into account a rich description of UI elements to achieve a high quality layout - rivaling what can be achieved with manual placement. A single HI description in Eve suffices for multiple OS platforms and languages. This document describes Eve2, the latest version of Eve. Eve2 was developed to work with Adam and to incorporate many improvements that have been requested since Eve1 was written.

It is important to note that Adam and Eve do not constitute a traditional application framework. They are component libraries which can be incorporated into a number of environments. They can be used together, or independently, but must be combined with other facilities to construct an application. Nearly all of the components which comprise Adam and Eve can also be used independently and are documented as part of ASL.

Sadly, my experience with Adobe's products extends only to their Acrobat Reader software, so I can't claim from personal experience that they have achieved their aim of writing stable software.

However, the fact that top-level architects at Adobe are cognizant of declarative paradigms and generic programming gives me new hope in the industry.

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.

Similar

The Eve description is very similar to the Oz/Mozart approach to UI and not too dissimilar from the SWI/Prolog approach.

... Reusable?

Since Oz/Mozart is (at core) a C++ program, I wonder if Adam/Eve could be leveraged to create an easier multi-platform support for the uI.

The Mozart/Oz approach to GUI and the QTk tool

I was wondering when the world would get around to realizing the advantages of a mixed declarative/imperative approach to GUI design. It has been available as a full-featured tool in Mozart, QTk, since 2001. This tool is the work of Donatien Grolaux, a truly gifted developer, who was pushed into designing and writing QTk by me after I refused to learn the arcane and verbose logic of tcl/tk. See, e.g., the short paper presented at the EHCI 2001 conference, the paper presented at the DSVIS 2001 workshop, or chapter 10 of CTM. If you haven't played with the Prototyper tool presented in chapter 10, then you are missing out on a real Aha experience. (What's even more amazing is that the whole Prototyper is written in only 140 lines of code.)

Interesting

I've got CTM here and have been reading through it off and on over the last few weeks (great work, by the way). I just looked at chapter 10 now in response to your post, so maybe this isn't the most thoughtful response you'll get.

I wonder if you could explain more about the particular features of Prototyper that you find useful. From what I can tell, the edge binding feature is identical to a similar feature in Borland's VCL. The tabular widget organization (lr/td) is interesting. I've made something similar in the user interface system of my little Scheme-like interpreter (UIs defined in my system can derive HTML or regular desktop window interfaces from the same widget layout definition).

One feature you describe here that I find really interesting is linking unbound variables to user interface fields.

Streams?

One feature you describe here that I find really interesting is linking unbound variables to user interface fields.

What about using widgets together with dataflow streams? Is this at all useful or desirable?

Using streams

What about using widgets together with dataflow streams? Is this at all useful or desirable?

Actually, it is! When a program interacts with a QTk-created specification, information flows in two directions: toward the GUI and toward the application. For the former, internally the GUI runs in a single thread and reads commands from a stream. This is important to keep the right order of graphics commands. For the latter, the GUI calls action procedures or sends messages to ports (QTk supports both), from within its single thread. (The P2PKit toolkit for building peer-to-peer applications that Kevin Glynn is working on now is based implicitly on message streams, BTW.)

The Prototyper

I wonder if you could explain more about the particular features of Prototyper that you find useful.

I was referring to two things. First, the fact that you can interactively enter and edit a GUI specification and run it directly. This is because Mozart has a first-class Oz compiler (a normal situation for a dynamic language, BTW) and because QTk is an interpreter (it interprets a GUI specification and creates handler objects to fill in the holes in the specification). The second thing is how Prototyper is organized as a learning tool: with progressive lessons on GUI construction in the left pane, that come with explanations and live code examples in the other panes. It's such a simple structure, but it's very effective. It is enabled by the first-class Oz compiler and QTk interpreter.

The world did realize, kind of

Don't forget that HTML with CSS is a declarative GUI library. Combine that with Javascript and the DOM and you have a mixed declarative/imperative approach to GUI design. No wonder Googles interfaces are so good.

Dynamic HTML

Yes, you're right. HTML with DOM is close to QTk in spirit (declarative specifications that can be interpreted at run-time, with embedded objects), but based on character strings instead of records. Character strings are really not the way to go for this kind of thing. They're flat so you have to parse them to get at their structure. Furthermore, it is hard to embed live language references inside them (you have to encode them). Full-featured records with syntactic and operational support on the other hand are almost ideal.

I agree

I wanted to say you can do all that in Javascript, but then you don't have the declarative part anymore. DHTML is not mixed declarative/imperative, but declarative only first and then imperative only.

But Mozilla now has E4X support (XML in Javascript), so that gives you the declarativeness back. But I haven't seen anyone use E4X with XHTML yet.

Dynamic HTML - good enough yet?

We tried using Dynamic HTML as a basis for a GUI toolkit (in the QHTML tool), but we ran into two practical problems: (1) nobody had implemented enough of the Dynamic HTML standard to be useful, and (2) the most complete implementation, in IE 5.5 I believe, was very slow. It was never intended to be used as a graphical toolkit (it suffered from the suffocating gerbils problem).

This was a few years ago, I don't know whether things have improved since then.

Absolutely good enough

The trick is not to try to emulate the standard graphical toolkits, but to improve on them using the new web idioms. That way you get the performance, because you are using the browser what is was optimized for. Google does this very well imho with their mail and map apps.

Mozilla and IE both have enough implemented from the DOM, and have added enough on their own, to seriously build applications. But they are platforms, and like any platform it takes some time to learn the details.

Suffocating gerbils?

Uhh, what's the suffocating gerbils problem?

Suffocating gerbils problem

I think the expression comes from the aerospace industry. A space rocket, like the Saturn V, is a complex piece of engineering with many layered subsystems, each of which is often pushed to the limits. Each subsystem depends on some others. Suppose that subsystem A depends on subsystem B. If A uses B in a way that was not intended by B's designers, even though formally B's specification is being followed by A, then we have a suffocating gerbils problem. The mental image is that B is implemented by a bunch of gerbils running to exhaustion in their hoops. A is pushing them to do too much. That's how I understand the suffocating gerbils problem.

Google says...

I searched google, and turned up some experiments where the active ingredient of marijuana was used to partially prevent brain damage in suffocated gerbils. So I guessed it was a colloquialism for brain damaged.

--Shae Erisson - ScannedInAvian.com

Tcl and Tk

Arcane and Verbose?

Well, it may not float your boat, but Tcl is pretty simple, really. It's like a cut down lisp with some things thrown in (expressions) that make it more palatable to people without a great deal of programming experience. It has been quite successful at that really. It certainly has some warts, but for what it was aimed at, it has done quite well.

Arcane and verbose

Well, I didn't mean to criticize Tcl/tk specifically. Like you say, it does quite well for what it is designed for (building GUIs). My criticism is aimed at the general GUI approach where you have to build the GUI by invoking lots of commands. At the time we did QTk, Mozart had a very nice tk interface with an OO layer on top (the Tk module). But for building simple interfaces, the number of lines of code needed using QTk is 1/3 to 1/4 that of Tk, and they're simpler to write.

Repetitive and clunky

Implementation techniques aside, do you guys really like these Gtk/Qt/Win32/etc point-and-click user interfaces? I can't stand them. Give me a higher-order interface any day, like Unix shell or Emacs.

Web applications do seem like a good step in this direction of "a large number of ways to manipulate a small number of data structures". Using Firefox I can now consistently navigate webapps with isearch (just like Emacs) and control which pages to keep in tabs (buffers) ready for display, to name but two important examples. Contrast this with "rich" applications that make me do mental alphabetic-sort while pulling scrollbars and repeatedly clickety-click my way backwards and forwards to get where I want to go.

What good stuff is happening in the world of powerful user interfaces today?

P.S. I haven't used Photoshop and I'm not saying that it has a bad interface. The best example I have of a wonderful program with a hurtful user-interface is Ethereal.

erm

Actually Sean's reply below makes it sound like there's more to constraint-based UIs than I realised. Perhaps I chose the wrong thread to unleash the "I don't like ethereal's UI" rant :-)

Nice!

From the functionality this reminds me a little of Apple's Interface Builder. But QTk seems much more declarative (IB only works graphically, but helps a lot with layout), with obvious advantages for automatically generated windows.

BTW: is there a short summary/introduction to the Oz lightweight Thread implementation? Are they heap-allocated, cooperative threads without OS support, maybe continuation-based, like in most Scheme implementations?

Declarative UIs have been around for a long time..

I wrote about this on my infrequent blog, but declarative UIs have been around for a long time.

Consider Garnet, which I used to develop a user interface for a finite element analysis post-processor back in 1990 or so. That was Lisp-based (and it was described as a "constraint-based" UI toolkit), but the same group at CMU later wrote Amulet, a C++ toolkit similar to Garnet. There was also some stellar work by Michael Sanella, Bjorn Freeman-Benson, and others (at UWashington) and even subArctic, a Java toolkit, was written almost a decade ago by Scott Hudson while he was at Georgia Tech.

I really figured constraint-based programming in general was the wave of the future -- that after everyone learned and adopted object-oriented techniques, constraints would be next. Shows you how good my predictive powers are.

Constraints in GUIs

Yes, I agree with you. It's depressing how long it takes for ideas to make it into the mainstream (20-30 years). I seriously think that most of the good ideas in CS existed already by the mid 1970s, and that what came after is just consolidation and maturation of the field.

I think that constraints have the potential to make it into the mainstream some day. The Adam tool is really a nice idea and we will try to find some time to give it the attention it deserves (it depends on whether one of my project proposals gets funded :-) ).

Thanks-

I was just browsing around - the release of ASL generated much more attention than I anticipated - and found your post. I thought I'd follow up with some more details for your readers. One of your readers posted about Oz/Mozart. Coincidentally, I just started looking at Oz this week to borrow some ideas that might improve the efficiency of the Adam engine. I've been working on Adam now for quite some time and my ideas have been influenced by many systems and reading many papers - but I still continue to find inspiration in new places. That is one of the reasons I've sited for making my work available - a little exposure uncovers new leads.

As for Adobe being cognizant of declarative and generic programming - certainly some of us are (Alex Stepanov is a member of my team so it would be surprising if we didn't have a fairly strong generic bent (see stepanovpapers.com), he and Mat Marcus are currently doing some great work at regarding teaching programming). I don't claim that a declarative approach to these problems is unique - but I do think Adam and Eve have some fairly unique attributes. Adam's ability to describe inter-related values without under-constraining, and gracefully handling over-constraints, makes it a fairly powerful and easy to use system. It also tracks dependencies at two levels, each cell consists of a (priority, value) pair - if either contributes to another value then the cell is said to have been "considered", if only the value contributes then it is said to "contribute" - this information is used to enable/disable UI elements (a UI element attached to a cell that wasn't considered is disabled, since it is a "don't care"). Script recording is done by capturing the contributing cells - which can be played back against the same sheet, but within a different context (Photoshop Actions are a scripting system that at least attempt to work this way). These dependencies are also used to determine which cells are invalid as a result of an invariant being violated (a cell contributing to an invariant is marked as poison and any derived cell is marked as invalid).

Eve is similar to a box model but has a mechanism to automatically establish cross hierarchy constraints without over constraint. This means that things like labels and baselines will automatically snap, even across groups (we refer to these constraints as "guides") - Eve1 is used quite heavily at Adobe (Eve1 has a less sophisticated guide model than Eve2).

Adam and Eve are quite usable (and I would assert they are high quality) in the current release, there is still work to be done though. I'm hoping others will jump in to contribute, it doesn't have to be code - this project is about algorithms (as every project should be :-) ). I have many ideas about what the next steps should be to realize the vision I outlined in my foreword.

Thanks again for your post -

Sean

A Few Notes

First, it's great to see Sean and the rest of the team's work in the wild. I had the great good fortune to offer presentations on O'Caml and the Whisper C++ framework at an event where Alexander Stepanov keynoted on the history of algorithms and Sean gave two presentations that hinted rather strongly at the work that he was doing on Adam and Eve. It was fascinating and exciting and I remember leaving the conference repeating the one thing that Sean had said that seemed immediately useful: "You can go a long way with just boost::signals and boost::bind." But I knew he was up to quite a bit more, so it's good to see it finally come to enough fruition that Sean and the others are comfortable releasing it.

Some of the Slashdotters seem not to quite know how much influence Alexander Stepanov has had on that work. Hopefully Sean's comments have clarified that. It was certainly clear in Sean's presentations.

With respect to the surprise that a hardcore product-shipping environment like Adobe uses things like Boost rather than rolling their own, let me also observe from knowing a lot of people who ship product for such companies that they are exquisitely sensitive to their external dependencies, and at some point, the "if you can't beat 'em, join 'em" line gets crossed, and out of that you get Adobe people contributing to Boost and even having people get involved in the C++ language and library standardization effort. At an even further extreme, e.g. Microsoft or Ericsson, you have a company that develops a new language and libraries even though that's not their core business. Then the dependency is no longer external, and management can breathe an iota (but only an iota!) easier.

Finally, you sometimes see something really nice, like Apple open-sourcing their Rendezvous implementation across all the popular platforms, or Adobe contributing a major design and implementation effort to the open source community. I think this reflects an enlightened self-interest, in which Adobe realizes that the value they provide in their products doesn't come solely or even primarily from this code, and that everyone benefits from the availability of good tools such as these.

So thanks, Sean and team—it was an honor to present at SFU with you and it's a pleasure to see the results, so far, of your hard work.