Configure player

Close

WWDC Index does not host video files

If you have access to video files, you can configure a URL pattern to be used in a video player.

URL pattern

preview

Use any of these variables in your URL pattern, the pattern is stored in your browsers' local storage.

$id
ID of session: wwdc2006-102
$eventId
ID of event: wwdc2006
$eventContentId
ID of session without event part: 102
$eventShortId
Shortened ID of event: wwdc06
$year
Year of session: 2006
$extension
Extension of original filename: mov
$filenameAlmostEvery
Filename from "(Almost) Every..." gist: ...

WWDC06 • Session 102

Make Your Application Scriptable

Application Technologies • 45:45

Learn how to give your application the power to respond to AppleScript commands. We'll introduce you to the key concepts of scriptability, show you how to design and create an AppleScript terminology for your application, and then explain how to implement the code needed to make it work.

Speaker: John Comiskey

Unlisted on Apple Developer site

Transcript

This transcript was generated using Whisper, it has known transcription errors. We are working on an improved version.

Good morning. Thank you for being here. My name is John Comiskey. I'm an engineer in the AppleScript group, and my job is to help people make their applications scriptable. There may be some of you that support a Carbon application. The stuff that we're going to be talking about today applies equally to both Carbon and Cocoa, but the Carbon usage requires a little bit of setup. So if you are in that situation, please come and find us in our lab immediately after this session, and we'll help you take care of that part. After that, everybody can use Cocoa scripting.

So what we're going to talk about today, several topics. Why should your application be scriptable? How do you start by designing a dictionary? The importance of logging what your program does. Then we're going to cover a few topics in basic scriptability for those of you that are just getting started. And for a few of you that I've seen before and are getting into more advanced topics, we're going to cover an advanced topic in scriptability. And then at the end, we're going to talk about the importance of testing your application with scriptability and testing your scriptability.

But first, we're going to talk about figure skating. I don't know anything about figure skating, which is why I was really surprised to come in one morning and see this, that my boss wanted me to revolutionize print media coverage of international pairs figure skating competition. And I had absolutely no idea how to do that. So I rubbed my eyes, I shook my head, and I took another look.

And it was really more like this. I was supposed to implement a scriptable object model in Aperture. Aperture was a new product, hadn't even been released yet. It's the first pro app from Apple to come out with scriptability in first release. And myself and James Dempsey, you may have seen James yesterday performing an original composition on the guitar. He and I sat down together and put scriptability into Aperture.

And this turned out to be very beneficial for a group of people. There's a photographer, Vincent Laforet. He used to work for the New York Times, and now he works independently. And he drew the assignment to go to the Olympics in Turin. and to cover the pairs figure skating. He knew that the way the competition worked, there's several minutes of skating, then there's just a brief interlude between skaters, and then another pair goes out there.

He had to make a decision what to do with his time. It's very difficult for a photographer to shoot an event and to also upload his pictures into a computer, do some editing, do some selecting, move the best pictures on through the workflow so that they can be published, and then get back to the skating. He knew he wouldn't be able to do that. He knew he would miss something, and he didn't want to miss anything. And it's a good thing that he didn't.

John Comiskey So what he did is he took Aperture, which is a scriptable product, and he built some automation around it. He would take the magnetic card out of his camera, put it into his laptop at ringside, image capture would come up, and start running an automator workflow.

The automator workflow would take the pictures off the card, bring them into Aperture, create thumbnails for them, take those thumbnails and put them in a folder that was accessible across the network. When that happened, his editor, who was over at the Kodak Pavilion in another part of Turin, had folder actions on that folder. So as soon as the pictures arrived, he was notified that there was work there for him to do.

He loaded those pictures into Aperture again, went through the thumbnails, and picked out the best shots, the ones that he knew they wanted to publish. Then he'd run another Automator workflow, which would go back to the computer at rink side, grab the full size image of that picture, pull it over to the Kodak Center, where he could crop it, edit it, do whatever fix-ups he needed to do, and drop it in another folder where another scriptable application, a transmit from a third-party vendor like you guys, took that photo and sent it via FTP to New York.

And Vincent captured probably the moment of the pair skating competition. Rene Anouilh and Jack Baldwin are the American skaters, and although they finished seventh, they did something that no one else had ever done before. They successfully completed a throw triple axel in international competition. It's never been done before, it's never been done since, and it's probably going to be the new standard. If you can't do a throw triple axel, you're not going to be a competitive pair.

Vincent got that shot, got it to his editor, got it to New York. So with the help of Aperture, Transmit, Automator, Folder Actions, AppleScript, the internet, and Nine Time Zones, he was able to get that picture published in the morning paper in New York before it showed up in the afternoon papers in Turin.

Meanwhile, all the other photographers were jumping on motor scooters, running across town to the Kodak Pavilion, frantically editing their photos. Vincent was able to scoop everybody else, and he was able to do it by using automation. So this is actually not Jack Baldwin and Renee Inouye. This is Tatiana Tamianina and Maxim Maranin. They're the gold medalists from Turin.

So that's a little lesson in why you want to be scriptable. You have a decision to make. Should you spend your time on scriptability or something else? I want to convince you to spend your time on scriptability because scriptability is something else. When you make your application scriptable, you get to join a club.

It's not a fancy, exclusive club. Anybody that does the work can get in. And the club's been around for a long time. You've been able to use AppleScript since System 7. But since then, we've done a few other things. AppleScript Studio came along a few years ago, which allowed you to make real applications out of your AppleScripts, to put real user interfaces on them, package them, and distribute them to your end users so that they could use the power of AppleScript in a nicely packaged application.

More recently, we came out with Automator, which is automation for the rest of us. For people who are not programmers or who do not feel comfortable writing scripting languages, they can use Automator to drive all the same scriptable programs that AppleScript does, but it's a lot easier for them. All they need to know is what they want to do, not exactly how to do it. And if you were at the developer technologies event, you could use Automator to drive all the same scriptable programs that AppleScript does, but it's a lot easier for them.

All they need to know is what they want to do, not exactly how to do it. Excuse me. If you were at the Developer Technologies preview yesterday, you heard about Scripting Bridge. What's that? Well, come back at 5 o'clock to see the Controlling Scriptable Application session. Scripting Bridge is a very interesting piece that completes the puzzle. We'll allow one Cocoa application to drive another Cocoa application to use its objects as if it were their own.

There's more reasons why you might want to make your application scriptable as well. First is loyal customers. Once your application is in somebody's automated workflow, there's very little chance that they will ever get rid of your application. They may dabble with your competitor's product, they may use it for a few things, but whenever they do that automated workflow, they're going to use your product. I see Joe Pizzillo is in the back there. Hi, Joe. He came to our Making Your App Scriptable session two years ago, and he brought his product Anthracite from Medify, his company.

And we started working on making it scriptable. We met again last year, and he was very nearly done, and we polished off a few rough edges. And now he's back again, and we're going to talk about recordability this week. Joe has found that our story is true. When people start using your application in their automated workflows, they're locked in, and they never get rid of it. And he's seen sales go, as he said last night, through the roof because of the scriptability of his application.

You can also let your customers set the agenda. You can't possibly anticipate everything that they're going to want to do, but you can give them some tools to construct their own solutions. An example of that is, you've certainly heard of OmniOutliner. It's an excellent outlining program. John Comiskey Well, there's another product called Kinkless GTD. Kinkless GTD is an AppleScript.

It's a very complex and powerful AppleScript that implements a system for getting things done, hence the name GTD. It's essentially an application built on top of another application. The power of object model scriptability allowed Kinkless GTD to build a whole new product on top of OmniOutliner. Now, both OmniOutliner and Kinkless GTD are benefiting in sales from this synergy that they've created. You can create synergy with other applications from your own house or from others.

The last thing that we really think is important is testing. It's the most immediate benefit that you get. As soon as you make your application scriptable, it's instantly easier to test. My testers wouldn't be able to do what they do without AppleScript. John Comiskey An example of this is, I'm sure you're familiar with the Microsoft Office suite. Its scripting dictionary is fantastic.

They've covered all the bases. They've touched every part of their program. There's hardly anything that you can do in Word or Excel or PowerPoint that you cannot also do through scriptability. John Comiskey The irony of this is they did it all for testing. They weren't even going to release it to their end users. They did it all for testing.

Only because your friend and I, Sal Segoian, saw this in operation in their labs and said, "You have to get this to your customers. You absolutely have to." That's the reason why the Microsoft Office suite has such rich, powerful object model scripting. They did it for themselves. They did it for their testers. Now, it's a big part of their product.

How to get started. We always encourage people to start with dictionary design. It's the route from which everything else flows. It tells you how to write your code. It tells you how the scripters are going to write their code. And it's very important to spend time upfront on dictionary design.

It'll solve lots of problems for you. You might feel a little trepidation when you do dictionary design that your application's too big and that you've made too many things scriptable. That's okay. Draw a nice line around what you think you can accomplish in the first release and go ahead and do that.

And then that'll give you a roadmap for your future. The importance of designing an entire dictionary before you start is you won't paint yourself into any corners. You won't realize a year from now, oh my, I should have done this a different way. It would have been a lot easier.

If you visualize your entire object model first, you can avoid some of those problems. And if you want to do that, and if you want to do it right, we've got a couple of things that you can look at that will help you out. The scripting interface guidelines, Chris Neville made sure that these are very complete and up to date.

They're published as Tech Note number 2106. And they guide you in a certain direction. They tell you that you should be providing tools for your end users rather than trying to solve individual problems. Your list of to-dos will just keep growing and growing and growing if you try to solve individual problems. But if you give your scripters tools to solve the problems themselves, you can spend a lot more of your time on more productive ends. So you empower your users.

You don't have to do all the work. trying to anticipate what they need you give them the power to solve their own problems also by following the guidelines you'll be more consistent and you'll interoperate better with other applications because you'll be speaking the same language One of the toughest parts of designing a dictionary is assigning the four byte codes.

The four byte codes are the actual medium of exchange, program to program. The scripter never sees them. Once you assign them, you probably never see them unless you're doing some debugging. But it's important that you pick the right ones. And we've finally done something to help you out.

Cheryl Evie put together a web page with about 3,000 four byte codes and the matching human terminology. The rules are simple. If you use the same human terminology, use the four byte code that's already being used. And vice versa, if you use the same four byte code, it should mean the same human term. And you can look things up there.

The best way to find this is just go to the developer website, search for Apple event codes, and the first thing on the list should be this page of four byte codes. I strongly encourage you to consult that before you release your scriptability for the first time. It can save you lots of headaches.

Every time I talk to people about putting scriptability in their app, I talk to them about logging. Cocoa Scripting uses your application as a set of callbacks. And whenever AppleScript needs something from your application, Cocoa Scripting will route that to a particular method on a particular object and ask for that information.

After you get used to it, it's all very logical and it all makes perfect sense. But when you're first getting started, it's difficult to learn just exactly what Cocoa Scripting is going to do and just exactly what it's going to do next after that. So I strongly encourage people to put a logging mechanism into their application so that they can follow this activity.

In the past, I've shown just a really simple logging mechanism. It's a macro. There's a switch that turns it on and off. I've got two of them in case I want to provide a little bit of extra information besides just a logging string. But even just a logging string that says, I'm here, is probably going to cover most of what you need.

But with the help of Brook Callahan, there's been a huge leap forward in logging technology. I've now got a much more complicated macro. But this macro puts interesting information into the console log, like the file name, the line number, the function that's being executed, and then any other information that you tack on to the end of that.

Whether you choose the simple or the complex, it doesn't matter. As long as you have a way of figuring out where your program's been and what it's done and how it's interacting with Cocoa Scripting, then you'll learn a lot about how Cocoa Scripting works and what it expects from you.

This is a sample script that matches our demo today. Or no, it doesn't. It's from System Events. And all it does is it finds out whether the script menu is enabled or not. And you'll see at the bottom that there's a couple of sample log entries that come back when you do this. And in there, the file name is highlighted.

The line number that you're executing is noted. The function that is being called is there. And a little bit of extra information, which is the input to this method, is also shown. This is going to be invaluable if you're trying to figure out what your program is doing and why it might not be doing things right.

We want to introduce people who are new to scriptability to some of the simple things and how to do the easy first steps to get started. So we're going to have a demo of basic scriptability. But before I get to that, I'm going to tell you a little bit about something we're not going to cover. Element accessors are very important.

Element accessors allow Cocoa Scripting to get at the objects in your application. In AppleScript, objects are things inside of other things. It's a hierarchical containment relationship. So in order to get, say, a document from your application, and then a paragraph from your document, and then a word from that paragraph, you're going to need element accessors. There's several different kinds. The most basic one accesses the entire collection all at once. So if you said, get every document, a documents method would be called.

If you said, get every graphic, a graphics method like this one up here would be called. And your job at that time is to return an array with the entire set of objects. This might not be the best way for your application to work. If you've got a very large collection of objects, or if it's difficult to assemble them all in one place at one time, you might want to use some of these other methods.

You can get at an individual object by its index, you can get at an individual object by its name, and you can get at an individual object by a unique ID. If you support a large database, you might want to use these more efficient accessors to get at that stuff so you don't have to constantly take the entire million record database and send it back to Cocoa Scripting.

For managing elements, you're going to need to be able to create and delete them. So there's two different ways to insert objects into your collection. The first method up here is a method where the order doesn't matter. Sometimes things have a natural order. If you make a new window, for instance, you're always going to want to make it in front. You don't want to make a new window in the back where nobody can see it.

But if, for instance, you do want to make a new window in the back where nobody can see it, the second method will allow you to do that. It'll make the window and it'll insert it in the collection at a specific index. Eventually, you're going to need to get rid of things. The method here, remove from graphics at index, is the method that you'd use to remove a graphic from the connection.

You'll want to provide both insertion and deletion accessors for any objects that you know the users are going to want to create and delete. And every good scriptable object has an object specifier. In order to get back to that object a second and a third time, it needs to be able to describe itself somehow.

So every scriptable object that you create should have an object specifier method on it that returns a description of how to get to this object. So, for instance, Word 5 of Paragraph 3 of Document 1. That will take you back to the same place over and over again. And so your objects need to be able to identify themselves in this way.

What we are going to talk about in our little demo today is properties. Property accessors are methods of a scriptable object, and they're pretty simple. If you're familiar with KVC and KVO, they follow the same naming pattern. These are the accessors that get the name of an object and can set the name of that object. If you're using KVC and KVO for other purposes, you may already have a lot of these accessors in your program. then it's just a matter of defining your dictionary to get access to them. So now I'm going to do a short demo on logging and basic scriptability.

This is the Sketch application, which is part of our sample code available on developer.com, and we've made some modifications to it. First thing I've done is I've added this header file, which has got my logging macro in it, and you can see I've turned the master switch on, so whatever I do, the logging is going to happen, and I'll be able to see what's happening while I'm running my program.

One of the things that people forget to do is to make their preferences scriptable. We have a tendency to think the users are going to set the preferences once and then forget about them, and that's largely true. But there are other groups of people that are interested in this.

Your own testers, for instance, will love you if you make the preferences scriptable. They need to set up multiple machines multiple times every day, and if there's an automated way to do it, that's great for them. Other people that like this are anyone that administers a large group of machines at a school or in a lab and needs to go around and set the preferences on a dozen different machines all at once.

They'll like having scriptable preferences. So Sketch, as it turns out, only has two preferences. One is a checkbox to say whether or not it should be auto-saving the document, and the second is an integer that tells the interval at which to save the document, and we're going to make those scriptable. So you can see here, I've got my method that gets the autosave state and tells me what it's set to right now. And I've got a second method to set the autosave state. So now we've got a read/write property.

Also down here, we've got another pair of matching accessors, one to get the autosave interval and the other to set the autosave interval. I've been telling people, including earlier today, that if you're using KVC and KVO, you're a jump ahead. And this illustrates one of the reasons why. The only thing that I have to do to make this work is to talk to the shared user defaults controller and say, I want to set this value, auto-saving delay.

John Comiskey The rest of Sketch is hooked up with Cocoa Bindings so that the feedback to the user is automatic and you don't have to do anything. So if you're using technologies like Cocoa Bindings, making your application scriptable gets even easier. John Comiskey So we're going to run this.

I'm going to run an AppleScript to show how it works. So these are the sketch preferences. Like I said, there's only two. And right now, autosave is off, and the interval is set to the default, which is 60 seconds. Our script is going to change those values and then change them back just for purposes of demonstration. This is a good example of a round trip test that puts things back the way it was. You're going to want to use those because it simplifies your testing.

So you can see, every time I click run on the AppleScript, the state of the preferences changes, and the visual feedback to the user is automatic. All we're doing is talking to the permanent store of the preferences, and Cocoa Bindings takes care of the rest. We didn't have to write any code to get this visual feedback to work.

And here's what's happening with our logging. We find that the SDF parsing is stricter in Leopard than it was in Tiger. Here's an example of autosave being turned on, autosave being turned off, and as you can see, I repeated that process twice. And this is all in the log. So now we know what Cocoa Scripting did and how our program reacted to it.

Another thing that people sometimes forget to do is to make the selection scriptable. It's important to have a scriptable selection for a couple of reasons. Script menu is one of them.

[Transcript missing]

The selection is going to return an array of all the objects that are selected at the present time.

But we want more than that. We want to be able to find out if an individual graphic is selected, and this accessor will allow you to do that. And most importantly, we want to actually be able to select things. So this final accessor will allow you to turn selection on and off.

So if we bring Sketch forward and we put some graphics in the window, and I'll select two of them and leave two of them unselected. So the easiest and the most direct way of demonstrating this is to just go ahead and get the selection. And this would be the first line of a script menu script to get the selection from Document 1 and then do some kind of action on it.

So we can see that it tells us that Graphic 1 and Graphic 4 in the window are the ones that are currently selected. We also want to be able to get at the property that tells us whether an individual Whether an individual graphic is selected, and we can do that as well.

And one of the most powerful parts of this is the ability to use selection as part of a who's clause. So if you want to find every blue rectangle who's selected as true, you can do something like that. And again, your users can use this to construct automator actions and script menu scripts that will help them get their work done.

And we've made this all read-write so that we can-- We've made this all read/write so that we can actually change the selection. And I've got a little We have a little junior animation here that we'll show you. We can control the selection from AppleScript now, as well as just asking about it. And that's our demonstration of simple scriptability.

This is where you should start. Just make a few things scriptable, make a few properties of the application, get the selection, start with something like this, and you'll already have something that'll be useful to your users, and then you can build on that. So what you just saw is we showed you the results of the logging, how you can tell how Cocoa Scripting is calling your application, and we've shown you how to write accessors that get and set some simple properties.

There's been a lot of development in Cocoa Scripting in the past couple of years, and there's new capabilities. One of the things that we've been asking you to do is to migrate your scriptable applications from Script Suite and Script Terminology files to SDEF files. And the reason you'll want to do that is the SDF format allows you to define a much richer dictionary with a lot more information in it that will help your scripters use your application and get at the power of it. In order to do that, you're going to have to register an Apple event handler, which is something you never had to do before. Cocoa Scripting took care of all of that for you. And this is the handler that you're going to want to register.

You need to put this somewhere very early in your program. In the application delegate, application will finish launching is a good place for it because that means it'll get executed before the first event arrives in your application. And since the first event might be this very event, you're going to want to get that in there early.

John Comiskey The important pieces of information in here, this call will register any handler. The important pieces of information in here are these two four byte codes, ASCR and GSDF. Those are the ones that say I'm interested in the event when I am asked to get the SDF. I want to handle that myself instead of letting Cocoa Scripting handle it.

When you register this handler, you also have to define the handler itself. This call has to go somewhere and you have to return the proper data so that the script editor can display your dictionary and so Cocoa Scripting can dispatch your events. And the prototype for that event and the prototype for that handler is going to look like this. And that handleGetSdef event was one of the operands to the previous call.

Why would you want to have, why would you want to handle the processing of the SDEF dictionary yourself? Well, SDEF dictionaries are static. Each application is allowed one. And that may not work for you. You may need to do something more elaborate than that. If, for instance, you have a plugin architecture and you want those plugins to also be scriptable, you're going to have to provide the dictionary yourself. Cocoa Scripting is not going to be able to piece your dictionary together for you.

I've created, by agreement with myself, a simple plugin architecture that allows me to add capabilities to Sketch with external plugins. And it consists of a few simple rules. First, it's going to be a Cocoa bundle like any other Cocoa bundle, but it's going to have a different extension.

It's going to have Sketch plugin as its extension so that I can pick it out from any other plugins that may be around and make sure I use it for the right purpose. And it's got to go in one of three particular locations. The user has an application support directory, and he can put it in there.

If you are going to provide these plugins with an installer, you might want to put them in the machine location and the application support directory there so that all users can get at them. Or if you want to couple this plugin tightly with your application for purposes of drag and drop installing, you can actually put the plugin inside the application itself.

And again, by agreement with myself, I decided that my plugin architecture would have two calls. The first plugin did load gets called at the same time application will finish launching is called. And if you have any upfront initialization that you need to do before the first event comes in, this is the place to put it. If, for instance, you wanted to register yet another event handler, you'd do that here.

Eventually, either the script editor or Cocoa Scripting will call and ask for your dictionary, and you need to provide it at that time so that the dictionary can be displayed and so the Apple events can be dispatched properly. And that call will come in at a method called SDef paths, and all that you have to do is pass back an array of the file paths where your dictionary definitions are, and you can have as many as you want. So I'm going to do another demo of implementing a dynamic dictionary and a plug-in architecture.

In this case, I do have to go in and modify an existing file, and that's the drawAppDelegate. And in the applicationWillFinishLaunching method, I've made some changes.

[Transcript missing]

And at that same time, I have also registered a handler for the event. So when the script editor or Cocoa Scripting wants my dictionary, it will come to me here.

In another file, I have my subroutines, and this is the load plugin subroutine. And you can see what is happening here is just arbitrarily the first dictionary in the collection is being selected as the base, and then I'm looping to add the other dictionaries to it. So I'm looping through the plugin paths, grouping them all together into one big dictionary, making that the return value for the event handler, and sending it back.

So let's run this. The plugin that I've chosen to make is a verb handler that we've used before to align objects. Align is a command in the Sketch menu bar, but it's not available through scripting. So what we've done is we've added the align command as a plugin.

So if we have a number of graphics in the window, We've got a number of graphics in the window. We can say through scriptability that we want to align their vertical centers, which should make them all line up in a nice neat row. Then we're going to delay for three seconds and then we're going to align the horizontal centers as well. So when we're done, all these graphics should be centered, one right on top of the other. And there they are. We can see that our graphics have all been rearranged so that one lays right on top of the other.

So that's a brief demonstration of the kind of thing you can do with a dynamic dictionary. Can we have the slides back again? Thank you. So that's a demonstration of the kind of thing that you can do with a dynamic dictionary and using a dynamic dictionary to create a plugin architecture.

You can extend an existing application, add capabilities to it, and then ship that plugin separately or as part of the application itself. If you're interested in doing these kinds of things, we can help you out here this week. We can meet with you in the lab and make sure that your application can handle what it is you want to do.

can't stress testing enough. Testing is the only way you're going to make sure your scriptability works, and it's also one of the great benefits of scriptability. Your model objects can be exercised rapidly and repeatedly through AppleScript in a way that a human tester can't. And you want to make sure that that capability is available to whoever does the testing. If you've got professional testers, we have two very good ones, John Coelho and Doug Korns do our testing for us.

They love testing AppleScript because all of their tests are automated. And if you have testers and you want them to love you, you'll make your application scriptable. If you don't have testers, then it's even more important to make your application scriptable because you're doing all of this yourself, and you want to spend more time making your application better, not just testing it.

So when you put your tests together, I want you to be very thorough. Send your code through every path that it can possibly take. When you get elements, you should get every element and call that collection accessor that we talked about before. Make sure that that works. But you should also access all of your elements by name, by ID, and by index if they're all applicable because you want to make sure that those more efficient accessors get called or, if you didn't code the more efficient accessors, that the built-in support from Cocoa Scripting is satisfactory for your person. So when you get into very large collections that you need to have the efficiency accessors.

You're going to want to get at the elements in various other ways as well. AppleScript has some names built into it for the first and last element. Some element just selects something randomly. You want to test all of that and make sure that that works. Negative indices work. They count backwards from the end of the collection. You want to test those and make sure that they work. And the most important, whose clauses. Whose clauses are part of the really great power of AppleScript. You absolutely want to make sure that those work.

Put together some simple whose clauses. Put together some really complicated whose clauses. Make sure that you get the results that you expect. And when you get these results, save them. Keep them somewhere so that the next time you change your program, you can run your scripts again, you can get the results, and you can make sure that they haven't changed. Or, if you really did want something to change, that you got the change you were expecting.

You want to be able to make and delete elements. You want to call those insertion and deletion accessors and make sure that they work correctly. You want to make sure that the rest of the collection functions properly after an element's been deleted, that there isn't some kind of hole in your collection that doesn't work anymore. So you're going to want to make and delete.

[Transcript missing]

When you do your testing, you want to set up some repeatable tests. So I suggest that you do a get set reset operation on all of your read write properties. Change the value, change it back so that the next time you come and run this test, you'll get the same results. You won't constantly be toggling between two different sets of results. You want to test edge cases.

You want to make sure that Values that are right up to the edge of what works work properly. So you might want to set the width of a graphic to zero, and then what you should see on the screen is a straight line instead of an oval or a rectangle. And you also want to purposely create error cases in your tests and make sure that they get handled correctly, that meaningful error messages get passed back, and that the program continues to function correctly even after an error has been made by the scripter.

When you add commands to your dictionary, you're going to want to test those yourself. The commands that you add to the dictionary are your value added. The standard suite verbs are very powerful and can do most of what you need to do, but your application does at least one thing that nobody else can do, and you'll be adding an AppleScript command to get at that. You want to test those and make sure that they work perfectly, because that's really your signature. That's your value added.

John Comiskey You want to test these commands in a couple of different ways. You want to take the default values for everything. Don't provide any of the optional parameters. Make sure that something reasonable happens. Make new circle. What's that going to do? Is it going to make a circle whose radius is zero? Is it going to put that circle at the origin? If that's the behavior that you want, make sure that that's the behavior that you get. Then you want to come back a second time and you want to specify every parameter and make sure that combinations of parameters work the way that they're supposed to.

John Comiskey Again, you're going to want to test your edge cases and your error cases. Drive things right up to the limit and make sure they work. Then take one step over the limit and make sure that you get a reasonable response and the program continues to perform properly after that.

The last thing that you want to do is add some real-world use cases. An excellent example is Kinkless GTD. Whenever Omni changes Outliner, I'm sure they must test Kinkless GTD because if they were to break that, that would be very bad for two different companies. John Comiskey So you want to find out what your users are doing with your scriptability.

Monitor feedback sources. If you have a chat list or an email list and people are sending AppleScripts back and forth and you see a dozen different AppleScripts that all do the same thing, make that part of your testing because your customers are dependent upon it. John Comiskey Also, it may be a hint that you need a new feature in your app.

And you want to make these tests repeatable. You want to retain your prior results. You want to be able to compare the results of one invocation to another. Make sure that if you got a change, it was the change that you wanted. And if you see a change that you didn't want, then you've detected a regression and you can go back in and fix that.

So what we've talked about today, we've talked a little about why you want your application to be scriptable. We've talked about the importance of doing your dictionary design upfront and getting that right. The importance of logging the activity of your application so you can learn how Cocoa Scripting works and what it expects from your application.

A few basic steps in how to get started in scriptability. One of the more advanced up-to-date topics that's available in Leopard that was not available before. And the importance of testing your app thoroughly so that you can detect regressions and so that you can support your customer's usage patterns.

The sample code that I was working on is available at the developer site, and those other resources, the scripting interface guidelines and the page of 4-byte codes are also available at the developer website. We've got some labs. Immediately after this one, we've got, immediately after this session, we've got the Make Your Application Scriptable Lab.

I'll be there. The whole Automator AppleScript team will be there, and we'll help you get started in making your application scriptable. I'll be here all day today and all day tomorrow, and if anybody needs for me to come back on Thursday and Friday, I'll do that too. I want somebody to leave here at the end of the week with a scriptable application that they didn't have when they came here on Monday.

John Comiskey The AppKit Lab is on Thursday, and there you'll be able to talk to the engineer who's responsible for Cocoa Scripting itself. He unfortunately can't be here. He's giving another session right now. But if you have specific questions about how Cocoa Scripting works and why it's expecting certain things of your application, you might want to talk to him on Thursday. I can help you contact him.

If you have questions after you leave here today, you can send messages to Sal Segoian, our product manager. You may very well know him already. He's a great advocate of scriptability and will help you get your job done, make your app scriptable. My boss is Todd Fernandez. He's the boss of the entire Automator and AppleScript group, and he can make sure that you get the answers that you need and put you in contact with the right people. The right people may very well be other AppleScript implementers, and they exchange ideas on the AppleScript implementers mailing list. Some of you may have already used that yourselves. It's a great source of information. It's a great source of ideas.