Skip to main content

No-code History: Peridot - UIs by Example, Visual Programming & Constraints (1987)

/galleries/post-images/nocode-history-peridot/peridot.jpg

Below are all slightly edited quotes from the material listed in the Resources section, emphasis mine.

Introduction

Peridot is an experimental tool that allows designers to create user interface components without conventional programming.

The designer draws pictures of what the interface should look like and then uses the mouse and other input devices to demonstrate how the interface should operate.

Peridot uses visual programming, programming by example, constraints, and plausible inferencing to allow nonprogrammers to create menus, buttons, scroll bars, and many other interaction techniques easily and quickly.

Peridot created its own interface and can create almost all of the interaction techniques in the Macintosh Toolbox.

Peridot demonstrates that it is possible to provide sophisticated programming capabilities to nonprogrammers in an easy-to-use manner and still have sufficient power to generate interesting and useful programs.

In order to allow interaction technique procedures to be created in a direct manipulation manner, Peridot has the designer provide example values for each parameter.

For instance, when creating a menu, the designer provides an example list of strings to be displayed in the menu.

Using a technique called programming by example, Peridot generalizes from the given examples to create a general-purpose procedure.

An important component of Peridot is the use of constraints, which are relationships among objects and data that must hold even when the objects are manipulated.

Peridot uses two kinds of constraints. Graphic constraints relate one graphic object to another, and data constraints ensure that a graphic object has a particular relationship to a data value.

The motivation for this style is that people make fewer errors when dealing with specific examples rather than abstract ideas. The programmer does not need to try to keep in mind the large and complex state of the system at each point of the computation if it is displayed on the screen. In addition, errors are usually visible immediately.

Example of Peridot in Action

/galleries/post-images/nocode-history-peridot/peridot-2-b.jpg

The designer has created a gray rectangle to represent a “drop shadow” for a button.

/galleries/post-images/nocode-history-peridot/peridot-2-c.jpg

The designer has drawn a black rectangle to represent the background of the button, and Peridot has noticed that this rectangle seems to be the same size as the gray rectangle, offset by a constant nine pixels.

/galleries/post-images/nocode-history-peridot/peridot-2-d.jpg

In the prompt area, it is asking the designer to confirm this constraint. The designer types y for “yes,” and Peridot immediately adjusts the black rectangle to be exactly the same size as the gray one.

If the gray rectangle’s size were now changed, the black rectangle’s size would change also, since a graphic constraint has been established that keeps both rectangles the same size.

/galleries/post-images/nocode-history-peridot/peridot-2-e.jpg

Next, the designer draws a white rectangle inside the black one, and Peridot correctly infers that this rectangle should be evenly nested inside the black one.

/galleries/post-images/nocode-history-peridot/peridot-2-f.jpg

The designer has selected the first element of the parameter “Items,” which is the string “Bold,” and has used that as the string to display.

Peridot infers that it is centered to the right of the white rectangle. The code that is produced for this string refers to the first element of the first parameter, whatever that is, rather than to the constant string “Bold,” so that any value used for the parameter will be displayed.

/galleries/post-images/nocode-history-peridot/peridot-2-g.jpg

Next, the designer selects all the objects created so far and specifies that they should be copied to a new position.

Peridot asks if it should look for constraints from the new copy to the old one, but this is not necessary since it is going to be part of an iteration.

/galleries/post-images/nocode-history-peridot/peridot-2-h.jpg

Next, the designer edits the second string to refer to the second element of the parameter.

At this point, Peridot notices that the designer has used the first two elements of a list in the interface, and asks whether the rest of the elements of the list should be displayed in the same way, as part of an iteration over all the elements of the list.

/galleries/post-images/nocode-history-peridot/peridot-2-i.jpg

The designer confirms this, and the rest are immediately shown.

In order to perform this conversion, Peridot has to determine which graphic objects should participate in the loop and how they should change in each cycle. Now the presentation aspects of the property sheet are finished.

/galleries/post-images/nocode-history-peridot/peridot-2-j.jpg

Next, the designer places the iconic picture of a check mark centered inside one of the boxes. This is used to show which items are selected.

/galleries/post-images/nocode-history-peridot/peridot-2-k.jpg

In order to demonstrate that this should be selectable by the mouse, the “simulated mouse” icon is used.

The real mouse cannot be used, since it is used for giving Peridot commands. The nose of the simulated mouse is placed over the check mark with the middle button down, and the MOUSEDependent command is given. Since there is only one active value (Selected-Props), Peridot guesses that the check mark should depend on this active value.

/galleries/post-images/nocode-history-peridot/peridot-2-l.jpg

Since the example value of that active value is a list, Peridot guesses that multiple items are allowed and that a check mark should appear for each one in the list. The designer is asked to confirm these guesses in the prompt window.

Peridot then shows the check marks displayed in the boxes next to Italic and Underline, since these are the current value of Selected-Props. Finally, the designer is asked whether pressing the middle button should toggle, set, or clear the selected object, and the designer types t for toggle.

The user interface is now complete, and either it can be tested with the simulated mouse, or else Peridot can be put into “Run Mode” and the real mouse can be used.

The PropSheet procedure that has been created can now be used outside of Peridot as part of application programs. It is parameterized as to the list of items that are displayed, so it can be called with an entirely different list of strings, even if that list has a different number of elements.

How Examples are Used

Many PBE systems require the user to provide multiple examples in order to generate code. In some cases, Peridot infers code from single examples. This is possible because the designer is required to explicitly give a command to cause Peridot to perform the inferencing.

For example, the designer issues the MOUSEDependent command to tell Peridot to look at the mouse position and to infer the generalization for the operation.

For iterations, however, the designer is required to give two examples, and Peridot can therefore usually infer the need for an iteration without an explicit command from the user.

Peridot also allows the designer to demonstrate conditionals that display special graphics and that serve as exceptions to the normal way the mouse dependencies work.

For example, some items of the menu might be shown in gray if they are illegal, and horizontal lines might replace certain items.

How Inferencing is Used

In order to make Peridot easier to use, it automatically guesses certain relationships. This frees the designer from having to know when and how to specify these relationships.

Peridot uses simple condition-action rules to implement these guesses. This approach is called plausible inferencing or abduction in the artificial intelligence literature. The condition part of the rules determines whether the rule seems to apply in the current context.

If the condition passes, then the designer is asked whether to apply the rule or not using an English message attached to the rule. If the designer answers “yes,” then the action part of the rule is applied, which changes the code of the procedure in order to add a graphic constraint.

The rules in Peridot are simple-much simpler than those used in typical artificial intelligence systems. Furthermore, there are only about 60 rules used in Peridot. The goal was to see if simple mechanisms would be sufficient, which seems to be true.

Peridot uses rule-based inferencing in four ways:

  1. To infer the graphic con straints that relate one object to another

  2. To infer when control structures are appropriate

  3. To infer how to create the control structures

  4. To infer how the mouse should affect the user interface

Inferring Graphic Constraints

Peridot infers how the various graphic objects are related to each other.

One reason that Peridot is more successful is that it guesses correctly more frequently, since it only needs to deal with the relationships that are typical in user interfaces, rather than all possible relationships that might be used in a general drawing.

If the designer wants other relationships, they can be explicitly specified, or if they occur frequently, a programmer can easily add them to the rule set.

Another reason for Peridot’s success is that it assumes that guesses will occasionally be incorrect. Therefore, it always reports to the designer the rule that it is planning to apply and allows the designer to confirm or prevent its application.

This gives the designer confidence that the system is not mysteriously doing strange and possibly erroneous things.

In addition, the results of the inferences are always immediately visible (the objects redraw themselves after every rule is applied), so the designer can view the results and see whether they were correct or not.

Another benefit of inferring graphic constraints is that they allow the designer to draw the picture quickly and sloppily, and then Peridot automatically “beautifies” the picture by enforcing the constraints.

The rules that Peridot applies are specific to the types of objects drawn. For example, it is more likely for a string to be centered at the top of a rectangle than it is for another rectangle to be.

Some of the rules specify all of the properties of an object. Examples of these are that a rectangle is the same size as another rectangle, that it is nested inside the other rectangle, or that a string is centered vertically to the right of a rectangle.

Other rules only constrain some of the properties of an object. For example, one rule might cause the width and left of a rectangle to be constrained by another rectangle, and another rule may constrain the top and height by a string.

In general, there are constraints for most of the simple relationships found in typical user interfaces.

There are currently 50 rules, and these are all listed in. Of these, 16 were added based on user testing.

Since most of the additional rules were added from the initial users and no new rules were needed for later users, it is expected that few new rules will be needed in the future.

Peridot goes through the rules in order, trying each test. The order is determined by the types of the objects, by the specificity of the rule (the rules that constrain all of the properties of the object are checked first), and by which ones seemed to be the most common.

If the constraint has parameters, such as how far apart the objects should be, the designer can answer “almost” and supply a new value for the parameters. If the designer answers “no”, then other rules are attempted.

Inferring Control Structures

Peridot automatically infers when control structures such as iterations are appropriate.

Iterations are inferred whenever the first two elements of a list are used.

To create a dependency on an active value or a parameter, the designer must explicitly select an element of these in the upper window and then specify which property of the object depends on the selection.

Conditional control structures are automatically inferred when objects depend on the mouse. In addition, the designer can explicitly specify that either a conditional or an iteration is desired by executing commands from the menu.

Differentiating Variables from Constants

After the objects that participate in a control structure are identified, Peridot must determine which properties of the objects are constant and which change.

It has been found with previous systems that inferring variables from constants is difficult, but Peridot’s simple mechanism has been successful. Again, this is due to the limited domain; graphic objects in user interfaces change typically in simple ways.

Inferring Mouse Operations

When the designer gives the MOUSEDependent command, Peridot looks under the simulated mouse to determine which objects are affected and where the mouse should be for the operation to be active.

The designer specifies when the operation should happen by toggling the state of the buttons on the simulated mouse. The interaction can start after single or multiple buttons presses (e.g., double-clicking) and either on the down or up transition of the button.

Next, Peridot infers which object should be affected by the mouse.

Then, Peridot infers how the objects should change with the mouse. The possibilities are 1. to choose one or more out of a set of objects (e.g., controlling which objects are selected in the property sheet or menu, 2. to move in a fixed range, 3. to move or change size freely 4. to blink on and off in place.

Peridot guesses which of these is appropriate by looking at the constraints on the graphic objects that are affected by the mouse.

The Language

Because Peridot creates user interface procedures, it operates as a code generator.

The code generated by Peridot has a number of conventional parts: straightline code, iterations, conditionals, and parameterized procedures.

Straight-Line Code

As the user is drawing objects, Peridot creates LISP code that will draw them for application programs. If the user edits an object, the code that generates it is modified.

If properties of objects are fixed and unchanging, then their values will be constants. If the properties are to change at run time based on parameters to the procedure or end-user input, they are controlled by constraints.

If the objects themselves appear and disappear at run time, they must be enclosed in conditionals or iterations.

Users are not allowed to edit the text code.

Iterations

Iterations are important because they allow Peridot to support variable-length lists and they relieve the designer from having to perform tedious, repetitive actions. Peridot infers iterations when two items from a list have been used.

There are two forms of iterations in Peridot. The most common form displays a copy of one or more graphic objects for each item of a list.

The items in the list can be used to control any property of the graphic objects in the iteration.

The other form for iterations is to display a set of objects for a specific number of times.

This is mainly useful for displaying a line of identical objects. To get this form of iteration, the designer creates two copies of the objects to be repeated, selects them, and then executes the Peridot Iteration command.

Conditionals

Conditionals in Peridot are used to support displayed feedback over one of a set of objects and to control an object blinking on and off.

Conditionals are created in a postfix style; that is, the designer first draws the graphic objects that are used as feedback when the conditional is true and then specifies what these objects should depend on. This allows the designer to use the standard drawing and editing commands to create the graphic objects.

Parameters and Return Values

An important property of the code that Peridot generates is that the procedures are parameterized.

This provision for parameters is the most significant difference between Peridot and other graphic user interface tools. Other systems like NeXT’s Interface Builder only allow the designer to specify a fixed set of values for the menus and buttons.

Visual Programming Aspects

An advantage in Peridot is that the system is not trying to address general-purpose programming, as in many other visual-programming languages. Therefore, more specialized techniques can be used.

Some parts of the user interface are not fully visible in Peridot. For control structures, the designer only sees the result, and there is no indication whether the objects were created due to an iteration or a conditional.

Mouse dependencies are even more abstract and do not appear in the normal graphic display. The designer must either exercise the interface or give a command to have the interactors listed in order to know what has been created.

One of the problems of many visual-programming systems is that they cannot handle large programs due to a lack of modularization. In Peridot this is not a problem, since parameterized procedures are created that can be combined into full interfaces.

Each user interface element is defined separately and encapsulated in its own procedure, so the designer can create interfaces out of small, modular, well-structured pieces.

Editing Programs

It is harder to edit control structures and mouse interactions, since they do not have visual representations on the screen that can be selected.

For editing control structures, the designer can simply select any graphic object and give an editing command. If that object is part of a control structure, Peridot will inquire whether a modification to the control structure itself is desired or whether there should be an exception to the normal way the control structure works.

If the designer specifies that the control structure itself should be edited, then Peridot returns the display to the original objects from which the control structure was created.

For an iteration, this is the original two sets of elements, and for a conditional, it is the original one element.

Now the designer can use all the normal editing commands to change the picture as desired. When editing is complete, then the Iteration or Conditional command is given to reinvoke the control structure.

This technique is used for three reasons.

First, it is easier to ensure that the designer’s edits always make sense. Otherwise, if the designer changed the fourth item of a list, what would this mean?

Second, if multiple items are generated by the control structure, the designer might make intermediate edits (such as deleting an object from one group) that would cause Peridot to be unable to show the control structure consistently.

Third, the list controlling the iteration or conditional might have only 1 or 0 items in it when the designer performed the edit, in which case there would not be two groups of objects for iterations or one for a conditional, so there would be nothing for the designer to select.

Returning to the original two groups of objects allows the designer to have full freedom to edit in any way desired, using all the conventional editing commands.

It is even harder to edit mouse interactions because there is nothing to select. Peridot provides two ways to edit interactions.

First, an interaction can be redemonstrated, and Peridot will inquire if the new interaction should replace the old one or run in parallel.

The second way to edit interactions is to select an active value and give the DeleteInteractions command. Peridot then prints in the prompt window a de scription of each interaction that affects that active value, and asks if it should be deleted.

Since individual interactions are small this should not be burdensome.

The added complexity for the designer of learning extra editing commands does not seem appropriate, given the ease of respecification.

Evaluation

In order to evaluate how easy Peridot is to use, an informal experiment was run where 10 people used the system for about 2 hours each.

Of these people, five were experienced programmers, and five were nonprogrammers who had some experience using a mouse.

After about 1; hours of guided use of Peridot, the subjects were able to create a menu of their own design unassisted. This demonstrates that one basic goal of Peridot is fulfilled: Nonprogrammers are able to create user interface elements using Peridot.

Graphic Constraints

One important reason that Peridot is more complicated than a conventional drawing package is that it must deal with the parameterization of the procedures.

This implies that Peridot must know how various graphic parts of the interface change with different values for the actual parameters.

Peridot must know that the size of the shadow and outline rectangles must change based on the width of the widest string and the sum of the heights of all the strings.

It is also possible to specify explicitly the relationships by selecting two objects and providing an arbitrary arithmetic expression that relates their properties.

After a relationship is either inferred or explicitly specified, Peridot creates a graphic constraint so that the relationship will be maintained if the picture is edited or if different parameters are used at run time.

The constraints used in Peridot differ markedly from constraints in previous systems because they are simple and efficiently implemented. The primary reason for this is that only one-directional constraints are necessary. The reverse relationship is saved at design time in case the designer edits the picture.

For example, when creating a button, the first step is to create the black and then the gray rectangles. At this point, the gray rectangle’s size and position depend on the size and position of the black rectangle.

Next, the designer adds the string, and Peridot infers that the size of the gray rectangle should depend on the size of the string.

Since constraints are only one directional, this would remove the constraint that connected the gray and black rectangles. Peridot notices this and asks the designer if the constraint should be reversed. The question is asked because it is often the case that the user wants to remove or change the constraints rather than reverse them, in order to change the way the picture looks.

The dependencies of an object’s attributes are often cascaded. Peridot is careful to reverse all the necessary constraints so that the interface stays consistent.

In addition, the dependencies may go forward in the drawing order as well as backward.

If a relationship has been reversed or the user explicitly edits an attribute to depend on some object, an object may be drawn before the object it depends on is drawn.

The drawing order of objects cannot be changed, however, since newer objects can obscure older objects. Therefore, the calculation order must be different from the drawing order.

The one-directional graphic constraints in Peridot have proved to be sufficient for handling all the relationships that occur in user interface elements.

Operations that appear to require two-directional constraints are usually handled in Peridot using active values.

Data Constraints

Active values are like parameters to the procedure except that, when they change at run time, graphics are updated immediately.

Active values can be set by the application program at any time to update the graphics.

In addition, application routines can be attached to active values, and these will be called when the active value changes. Therefore, active values are also used to pass information back to the application programs.

The screen in the top Peridot window, and the displayed value is updated when the value changes. This makes the system more understandable, since the state of the system is always visible; the designer does not have to try to remember the values of the variables.

Another factor that makes active values easy to use is that the designer can type in new values for the active value using the FixActive command. This can be used to check that the graphics change appropriately.

Trivia

Peridot was implemented in Interlisp-D on the Xerox 1109 DandeTiger workstation

Peridot stands for Programming by Example for Real-time Interface Design Obviating Typing.

Resources

See Also

Found it interesting?

Subscribe to instadeq's monthly newsletter to stay updated