TweetFollow Us on Twitter

Rapid Prototyping

Volume Number: 14 (1998)
Issue Number: 2
Column Tag: Programming Techniques

Rapid Prototyping

by John Schettino

An Object Oriented Approach to Using FaceSpan and AppleScript to Prototype Applications

Software Development 101

Just the other day I read a posting to a Macintosh programmers news group that asked a simple but powerful question. What design methodologies do most Macintosh programmers use? As I stared at the phosphors of my monitor, I recalled my years of formal study in Software Engineering. I learned all the state of the art (in the late 80s) software design methods when I was getting my Masters degree -- but what do I actually use in practice?

The answer is a bit surprising. It turns out that I usually use a technique called either incremental development or rapid prototyping. This approach relies on my own expertise in ad-hoc design and the fact that I'm usually working alone on a project. It doesn't hold up quite so well for large programmer teams. The basic idea is to quickly implement a subset of the application, use it -- or better yet let the customer use it, see what works and what doesn't, and then repeat the cycle. Each time through the cycle refine:

  • the requirements (what the application is supposed to do)
  • the interface (how the application looks)
  • the behavior (what the application does), and
  • the design (how the application is structured)

For this approach to succeed, using tools that support very fast implementation of successive versions of the prototype is critical. Discarding the prototype once it has served its purpose is also critical. This prevents overattachment to the initial version's implementation. It also keeps me from over-polishing the prototype! For these reasons I've selected AppleScript and FaceSpan as my Rapid Prototyping Environment.

The Tools

AppleScript is the Macintosh's bundled scripting language. It is a reasonable programming language for prototyping, since it includes basic block-programming constructs, subroutines, and several data types. It supports classes with data and member functions, and fairly complex data structures. There is also a wide array of scripting additions on the Internet that I use to round out the language. AppleScript is close enough to Java, C, or C++ to allow me to re-implement the prototype in any of those languages. It also reads a bit like psudocode so it can be used as a specification language for the final implementation. The big plus for AppleScript is that it can call on third-parties to perform complex tasks. That means databases, emailers, text editors, and even the Finder can be called on to perform major portions of a prototyped application. The big minus with AppleScript is that it completely lacks any capabilities for interface creation.

FaceSpan is a product from Digital Technology International that works as an interface tool with AppleScript or other OSA scripting languages, such as Frontier. Using FaceSpan I can create interfaces for AppleScript prototypes. The interface consists of several different styles of windows containing standard Macintosh interface elements. I then attach scripts to the windows and elements to process the events they generate. All the windows and scripts are contained in a single project file. I run the project within the FaceSpan environment while I'm developing it. Once it is working correctly, I save the project as a standard Macintosh executable file. In many ways it's simpler than it sounds.

The combination of AppleScript and FaceSpan is similar to HyperCard with several key advantages. Most important is the elimination of the Card/Background/Stack metaphor. In FaceSpan each window and it's window items behave as a unit, with their own message hierarchy. This yields "Mac-like" prototypes instead of "HyperCard-like" prototypes. FaceSpan also fully supports color, QuickTime, Drag and Drop, and other key Mac technologies. It has a rich set of interface elements to choose from. I've done pretty fancy interfaces with FaceSpan, creating and destroying window items on the fly, implementing direct manipulation interfaces, and so on. Some of the more interesting effects require a bit of script code, but at least that code is easily reused in other projects.

The Method

I like methods. A method is a little less formal than a procedure. It is a general description of the steps needed to get something done. If there is something in this method that doesn't work for you, then just work around it. The primary reason I develop a prototype is to refine my understanding of the application I'm creating. I also use it to get end-user feedback early in the design and implementation process while it is easy to make changes. The method I use to meet these goals with FaceSpan and AppleScript is quite simple:

  • First, create the static portions of the interface.
  • Second, add enough AppleScript to animate the interface at the most basic level.
  • Finally, add more AppleScript to implement as much of the application behavior as is needed for the prototype.

This three-step approach is not specific to FaceSpan and AppleScript. It's the same method I use in any language. When using these tools it is just a lot faster to complete each step. Depending on the goal of the prototype it is usually possible to stop before completing all three steps. For example, a UI designer might simply want to draw a possible interface and add a bit of AppleScript to animate it. The prototype could then be handed over to users and its usability could be assessed.

Drawing Interfaces in FaceSpan

Begin with whatever you know about the desired application's look and behavior and start creating windows in FaceSpan. This is a good time to review the Macintosh Human Interface Guidelines, also known as the human-computer interface (HCI) guidelines. I'm a big fan of following these, because applications that follow the guidelines are easier for users to learn and use. The FaceSpan Window Editor is a great environment to experiment with different layouts, but even more so, it's a place where the developer can see first hand the effects of following (or ignoring) the HCI guidelines. Here's a simple example. There are detailed rules for laying out the elements of a modal dialog box. The first dialog box below follows these rules to the letter, the second does not.


Figure 1. Conforming and Non-conforming dialog boxes.

Although the two contain the same buttons, the first conforms to the HCI guidelines. The default push button is in the right location, there is a correct amount of white space between the window items and the window border, and the icon is placed correctly. The result is a dialog box that is instantly recognizable to a Mac user. FaceSpan encourages this type of consistency throughout the application, but it by no means enforces it.

FaceSpan's Window Editor creates three different types of windows. Document windows are used for main windows. They can be resizable, closeable, and zoomable. Their optional titles are distinct from their name, as used in scripts. Modal windows can be titled or untitled and, unlike Document windows, must be closed before any other windows can receive events. The last window type is floating Windoid. These are windows that float on top of all Document windows. They are usually used for tool palettes.

A window contains zero or more window items. The upper limit of window items is 330. There are 14 different types of window items, and these types are further customizable using Forms. For example, the Button window item can have either a standard or a 3-D visual representation.

The Window Editor consists of a pair of tool palettes. The window under construction is displayed almost exactly as it will appear. New window items can be dragged onto the window, or drawn on the window. Window items have several properties that control their behavior. For example the visible and enabled properties determine if a particular window item is visible, and usable. If its enable property is false, it displays in a grayed-out style.

Figure 2. The FaceSpan Window Editor.

Figure 2 shows a complex preferences Modal window in FaceSpan's window editor. This window uses several window items, including labels, textboxes, boxes, checkboxes, and buttons (called push buttons by FaceSpan.)

In addition to the window editor, an application has full control over the menu bar. Basic menu capabilities are supported, as well as limited (single level) hierarchical menus. The menu bar support is the weakest portion of FaceSpan. Applications can have only a single menu item in the Apple menu and have no access to the Help menu.

Animating the Interface

There are three basic forms of interface behavior: workflow control, feedback, and application specific behavior. The next step in prototyping is to implement the first two forms. By workflow control I mean the degree to which the application controls what the user can do at any given point in time. This includes simple things like push button and menu sensitivity, as well as window interactions. It also includes managing dependant window items. Feedback is the use of visual and auditory messages in the application. For example, feedback is displaying a confirmation dialog box when the user closes a window, or playing a beep when invalid data is entered into a text box.

The first step is to get the ball rolling at application startup. Let's assume I have a prototype that needs to open three windows when it is launched. I make a project in the FaceSpan environment, draw three windows in the Window Editor, and then save the project as an executable. When the user double clicks the appliction icon in the Finder, it launches just fine, but no windows are displayed. I need to add some AppleScript to the project to link the launching event to several actions. When the user launches a FaceSpan application a run event message is sent to the project script. If the user drops a file on the application icon, an open event message and a list of file references is sent to the project script instead. I want to open three windows when the user launches the application, so I add an on run handler in the project script:

on run
  -- get prefs
  set {p1, p2, p3} to storage item "positions"
  open window "Call Manager" 
    with properties {bounds:p1}
  open window "Status" -
    with properties {position:p2, zoomed:false}
  open window "Call Manager - driver" 
    with properties {position:p3, zoomed:false}
end run

Most Macintosh applications keep track of window positions for the user. I can do that for my prototype as well. This handler uses a storage item to keep track of user placement of the windows. Storage items are named containers where an application can store and recall any type of data. The actual data is kept in the resource fork of the application. Recall that this is the executable version of the project file.

When the user double clicks the application icon, the on run handler of the project script is called. I begin by recalling three positions (positions are a FaceSpan datatype that specifies the x, y, width, and height of a window) from storage. I use each position to place and size each window exactly where the user left them when they last quit the prototype. I open each window use the open window command. A Window is controlled by the settings of its properties, and I can set the values of window properties in the open window command using the with properties modifier. I use this to set the initial position of each window to the stored value. I need to create the initial values for the three positions and save them in the "positions" storage item within the FaceSpan environment. I also need to somehow capture the current location and size of each window and update the storage item when the user quits the prototype.

Once a window is open the user can interact with it. They can click buttons, enter text into textboxes, check checkboxes and radio buttons, and so on. If there are no scripts attached to a window then these actions don't do anything specific to the prototype. The window behaves like a fill-in-the-blanks form. All the window items and the window itself will work, but unless the prototype does something with the information or actions the user takes, not much else will. FaceSpan does a lot of the hard work: the user can enter text into text fields, select radio buttons or checkmarks, tab between fields, scroll scrollable textboxes, and what not. What is missing is the application-specific actions that link the whole interface together.

For example, the modal dialog window in Figure 2 has a checkbox (displayed as a pull-down flag) labeled "Advanced Options." When the user toggles this checkbox "on" the window should expand to show the window items below it, and the OK push button should move down to the bottom. Clicking it again should collapse the window back to its original size and move the OK push button back to the original location. When I draw the dialog window in the FaceSpan Window Editor I set the OK push button growth property to move both. That tells FaceSpan to move it in both directions whenever the window size changes. In effect it becomes attached to the lower right corner of the window. What I want to do is resize the window between two fixed sizes, based on the setting of the "Advanced Options" checkbox. I add a handler to the script attached to the checkbox that resizes the window when the user changes the checkbox's value. That handler is very simple:

on hilited theObj
  if hilite then
    set height of my window to 555
  else
    set height of my window to 345
  end if
end hilited

When the user clicks to push a button, checkbox, or radio button window item the hilited event is sent to its attached script. The hilite property of the checkbox is true if it is checked and false otherwise. This little script changes the window size to one of two sizes, based on the hilite property value, each time the checkbox is clicked.

Figure 3.

I create lot of the animation of a prototype interface using similar techniques. Handlers for push button clicks (on hilited) or listbox selections (on selection made) usually enable or disable other window items, open or close other windows, or enable or disable menu items.

When the interface is fully animated the prototype is sufficient to answer a lot of questions about the final product. Does the interface work well? Is it easy to figure out how to accomplish a given task? Is feedback clear and consistent? The final step for a prototype is to add some or most of the application specific behavior. This is both a valuable and a dangerous step. Valuable because of what it can reveal about a potential design, and dangerous because if the prototype becomes "too functional" there is a real danger to ship it. By using FaceSpan and AppleScript, you are relieved of that danger, while still retaining the benefit of trying out a design before committing many hours to a C++ implementation. In other words, you're pretty much assured of having to throw away the prototype!

Adding Application-Specific Behavior

Adding application behavior is pretty much an exercise in AppleScript programming. The FaceSpan message hierarchy provides a lot of flexibility in the placement of handlers for FaceSpan event messages as well as application specific handlers. My job is to convert the various FaceSpan event messages into application-specific messages. FaceSpan event messages signal interface events (hilited, selection made, and so forth) while application-specific messages signal much higher-level events (produce a report, export to file, open database, and so on.) I then write handlers for those application-specific messages in AppleScript. This approach lets me reuse more of the design from the prototype because I'm able to separate the application-specific portions of each handler from the interface-specific portions. If I go on to implement the final application in C++ or Java, the interface code will be quite different than FaceSpan. The actual application specific behavior will also be coded differently, but the AppleScript code I write in the prototype can act as pseudocode.

A simple example is a push button in a window. When the user clicks the push button FaceSpan sends a hilited event message to its attached script, and then on to the window the button is in, and finally to the project script. The message flows along the message hierarchy until it is handled by a script, so I can place the on hilited handler wherever it makes the most sense. My rule is to place the handler in the script attached to the window or window item closest to the item generating the event message, unless a very similar action is performed regardless of which window item is generating it. For push buttons, I generally put the on hilited handler in the script attached to the push button. This handler converts the FaceSpan event message (hilited) into an application-specific function call. Function calls in AppleScript send a user-defined command message corresponding to the function name into the message hierarchy. Here's an example script that converts a FaceSpan event message to an application-specific user-defined command:

on hilited theObj set address to contents of textbox "digits" - as string sendCall(address) set contents of textbox "digits" to "" end hilited

The handler is from a prototype Call Management application. In this prototype the main window consists of a graphical representation of a call, a textbox named "digits", and a push button labeled "Send". When the user clicks Send, I want to extract the current phone number from the textbox and place a telephone call to that number. I then want to clear the textbox. There are two different things happening here. Getting the phone number and clearing the textbox are both interface-specific actions, so I take care of them in this handler. The second action is placing a call to the entered number. That has nothing to do with the interface, and I'd like to separate the code out so I can at least have the option of reusing the design. I do this by calling a user-defined function. This in effect converts the FaceSpan hilited event message into an application-specific event message named sendCall(). Now all I have to do is implement the AppleScript handler for sendCall(). This handler is totally separate from the FaceSpan interface, and can be placed in a script anywhere along the message hierarchy (window item, window, and project). Where this is placed depends on several factors, including the ultimate target implementation language. For this prototype, I placed the handler in the project script:

on sendCall(phoneNum)
  if isConnected then
    tell window "Status"
      setMsg("Dial " & phoneNum)
      enableWaiting()
    end tell
    tcp write data "Dial " & phoneNum & LF -
      stream tcpDialogSocket
  end if
end sendCall

In the handler I send a protocol message through a TCP/IP socket to a host application. I also enable what amounts to a thread in another window (again using an application-specific message named enableWaiting()) that uses the FaceSpan idle handler to poll a TCP/IP socket for a reply. I'm taking advantage of the excellent shareware TCP/IP Scripting Addition by Mango Tree Software to perform the TCP/IP operations.

Don't get too hung up on the actual code, what's more important is to understand what it shows. When I implement the actual application it's pretty clear that the code must write a string to a TCP/IP socket to make a call, and once it's done this it must wait for a response. This design applies just as well to the final application as it does to this prototype.

Object Oriented Programming

I generally take an object-oriented approach to application design. FaceSpan and AppleScript fully support object-oriented implementations. For those not interested in or concerned with objects, a purely functional approach can also be used. If objects are important to the prototype, then there are several options available when using the FaceSpan/AppleScript combination. FaceSpan's windows and window items are themselves objects, while AppleScript includes its own script objects.

Objects in FaceSpan

In FaceSpan, every window is considered a window template. This means that FaceSpan considers every window, including all its window items and attached scripts, to be a class of sorts. An application can either use the template directly, or it can create several instances of the template. Each instance contains a complete copy of the window, including window properties and attached script properties. Each window instance is assigned a unique window id property. The open window command opens a window based on the template created in the Window Editor.

Window items also are objects. They contain properties as well as data, and can be created and destroyed dynamically. When a window is created in the Window Editor, the initial set of window items is specified and their property values are set. The application has complete control over these values, and can even override them when the window template is opened. The following code fragment dynamically creates several window items in a window.

on displayCall(calledNumber, calledNumberId, -
    isActive, isRadio, isInConf, -
    isConf, lineFrom, nodeX, nodeY)
  local xPos, ypos, iconArt, lineProps
  set ypos to (nodeY * 60) - top
  set xPos to nodeX * 80
  
  if isRadio then
    set radioItem to id of (make radio button -
      with properties {position:{4, ypos},width:16,-
      height:16, script:none, hilite:isActive, -
      cnum:calledNumber, cid:calledNumberId} -
      at end of window id theWindow)
    set index of window item id radioItem to 2
  end if
  
  set theIndex to -
    (index of graphic line "divLine") + 1
  if isConf then
    set iconArt to {class:resource info, -
      type:"cicn", name:"group", id:5001}
  else
    set iconArt to {class:resource info, -
      type:"ICON", name:"Big Off Tone", id:5002}
  end if
  
  set iconItem to id of (make icon with properties-
    {artwork:iconArt, position:{4 + xPos, -
    ypos - 10}, width:36, height:36, -
    draggable:true, droppable:true, script:none,-
    selection rule:as push button, -
    balloon:"ISP Id is: " & calledNumberId, -
    cnum:calledNumber, cid:calledNumberId, -
    conf:isInConf} at end of window id theWindow)
  set index of window item id iconItem to theIndex
  
  if (lineFrom = -1) then 
    set lineProps to {position:{18, ypos + 8}, -
      width:80, height:1, script:none}
  else if (lineFrom = 0) then 
    set lineProps to {position:{(80 * (nodeX - 1)) -
      + 22, ypos - 60}, width:1, height:68, -
      script:none}
  else
    set lineProps to {position:{(80 * lineFrom) + -
      14, ypos + 8}, width:80 * (nodeX - lineFrom),-
      height:1, script:none}
  end if
  
  set lineItem to id of (make graphic line -
    with properties lineProps -
    at end of window id theWindow)
  set index of window item id lineItem to theIndex
  
  if (lineFrom = 0) then
    set lineItem to id of (make graphic line -
      with properties {position:{(80 * (nodeX - 1))-
      + 22, ypos + 8}, width:72, height:1,-
      script:none} at end of window id theWindow)
    set index of window item id lineItem to theIndex
  end if
  
  set labelItem to id of (make label -
    with properties {position:{xPos + 10, ypos + -
    24}, width:80, height:16,contents:calledNumber,-
    script:none} at end of window id theWindow)
  set index of window item id labelItem to theIndex
  
end displayCall

This is a meaty handler that creates several window items. It shows several interesting things. First, the algorithm used to place the radio button, icon, label, and lines is reusable. I used virtually the same algorithm in a Java and a NewtonScript version of the final application. Second, the application has total control over the placement and property values for window items it creates. Third, I'm adding application-specific properties to the radio button and icon window items. I use these window items to hold information I need (caller number and conference information) to associate with the call, but don't want to store separately. Finally, notice that each window item has its script property set to none. This is one case where I take advantage of the FaceSpan message hierarchy for performance reasons. Whenever one of these window items generates an event message I can handle it in the window's attached script with a general handler. Here's the hilited event handler:

on hilited theObj
  try
    if class of theObj is radio button then
      set theCallId to cid of theObj
      switchCall(theCallId)
    end if
  on error
  end try
end hilited

I dynamically create radio buttons, icons, graphic lines, and labels as children of the window. Of these, only radio buttons and icons generate the hilited event message. In this prototype I don't want to perform any actions if the user clicks one of the dynamic icons, and there are no other radio buttons in the window except those I create dynamically. When I add the on hilited hander to the script attached to the window, it is called whenever the user clicks something (radio button, checkbox, push button, or icon) in the window, but only if that window item does not include its own on hilited hander in its attached script. In this case I need to verify only that the class of the sender of the message is radio button. If it is, then it must be one of my dynamically created ones.

I use the class of operator to determine if the object generating the message is a radio button. If it is, then I convert the FaceSpan event message into an application specific message named switchCall(). I retrieve the application specific property cid from the radio button, since that's the id that the server process knows about. This is an example of treating window items like objects, since each item contains its own unique data.

Objects in AppleScript

AppleScript also has its own little-used object/class system. Each script in AppleScript is considered a Script object that contains methods (called handlers) and data (called properties.) The script/end script command defines a script object within a script. The basic form is:

script className
  property parent: otherClassName

  property p1: value1

  on handlerName(params)
  end
end script

A script object can have zero or one parent script property, zero or more other properties, and zero or more handlers. This is more like Java than C++ since there is only single inheritance. There is also no private or protected data or methods. Everything is public. For prototyping, this is not a major hardship. Script objects are a little different than classes in most object-oriented languages in that the script/end script commands actually make a single instance. In the above example the commands make a single instance of the class named className. To make several instances of the class I'd have use the copy command to copy className. Instead of doing this, I can place the script/end script commands in a handler. Then the handler acts like a constructor. Every time I call the constructor a new instance of the class is created. Parameters to the hander can be used in the property statements of the script to provide initial values to newly created objects. This is an example of a simple constructor handler:

on makeMyObj(name)
  script myObj
    property myName: name
    on getName()
      return myName
    end getName
  end script

  return myObj
end

Calling makeMyObj("Fred") returns an instance of the myObj script object with its myName property initialized to "Fred".

Combining script objects with FaceSpan allows for encapsulating all of the handlers and data associated with a group of dynamic window items into one object. I use this technique to bind all the methods and data for a meeting in a meeting object in an example in by book, AppleScript Applications: Building Applications in FaceSpan and AppleScript, in the DateMinder application. This application implements a PIM that includes a Day view. The Day view is a window that displays a cluster of three window items for each meeting in a day. Here is a portion of the constructor and script object for a meeting:

on makeDayItem(itemclass, itemDetails, itemNote)
  local pos, startAt, meetingLength
  
  if itemclass = "Meeting" then
    set {pos, startAt, meetingLength} to itemDetails
    updateCalendarMeetMarks(startAt, true)
  else
    set startAt to 0
    set meetingLength to 0
    set pos to itemDetails
    updateCalendarOtherMarks(itemclass, true)
  end if
  
  script DayObject
    property theIndex : 0
    property barIndex : 0
    property iconIndex : 0
    property textIndex : 0
    property myPos : pos
    property myTime : startAt * 15 * minutes
    property myLength : meetingLength
    property myClass : itemclass
    property myNotes : itemNote
    

    on getItemInfo()
      if itemclass = "Meeting" then
        return {itemclass:myClass, xPos:myPos,-
          starttime:myTime, duration:myLength, -
          notes:myNotes}
      else
        return {itemclass:myClass, xPos:myPos, -
            notes:myNotes}
      end if
    end getItemInfo
    
    on resizeMeeting(theObj)
    end resizeMeeting

    on createImage()
    end createImage

    on updateMeeting(newTime, newDuration, newText)
    end updateMeeting

    on move (theInfo)
    end move

    on redraw()
    end redraw

    on openWindow()
    end openWindow

    on closeWindow()
    end closeWindow

    on windowName()
    end windowName

    on updateWindow()
    end updateWindow

    on adoptDetailWindow(oldWindowName)
    end adoptDetailWindow

    on updateItemText(newNote)
    end updateItemText

    on updateItemTextAndDisplay(newNote)
    end updateItemTextAndDisplay

    on remove()
    end remove
    
  end script
  
  return DayObject
  
end makeDayItem

I call the makeDayItem() handler to create a day item object. Once it is created I draw it's graphical representation in the Day window by calling the createImage() handler. An example of this is in the handler called when the user drags an icon onto the window to create a new meeting:

on newDayItem(theClass, theInfo)
  local theDayItem
  set theDayItem to -
    makeDayItem(theClass, theInfo, "")
  set end of theDayItems to theDayItem
  tell theDayItem to createImage()
end newDayItem

In this handler I create a new day item object by calling the day item constructor handler, and save the object in a list of all day items stored in a property. I then call the createImage() handler in the object to draw the object in the window. Any script needing to access data associated with the object, or to change its contents or location, need call only handlers in the object. I don't have to know how it is implemented, what window items are associated with it, or how to modify their properties. As I said, it's a powerful combination.

Moving From Prototype to Product

Once the prototype is completed and ready to retire, I don't just ignore it. Rather it can be mined for valuable information. The interface will have to be reimplemented in the target language (using PowerPlant, or the Constructor for Java, or by hand coding, depending on the implementation language). The prototype serves two roles here: it acts as a guide when laying out the interface and as a specification for naming the elements of the interface.

The same holds true for the AppleScript scripts. They act as a high-level specification language for the final code. Algorithms implemented in AppleScript are highly reusable, as are data structures and class hierarchies. I'm not suggesting that it's just a matter of "porting over" to C++ or Java, but at least I've already got a working solution to use when I'm doing the final implementation.

One Example of a Prototype That Worked

This is not just some abstract article - I've used these techniques many times when creating prototypes for GTE Laboratories. Here at the labs fast turn around times are critical when we're mocking up applications. By using this method and these tools, I've created many successful demos using AppleScript and FaceSpan. When we recreate a particular application in a production system, we first capture the design by dissecting the prototype.

One such example is a Call Management client application for an Internet telephony project. This application drives a server front end to allow the user to create and manage many telephone calls. Calls can be placed, merged into conferences, and dropped. Furthermore the user can have many calls active at the same time. The ultimate implementation target for the client application was Java, but much of the protocol used to communicate between the client and server was undefined and we needed a usable prototype in just two weeks. Using the method outlined in this article, and the TCP/IP osax from Mango Tree Software, I was able to create a professional prototype with a direct manipulation interface. This prototype carried us through the demo, and then was used for the final Java application over the next two months. The running application is shown below.

Figure 4.

As you can see, the application looks and behaves like any other Macintosh application. The icons on the scrolling display support drag & drop -- just drag a phone icon on top of another to merge the calls into a conference, or drag a phone icon out of a conference and onto the main window to split that call out of the conference.

Building this prototype in FaceSpan and AppleScript let me focus on the important details including creating a layout algorithm for the call graph, finalizing and debugging the TCP/IP protocol between client and server, and creating an enjoyable and usable interface for call manipulation. I didn't need (or have time) to struggle with the details of coding the application in C++ or Java. Even so, I was still able leverage the time spent on the prototype when building the final version in Java. I also re-implemented it in a custom NewtonScript application. Even there the time spent on the prototype reaped large rewards when designing the GUI in the Newton Toolkit and implementing the application in NewtonScript.

Prototyping Can Work For You

There are at least three good reasons to create a prototype before building an application. A prototype can help answer tough questions about an interface: how usable is it, does it work better one way or another, what is the optimal placement of controls in a window. A prototype is usually ready to use in short order and can fill in for the final application while it is being written. A prototype also lets you play "what if" games with different algorithms and data structures. As long as you're willing to throw it away, it's almost always worth the investment in time.

FaceSpan and AppleScript provide a powerful and rich environment for rapid prototyping. FaceSpan interfaces can be designed such that they are full Macintosh interfaces. The tool provides a fast way to mock up interfaces, and those interfaces can be quickly modified as the prototype evolves. In a similar manner AppleScript is a wonderful prototyping language. The syntax is like psuedocode, so the resulting scripts act as documentation when moving to C++ or Java. It supports object-oriented programming, as well as a huge library of osax building blocks and access to scriptable applications. These tools and this method are valuable additions to any programmer's toolbox.

References


John Schettino is an author and Senior Member of the Technical Staff at GTE Laboratories, Inc. He is the co-author of the books BASIC for the Newton: Programming for the Newton with NS BASIC and AppleScript Applications: Building Applications with FaceSpan and AppleScript, both published by AP Professional. He is also a contributing editor for the Handheld Systems Journal and for the web eZine Mobilis, where he writes about Newton and WindowsCE. You can reach him via http://members.aol.com/pdcjohns.

 

Community Search:
MacTech Search:

Software Updates via MacUpdate

Latest Forum Discussions

See All

Tokkun Studio unveils alpha trailer for...
We are back on the MMORPG news train, and this time it comes from the sort of international developers Tokkun Studio. They are based in France and Japan, so it counts. Anyway, semantics aside, they have released an alpha trailer for the upcoming... | Read more »
Win a host of exclusive in-game Honor of...
To celebrate its latest Jujutsu Kaisen crossover event, Honor of Kings is offering a bounty of login and achievement rewards kicking off the holiday season early. [Read more] | Read more »
Miraibo GO comes out swinging hard as it...
Having just launched what feels like yesterday, Dreamcube Studio is wasting no time adding events to their open-world survival Miraibo GO. Abyssal Souls arrives relatively in time for the spooky season and brings with it horrifying new partners to... | Read more »
Ditch the heavy binders and high price t...
As fun as the real-world equivalent and the very old Game Boy version are, the Pokemon Trading Card games have historically been received poorly on mobile. It is a very strange and confusing trend, but one that The Pokemon Company is determined to... | Read more »
Peace amongst mobile gamers is now shatt...
Some of the crazy folk tales from gaming have undoubtedly come from the EVE universe. Stories of spying, betrayal, and epic battles have entered history, and now the franchise expands as CCP Games launches EVE Galaxy Conquest, a free-to-play 4x... | Read more »
Lord of Nazarick, the turn-based RPG bas...
Crunchyroll and A PLUS JAPAN have just confirmed that Lord of Nazarick, their turn-based RPG based on the popular OVERLORD anime, is now available for iOS and Android. Starting today at 2PM CET, fans can download the game from Google Play and the... | Read more »
Digital Extremes' recent Devstream...
If you are anything like me you are impatiently waiting for Warframe: 1999 whilst simultaneously cursing the fact Excalibur Prime is permanently Vault locked. To keep us fed during our wait, Digital Extremes hosted a Double Devstream to dish out a... | Read more »
The Frozen Canvas adds a splash of colou...
It is time to grab your gloves and layer up, as Torchlight: Infinite is diving into the frozen tundra in its sixth season. The Frozen Canvas is a colourful new update that brings a stylish flair to the Netherrealm and puts creativity in the... | Read more »
Back When AOL WAS the Internet – The Tou...
In Episode 606 of The TouchArcade Show we kick things off talking about my plans for this weekend, which has resulted in this week’s show being a bit shorter than normal. We also go over some more updates on our Patreon situation, which has been... | Read more »
Creative Assembly's latest mobile p...
The Total War series has been slowly trickling onto mobile, which is a fantastic thing because most, if not all, of them are incredibly great fun. Creative Assembly's latest to get the Feral Interactive treatment into portable form is Total War:... | Read more »

Price Scanner via MacPrices.net

Early Black Friday Deal: Apple’s newly upgrad...
Amazon has Apple 13″ MacBook Airs with M2 CPUs and 16GB of RAM on early Black Friday sale for $200 off MSRP, only $799. Their prices are the lowest currently available for these newly upgraded 13″ M2... Read more
13-inch 8GB M2 MacBook Airs for $749, $250 of...
Best Buy has Apple 13″ MacBook Airs with M2 CPUs and 8GB of RAM in stock and on sale on their online store for $250 off MSRP. Prices start at $749. Their prices are the lowest currently available for... Read more
Amazon is offering an early Black Friday $100...
Amazon is offering early Black Friday discounts on Apple’s new 2024 WiFi iPad minis ranging up to $100 off MSRP, each with free shipping. These are the lowest prices available for new minis anywhere... Read more
Price Drop! Clearance 14-inch M3 MacBook Pros...
Best Buy is offering a $500 discount on clearance 14″ M3 MacBook Pros on their online store this week with prices available starting at only $1099. Prices valid for online orders only, in-store... Read more
Apple AirPods Pro with USB-C on early Black F...
A couple of Apple retailers are offering $70 (28%) discounts on Apple’s AirPods Pro with USB-C (and hearing aid capabilities) this weekend. These are early AirPods Black Friday discounts if you’re... Read more
Price drop! 13-inch M3 MacBook Airs now avail...
With yesterday’s across-the-board MacBook Air upgrade to 16GB of RAM standard, Apple has dropped prices on clearance 13″ 8GB M3 MacBook Airs, Certified Refurbished, to a new low starting at only $829... Read more
Price drop! Apple 15-inch M3 MacBook Airs now...
With yesterday’s release of 15-inch M3 MacBook Airs with 16GB of RAM standard, Apple has dropped prices on clearance Certified Refurbished 15″ 8GB M3 MacBook Airs to a new low starting at only $999.... Read more
Apple has clearance 15-inch M2 MacBook Airs a...
Apple has clearance, Certified Refurbished, 15″ M2 MacBook Airs now available starting at $929 and ranging up to $410 off original MSRP. These are the cheapest 15″ MacBook Airs for sale today at... Read more
Apple drops prices on 13-inch M2 MacBook Airs...
Apple has dropped prices on 13″ M2 MacBook Airs to a new low of only $749 in their Certified Refurbished store. These are the cheapest M2-powered MacBooks for sale at Apple. Apple’s one-year warranty... Read more
Clearance 13-inch M1 MacBook Airs available a...
Apple has clearance 13″ M1 MacBook Airs, Certified Refurbished, now available for $679 for 8-Core CPU/7-Core GPU/256GB models. Apple’s one-year warranty is included, shipping is free, and each... Read more

Jobs Board

Seasonal Cashier - *Apple* Blossom Mall - J...
Seasonal Cashier - Apple Blossom Mall Location:Winchester, VA, United States (https://jobs.jcp.com/jobs/location/191170/winchester-va-united-states) - Apple Read more
Seasonal Fine Jewelry Commission Associate -...
…Fine Jewelry Commission Associate - Apple Blossom Mall Location:Winchester, VA, United States (https://jobs.jcp.com/jobs/location/191170/winchester-va-united-states) Read more
Seasonal Operations Associate - *Apple* Blo...
Seasonal Operations Associate - Apple Blossom Mall Location:Winchester, VA, United States (https://jobs.jcp.com/jobs/location/191170/winchester-va-united-states) - Read more
Hair Stylist - *Apple* Blossom Mall - JCPen...
Hair Stylist - Apple Blossom Mall Location:Winchester, VA, United States (https://jobs.jcp.com/jobs/location/191170/winchester-va-united-states) - Apple Blossom Read more
Cashier - *Apple* Blossom Mall - JCPenney (...
Cashier - Apple Blossom Mall Location:Winchester, VA, United States (https://jobs.jcp.com/jobs/location/191170/winchester-va-united-states) - Apple Blossom Mall Read more
All contents are Copyright 1984-2011 by Xplain Corporation. All rights reserved. Theme designed by Icreon.