WWDC2003 Session 414

Transcript

Kind: captions
Language: en
good morning thank you for coming my
name is John Comiskey I'm and an
engineer in the applescript group I want
to talk to you today about three things
three things we're going to talk about
designing a dictionary for a newer and
existing application we spend most of
our time on that we're also going to
talk about implementing scriptable
objects to bring that design to reality
we're going to focus mostly on cocoa
scripting that's what I do most of the
time myself we're talk about a little
bit about carbon at the end and we're
also going to talk about developing
tests for your script ability as you go
along so you make sure that you don't
back track or have any regressions
designing a dictionary is the most
important part of the entire operation
once you've done that writing code is
not as hard the thing that we really
want to encourage you to do is to use an
object model in your dictionary Apple
script functions best when applications
have an object model in their dictionary
and why do you want to use an object
model in your dictionary well I think
you already know the reasons for that
you use object oriented programming
languages yourself you know the benefits
of them you wouldn't go back to the old
ways of doing things anyway what we want
you to do is to let scripters have all
those same advantages we want them to be
able to reuse your objects you put you
put time and effort into those objects
if you give the script or the
opportunity to leverage that that adds
value helps you sell your product helps
you make money which is why you're in
this business scriptable applications
are interoperable i like to say two plus
two is five to scriptable applications
can do things that neither one of them
can do alone neither one of them can do
while being worked by hand if you've got
one or if you've got two or more
scriptable applications they can be
combined together into a super
application that does something that no
one of them can do alone script ability
an object model for script ability
offers your users flexibility when I
talk to people about making their
applications scriptable they often say
well why would anybody want to do that
and my answer is I don't know why and
you don't know why
either but your customer knows he knows
what he wants to do he knows what
problem he needs self if you give him
powerful recombine about reusable object
he can build a solution for himself and
you might be surprised sometimes at what
your own customers do with your products
they can also create new functionality
that's missing sooner or later you have
to ship your product and you always have
a cool new feature that's almost done
but it isn't ready to go and so you have
to leave it out that's always a
disappointment but it's a reality of
being in business applescript is the
feature that you forgot your customers
can take applescript and use it to
create features that are missing from
your application if you went to the
applescript studio session yesterday you
saw a demo of using Apple script studio
to create plugins for the Xcode program
for the Xcode environment and we were
able to create a feature that's really
nice to have but it's missing from Xcode
maybe someday it'll be a native feature
of Xcode but in the meanwhile you can
use Apple script to write a plug in plug
it into Xcode and get a cool new feature
that wasn't there well there's several
reasons why you want to use not an
object-oriented language the biggest one
an object model in your dictionary and
the biggest one is that Apple scripting
op the object-oriented language itself
it's got all the cool things there in
all the other object oriented languages
and Carrington's data hiding all of
those kinds of things but you only get
those benefits if you use an object
model Apple script is also an English
like language you write simple
declarative sentences with a verb acting
on a direct object modified by one or
more clauses but you only get that nice
English like flow if you use an object
model in your dictionary when you're
writing an apple script you always use
cell blocks at least to tell
applications which you can also use tell
blocks to shorten the apple event that
you have to write if you've got a
complex or deep containment hierarchy
you can nest tell blocks and then the
Apple events that you write inside those
tell blocks are shorter and smaller
easier to read easier to understand but
this only works if you've got to
containment
you are key in your object model and as
I mentioned before applications can
interoperate there's synergy between
applications they already share data
what we're talking about inviting them
into a workflow together you can create
a workflow across several different
programs from one vendor or several
vendors that solve your problem your
end-users problem and once you've got a
workflow like that it can be wrapped up
in an applescript studio application and
become one of these super applications
that i mentioned you could do something
some kind of post-production job that
has to be done over and over and over
again doesn't require a lot of artistic
expertise but it needs to be done and it
needs to be done a lot that can be
turned into an automated workflow while
we're talking about this today we're
going to be developing some regression
tests for your own software those can be
put together into a workflow so that a
tester can just fire up a studio
application run it come back later and
find out what the results of the tests
were but none of this works unless you
use an object model in your dictionary
so what is an object model um it's a lot
easier to say what it's not this is the
implementation of folder actions from
system nine it's not an object model
it's five different verbs and you can
see pretty quickly what goes wrong here
two of these are removed two of these
verbs have removed and add in them you
could have used make and delete which
are already standard verbs in a standard
suite you can also see that these these
events have have things that ought to be
objects just embedded right into the
verb it takes away the flexibility and a
recombination that end user can do when
the verb and the object are sealed
together into a single event like this
and you'll also see that these a lot of
these end with a preposition and you all
know you should never end a sentence
with a preposition again this takes away
flexibility prepositional phrases in
Apple script should be parameters and
they should usually be optional
parameters you shouldn't force the user
to describe prepositional phrases
weather
he needs them or not so this is a this
is a good example of a bad example in
Panther we have done something about
this all the old verbs for folder
actions are still there and they still
work and we actually still use them
ourselves internally but we've also
provided an object model for folder
actions the first thing you notice is
the rectangle got smaller that this is a
you can express all the same operations
in a smaller dictionary if it's an
object model these two objects can do
all the things that those five verbs did
plus a lot more you get more for your
money with an object model when you
start to design your object model you
should plan for a full implementation
look into the future we know that you've
got to ship something and you've got a
limited amount of time to do that but
your life is going to be better and
easier a year from now if you plan an
object model with room to grow map out
as big an object hierarchy as you think
is meaningful for your for your
application decide now what things are
going to be called in the future so that
we don't run into the problem of all the
good names have been taken and define as
much functionality as possible
everything that someone can do by hand
with your program is very good candidate
for script ability some high-powered
operations that might not be suitable to
be done by hand might might also be
targets for script ability as well your
scripting of implementation may in the
end actually be more powerful than your
duty presentation now you plan for the
future you plan this huge object
modeling now you don't have time to
implement it all you're going to have to
scale back for your first release and
only do part of it when you decide what
you are going to do it's important to
include a minimal functional set enough
objects and enough verbs to do at least
one interesting operation something that
some customers been bugging you about if
you pick a set of objects that allows
you to perform that function you know
you've got a minimal functional set
there's sometimes things in your
application it's hard to think how you
might
use them through script ability there's
complex interactions one example in
network setup you've got an IP address
and you've got a router address and
they're not independent of each other if
you change one you might have to change
the other and you have to do it in a
synchronous fashion it's not easy to see
how you're going to do that with Apple
script maybe the solution for release
one is to just leave those properties
read-only chances are you're using a
DHCP server anyway you need to know what
the IP address is but you don't need to
change it if you make that read only the
information is available the values
therefore your user and you've skipped
the complex problem until later when you
have more time to think about it but
even if you have a largely read-only
implementation in your first relief you
should always provide at least one
powerful read write function that can
actually do something in the instance of
network setup that would be the location
if the user can switch his location
through script ability then he really
has the power he needs to do whatever he
wants he's got to sit down in advance
create a number of configurations
organize them into locations that are
meaningful for him but once he's done
that all he needs to do is change the
location as he moves from city to city
or from work to home or into a
conference room or anywhere else you
might go the standard suite has a number
of verbs that cover almost everything
you're ever going to want to do get and
set are used on properties of your of
your objects and exists count make and
delete are pretty much implemented for
you by coco scripting there's not a lot
that you have to do if you create
scriptable objects according to the
pattern that Coco scripting expects
these four verbs are just going to work
so and then in a standard suite all
that's left is six other verbs that act
on objects things like print and save
where you're going to really have to
write some code yourself and quit to
quit the entire application we think the
thirteen verbs in the standard suite
will cover most of what you're going to
want to do and you should always try to
use them first before you create a verb
of your own
if you use an object model along with
the standard suite you get this multiple
multiplicative effect if your object
model has say three objects with a verge
of ten properties each and they can all
be gut geht and step that's 60
operations you can perform right there
if those three objects also respond to
the 10 other verbs that act on objects
and remember four of those 10 are done
for you that's another 30 operations
that your application can perform plus
one more quit so that's 91 things that
your application can do and you hardly
written any code at all at this point
one thing we tell people not to do is to
create a bunch of verbs you saw what
happened with uh with folder actions we
created a bunch of birds it worked it
covered the problem that we needed solve
but it was kind of a dead end it
couldn't do anything more than that so
we we discouraged the creating of a lot
of verbs the temptation is there to do
that to just take an existing API and
expose it as a lot of apple script verbs
but it doesn't give you the power than
an object model does a procedural verb
is one-dimensional it performs one
operation on one data item and they're
married together like they were in the
example that we saw and you have to
anticipate every need for folder actions
it was pretty easy because we were
defining what folder actions was going
to do and we knew when we got to the end
of those five verbs that we were
finished if you have a bigger more
complex application than that you'll
never know when you're done you'll never
know when you've gotten to the end of
the list procedural verbs are also
really ugly they defeat the english-like
syntax of apple script and make ample
scripts very choppy and hard to read
I've got an example here of a folder
action verb the way things used to work
in system nine and it's clunky and not
too particularly meaningful it's hard to
tell what that verb is going to do and
there's a lot for the scripture to learn
I've seen dictionaries with two and
three hundred verbs a lot of herbs to
slog through looking for the one that
you want and even when you get to the
end of the list you don't know for sure
if you missed it or it's not there it's
a lot for the script
to learn and hard to retain that
information if you don't use an object
model and you create a lot of verbs
instead your application script ability
is somewhat of a dead end the only way
you can communicate with other
applications is by the native data forms
strings and numbers you can pass strings
and numbers back and forth to other
applications and that's about it if you
have an object model and you pattern
your object model after the existing
object models of other applications you
can interact on a higher plane instead
of just sending numbers back and forth
if you do need a verb go ahead and
create it first you should look at the
standard verbs and make sure there's
nothing there that you can use but once
you've decided that that's the case yeah
it's okay to go ahead and make your own
verbs they should be simple applications
that you have the simple operations that
your application performs on its own
objects and the names of these verbs are
going to come from probably buttons and
menu items that you already have in your
program now that doesn't mean you should
take every button and every menu item
and turn it into a verb but when you're
trying to figure out what to call a verb
if you call it the same thing you call
it in your UI you should try to create
verbs that can be reused on multiple
objects that's what the standard suite
is all about is it's it's 13 verbs that
we think you can use everywhere um you
should try to do the same thing when you
create verbs of your own if you create a
verb that only acts on one object or one
kind of object um you're slipping back
into that procedural verb problem that
we do we talked about and one thing that
you want in it you want verbs that can
be reused in your application a good
place to find them in to reuse verbs
from other applications look at the
script of elapsed from Apple and see
what's there that you might already be
able to use if you copy a verb or any
other term from another application you
can copy the human readable term and the
four byte code bolt that's going to make
your program interoperates better with
other programs your your dictionary is
scoped to your application and you
won't end up in collisions with other
applications what you also won't end up
in synergy with the miser and you should
definitely choose reusable parameters
there's a lot of things in the standard
dictionary little prepositional phrases
that modify the verbs that are going to
be of use to you anywhere there's one in
there for naming the target file that
you want to write to that can be reused
there's there's others in there for a
asked me if I should do something before
I quit that might be useful to you reuse
those parameters to and recombine them
with your verbs in different ways when
you decide whether or not you're going
to make a verb you should choose
carefully what it is you do um you
should always use a property instead of
a verb whenever you can now I've got a
big X here next to enable script Tim
that sounds real simple why don't I like
that it's just verb object not even any
modifiers what's wrong with that nothing
on the face of it but what happens after
that that's wrong if you have an enabled
verb well now you need a disabled verb
and even though you've got an enable
verb and a disabled verb you still don't
know whether this thing was enabled or
not in the first place and that might
actually be more important than being
able to turn it on and off if you have
instead of simple boolean property
called enabled then you can use the get
and set verbs to replace your enable and
disable verbs and you can actually get
what the setting is now and decide
whether or not you even need to touch it
so uh when you've got a simple boolean
switch that can be turned on and off
make it a property and use getting set
should pry you supply verbs to objects
rather than data on it you're slipping
back into the procedural verbs if you
apply your verbs to data if the
parameter to a verb is always a string
are always a number you're slipping back
into the procedural verbs there are some
exceptions to this though it's much more
natural in the case of say a chat
program that wants to be scriptable to
say i want to send a message to a purse
well messages and object strings are
it's okay for them to sit in the direct
parameter but you'll find that when
you've got something like a string or a
number sitting in the direct parameter
you should also have the direct object
you should also have an indirect object
a prepositional phrase that begins with
preposition two and that's a second
object that also participates in this
operation and it's the target that the
first object is going to be fired at
definitely avoid just exposing your raw
internal API don't just take all of the
commands and all the routines in your
API and just turn them into verbs this
is how you end up with a dictionary with
two or three hundred verbs in it it
leads to these clunky one-dimensional
procedural verbs that we don't like how
do I decide what I'm going to call these
things where do I get the words that I'm
going to use in my dictionary where do I
where do I decide how do I decide what
these things are and what they're called
the best way to do this if you can if
you've got an existing application and
you've got users that have been bugging
you for automation um interview one of
them sit them down maybe sits facing
away from them and have them describe to
you what it is they're doing the what
they'll do is they'll lead you through
the steps that it takes for them to
perform an operation by hand write down
what they're saying that that's your
apple script now it's not going to
compile and it's not going to run you're
going to have to change the wording so
that it's fitting into the apple script
form but that's not the most important
part the most important part is you're
going to have to pull out of that
description the objects that the person
is talking about and make those the
scriptable objects in your dictionary
use the same words that your customers
are already using to describe these
things and then they don't have to
relearn your program for script ability
they look in the scripting dictionary
and they say oh I know what that is and
they know what it is because you've got
the word from them um so then you define
you define in your dictionary those
those objects and properties that the
that the user says he needs to do his
job and you only create
new verbs when he's doing something that
your program does and other programs
don't do that if you don't have the
opportunity to talk to a real live user
about how he does his work maybe your
company has technical writers and
produces some nice documentation in
those dot in those documents there is
very often a tutorial or a sample
session of a user sitting down using the
program this is the same kind of
information that came from the interview
that that step by step tutorial of how
to do something with the program again
that could be an applescript you've got
to massage the spin taxi to the
applescript form but much more
importantly you have to create the
objects that the user is manipulating so
that script ability will be as powerful
and more so than the GUI so you define
those objects and properties that that
are in your documentation create new
verbs if you have to now you don't have
to have separate documentation for your
scripting and for the rest of your
program because whatever it's called in
the documentation that's what it's
called in the dictionary if if you don't
have if you're out there by yourself and
you don't have customers and she can sit
down and interview on a frequent basis
and you don't have a big tech writing
organization you can look at your own
object model we started out by saying
you know what what's good about object
models you use them yourself you're
using one in your application look at it
and abstract from Matt the objects and
properties that your customers are most
likely to need to do to do what it is
they want to do but the most you take
this approach the most important thing
is humanizing the programmatic terms
that you've used just reading your
source code it's too techy it's too hard
to understand you have to put this in a
form than an end user is going to be
able to understand you definitely don't
want to expose absolutely everything
that's in your program you've probably
got a few main objects that represent
the concepts at the end users trying to
work with you've also probably got a
bunch of helper objects that do
interesting and important things that
the customer doesn't need to know about
those helper objects don't belong in
your Apple script dictionary just the
main conceptual objects deal when you're
pulling terminology out of your
application you've got to humanize it
and one of the most important things is
get rid of the inter caps use separate
words with white space in between them
instead also a good terminology and
Apple script doesn't use a lot of
capital letters you only want to use
capital letters for acronyms and proper
nouns the reason for this is Apple
script is English like these terms show
up in different places in the inn and an
apple event and if you've got a capital
letter in the middle of an apple event
it looks funny it's that capital letters
there because it's a product name it
makes sense but if it's there because
it's one of your verbs or one of your
objects it's going to confuse people if
you have boolean properties you might
have the word is in your code leave that
out is mean something in Apple script
you don't want to make it part of your
terminology and again only make new
words if you really need them the last
way that you can go about it is to look
at your own it's your own GUI and
extract an object model from that this
one's tricky because you have a tent you
might have a tendency to script the user
interface and that's something you don't
want to do there's a session tomorrow
311 well we're going to talk about
scripting the user interface and try to
convince you further that that's not
what you want to do so don't just
describe the little widgets that are on
the screen and give the user the ability
to poke at them conceptualize it figure
out what it is that that widget
represents maybe it's a property maybe
it's an object give it a name and put it
in your dictionary and don't just
inventory everything again you'll end up
with a long dictionary that's hard to
find things conceptualize what are these
things that I'm manipulating what is it
that I'm trying to do with them what
properties do they have that can be get
and set when you form the terms
themselves don't use articles like and
leave those out they can be sprinkled in
to your Apple script
later they don't affect the way that the
aplex Crypt execute but they can make it
easier to read if you've embedded them
in your terminology then it's hard for a
person writing an apple script to ship
to ship them and shuffle them to where
they ought to belong also avoid personal
pronouns like me and my again me and
mine mean something in apple script you
don't want to stick them in your
terminology and again if you do need to
define some verbs you're probably going
to find the terminology for them on an
existing button or an existing menu item
somewhere in your program again don't
expose everything not every menu item
needs to become a verb and the menu
items that do need to become a verb are
already in the standard suite at least
that's our opinion when you're mapping
stuff off of the screen into your
dictionary most of the stuff you're
looking at is going to be properties of
an object generally one window or one
pain within a window is going to
represent an object and everything
inside that is going to be a property on
when you when you map that to your
dictionary you're going to need to pick
data types for those the most important
one here on this slide is radio buttons
if you have a small finite set of things
of values that a property can take on
that should be expressed as an
enumeration it makes your Apple scripts
look nice makes them easier to read
gives the and it gives the script or the
notion that he can't set this value to
just any old thing he's got a pic from
this list some other UI widgets lead to
more to richer relationships in your
object model some pop-ups are just
replacements for radio buttons and in
that case they ought to be rendered in
your dictionary as an enumeration just
like the radio buttons were but other
pop-ups actually represent an element
relationship if you change a pop up at
the top of your window and it changes
the entire contents of the screen and
now you're looking at a different set of
data then that pop up really represents
a element relationship and to go back to
our example of network set up the
location is a pop up in the
you I but it actually represents a
element relationship in the object model
the same thing with scrolling list
sometimes a list is just a list of
strings and if that's all it is and then
maybe that's what you should be passing
back to your user this is a property the
property is an array of strings um but
that's not always the case sometimes the
scrolling list actually represents an
element relationship for instance in the
finder you've got a scrolling list of
files that you would want to render in
your dictionary as an element
relationship a relationship between two
objects table views are a rich source of
element relationships this is a simple
spreadsheet um there's already a table
view script a table view suite or a
table sweet sorry defined in the
standard headers it's got a table which
contains rows and columns the
intersection of a row and column is a
cell and each cell can't can in turn be
a container for an entirely new object
hierarchy the contents of a cell in a
spreadsheet might be a chart and the
chart has an entire object hierarchy of
its own so this is somewhat of a
physical mapping from your screen to a
dictionary if you do something like a
spreadsheet where the user has the
opportunity to put all different kinds
of data in here and you don't know in
advance what it's going to be a physical
mapping like this might be appropriate
if you if you do know a little bit about
the data that's that's expressed in a
table view then you can make an
abstraction in this instance this is a
page from a database program that that I
wrote just as an experiment the object
here the table itself represents a
database each instead of calling each
each line a row we're going to call it a
record and instead of a row being
divided into cells we're going to have
field and the fields are going to have
names which happen to be the same names
as the columns this is one step up from
the physical mapping the most
interesting thing about this is that Jim
Mora is one of the 20
winning in coaches in NFL history one
step up from that as a conceptual
mapping we really know what this is all
about this tables for one purpose it's
not it's a database but it's my database
and I control what's in it this is a
part of the folder action set up user
interface that's going to be in Panther
um here the container is the application
itself nobody nobody owns this there
isn't a table anymore there's just
folder actions and the application has a
bunch of them and every folder action
has a name and a switch that says
whether it's enabled or not the thing
that's not showing here is there's
another scrolling list right next to it
where every folder action has a set of
scripts attached to it and that's an
element relationship so when you're
designing your dictionary we definitely
want you to use an object model it makes
it makes your program fit in better with
Apple script it makes your program fit
in better with other scriptable
applications Apple scripts to do let's
you be part of a workflow let you be
part of a super application only create
new verbs when you have to use something
in the standard suite if you can omit
certain boro MIT certain words from your
terminology that make a mess of things
and don't use uppercase unless it's a
proper noun of some kind go ahead and
take things from other programs the
reason scriptable the reason scriptable
applications interact the way they do is
because they use similar terminology
this this allows you to interact with
other programs at a level above just
passing back numbers and strings lay out
the entire future as far as you think
you're ever going to be able to go and
then implement what you can in the first
release remembering to give you your
script or at least one really
interesting thing that he can do you
have to write a sample script so you
need at least one really interesting
thing to do um now you've got your
dictionary and you need to write some
code um there's three cases that you can
find yourself in if you're really lucky
you're starting
from scratch you're building a whole new
application from the ground up you can
do whatever you want um much more likely
you've got an existing application and
you you've been tasked with adding
script ability to it you're going to
have to keep what's there keep the GUI
functionality and add scripting to it
you need to do a little retrofitting the
toughest situation is when you've got a
big existing framework that is not
itself scriptable and you don't have the
opportunity to make it scriptable
perhaps your application is
cross-platform and you use a framework
that makes being cross-platform real
easy but it makes being scriptable real
hard so the first case maximum freedom
starting from scratch I can do anything
I want except interview a user who is
using the program because it doesn't
exist yet so how do I do this how do I
find how do I develop my terminology if
the program itself doesn't even exist
well if you're from a large corporation
that has a powerful marketing department
and they provide you with detailed
specifications in advance um that
information can be used to develop the
object model for your Apple script
dictionary that's not normally the case
the situation i find myself in and I've
got some direction I've got some goals
but I don't have a lot of real
specifications um you could use a
competitive analysis which means steal
from other programs look at how other
programs do similar things how they
implement their their script ability and
while you might not copy it exactly well
you might not be able or allowed to copy
it exactly you can certainly get some
concepts or how other people are doing
the same thing however you define your
decide on your object model you should
subject it to significant review pass it
to other engineers back to the marketers
that give you your specifications any
tech writers that are going to need to
write the documentation and especially
to your testers your testers know what
they need to test and the things that
they need to test
are easier to test if they're in your
Apple script dictionary um and at some
point along the line in the development
your program you're going to do some
prototyping you're going to take some of
your ideas and concepts and lay them out
at least in static screen shots that are
going to give people some idea of what
the application is going to look like
when it's done once you've done that
prototyping then you can sit a user or
maybe a marketing manager down in front
of it and say take me through the steps
that you would do that you would do to
perform some function and now you can do
the interview and when you're done
you'll have an apple script dictionary
which is an object model of the
conceptual objects that your end user is
going to be using whether they're
scripting or using the GUI this can
actually be a design document for your
entire application you've got you've got
a running start here of how the entire
application should look regardless of
scripting one of the things that I do to
make my life easier is I implemented a
scriptable base class it does a lot of
the common functions this is this is the
promise of object-oriented programming
reusable code so my scripting is mostly
done by this reusable base object it
gives me consistent behavior across all
my objects all the objects in a
particular program are going to behave
very much the same we won't get a lot of
chattering between them that makes them
hard to use together if your company
develops a suite of applications and you
have a scriptable base a base class this
is going to give you consistent behavior
across your application this is
beginning to build the synergy now these
applications can talk to each other they
have similar object models they have
similar ways of describing those object
models they can pass things back and
forth that are a level up from just
strings and numbers and let's code is
less bugs if you've got a base class
that works you find you're spending very
little time debugging it and that's
great because then you can do other
stuff Maya Maya scriptable base class is
called elements because every object in
scriptable application dictionary is an
element of some other object the
top-level objects are all elements of
the application itself good scriptable
object have names so I have a way to set
and get the name of my object excuse me
get some water thank you in some
applications you may find that you want
unique IDs for your objects databases
especially the the objects will have
persistent unique IDs unique IDs in
applescript are guaranteed to be good
for one launch of the application and in
order to create a unique ID that's good
for one launch of the application all
you need is a serial number just never
give the same number out to two
different objects and you're okay
there's a slight problem with that
though if somewhere in the execution of
a script that application quits and then
relaunches it will start reusing those
unique IDs if you've saved an object
specifier in a script variable and it's
still hanging around after the
application has quit and relaunched it
might now refer to a different object
and that could be bad um one way to get
around that is to choose a time stamp
you can get the time stamp once when
your application launches or every time
somebody creates an object now even if
your application quit and relaunch is it
will never generate the same unique ID
again if you need unique IDs for
something like a database that need to
persist across several applicable laws
of the application and need to stay the
same across several launches the
application corefoundation provides
something called a uuid and it's great
it's got a time stamp in it so it has
all the qualities of the time stamp it's
got your Ethernet hardware address in it
so it can even be differentiated from
objects created on other machines and if
the first part of it is a hash key which
means if you stick it into a hash table
or a binary tree the the IDs will spread
out across the range and they won't
cluster together like if you were just
using a plain old time stamp
every good scriptable object needs to be
able to send back an object specifier to
describe itself so that that same object
can be retrieved later later in the
script in my scriptable based class I'm
implemented a cascade that creates an
object specifier for every object and
tries to create the best object
specifier that it can if if unique ID is
defined in the dictionary for this
object I go ahead and use that unless of
course there isn't one is if there is no
unique ID defined in the in the
dictionary then I look and see if name
is defined in the dictionary every good
Apple script scriptable object should
have one or the other of those defined
in the dictionary um if it turns out
that neither of those is available then
I use an index specifier instead index
specifiers are weak they may not even be
good for one launch of the application
if you add or delete any objects at all
your index specifiers are going to
change and any that you might have
stored in script variables just aren't
going to be any good anymore or they're
going to point to a different object and
that could be bad in order to create an
object specifier you're going to call an
API that's going to need two pieces of
information what container do I belong
in and what does my container call me
and that's what these two first two
things are about every scriptable object
i create has a pointer back to its
parent do not retain your parent pointer
this creates a loop and your objects
will never go away you also need the an
object also needs to know what its
parent calls it what element
relationship does it belong to I have a
method called siblings it simply passes
back the name of the method that that
then this collection of objects back to
the container
these two pieces of information are
going to be necessary to create your own
object specifier so I keep them around
all the time and all my object
another thing I do as a favor to myself
is every one of my scriptable objects
has a nsdictionary in it called
attributes and I use this to store the
data for all the properties of the
object now I can take this nsdictionary
flatten it write it out to the disk read
it back in later if i use a uuid to give
it a unique ID I've now got a persistent
object that i can use across several
launches of the application several runs
of the script several days from now I
can go back and get that same data and
use it in a scriptable way again this
does not show up in my Apple script
dictionary each individual property
shows up in my Apple script dictionary
but physically inside I keep them all in
an NS dictionaries it's nice it's easy
does a lot of stuff for you um now you
need to create your actual model objects
the things that you've decided to define
in your dictionary you're going to want
to create an object in and inherits from
your scriptable base class so now you
don't have to worry about names or IDs
or object specifiers that's all done you
are going to need to initialize this
object and the way cocoa scripting works
it creates an object first then it calls
the various set methods to set the
parameters you need to work with this
you need to have an anit method that
doesn't take any parameters it has to
create an object that's ready to use
right now to do that you might need to
do some defensive programming make sure
that check checking pointers for nil and
things like that that object has to be
safe to use right away because the way
cocoa is going to use it is it's going
to allocate it it's going to initialize
it and then it's going to call the set
methods to set what's in it it's not
safe to do that you're going to have
trouble Coco scripting is also well not
just cocoa scripting put cocoa itself is
going to expect you to have a deallocate
method so that you can put away all your
toys applescript is very is very memory
intent at coco scripting is very member
intensive you create and delete a lot of
objects to process a particular apple
event you want to make sure that you're
not leaking so you want to make sure
that you chained to any deallocation
methods flow many any base classes you
inherit from as well you want your
scriptable objects to have properties
and the way you do that in cocoa
scripting is by creating a method with
the property name for getting that value
and another method that says set
property name for setting the value the
part that's here in italics is the part
that you want to change to the property
names that you've selected when you
design your dictionary your dictionary
also has element relationships and
there's there's varying levels of
support for that that you can that you
can do in your cocoa scriptable objects
the most basic one is to provide a
method that has the same name as the
element name and it bends back to
whoever calls it an array of objects of
that type this is this is the minimum
amount necessary for a cocoa scripting
application there are more things that
you can do to make your application more
more efficient but this is the start you
have to start here the first time you
come through this I just want you to
create the methods they don't really
have to do anything but the element
relationships have to at least fake it a
little bit so that you can test this
stuff we're trying to get to the point
where we can we can write some test
scripts see if our program even works at
all and then we're going to go back
we're going to create this skeleton and
then we're going to go back and put some
muscles on it you also every everything
is an element of some other object your
top-level objects are going to be
elements of the application itself in
order to do that you're going to have to
add element relationship methods to the
NSF plication object we don't want you
to have to subclass NS application if
you don't want to if you do that for
some other reason great but you don't
have to do it for scripting you can use
an objective c category or a delegate to
add the methods that you need to the
application object
you may also have properties of the
application there's no place to put
these you can't change the list of ivars
in the NFF l'occasion object you could
if you subclass tick but we want to try
to avoid that but since there's only one
application object it's okay to go ahead
and use Global's for these for any
persistent properties that the
application itself might have normally
we want to avoid using Global's but this
is an instance where it might be okay
now you want to be able to create and
delete objects you want to be able to
insert them into collections and remove
them from collections and Coco scripting
again it takes the element names that
you've decided to use in your dictionary
create method names out of them and then
you write those methods so you want to
be able to insert elements into in
through the element relationship and
there's two ways to do that you can do
it positionally or you can do an
independent of position um sometimes
doing it positionally is important if
you're creating deleting windows you
might want to create them in the front
you might want to create them in the
back might want to create them in
between existing windows so you'd want
to insert things to add index on other
things that you create there's really no
implicit order to them it's okay if they
just go at the end in that case you can
do a simpler insertion the team that
doesn't take an index either one of
these will work you may end up for
various reasons you may end up wanting
to do both these are both going to be
used anytime you make a new object in
your Apple script you also want to be
able to remove things from the from the
collection that's always done by index
that's the way cocoa scripting works the
object may be found in any one of a
number of ways but when it finally gets
deleted it's going to get deleted by
index inside your code and this gets
called by the deletes or there's there's
enhanced element accessors that can make
things more efficient for instance if
you if you are implementing a database
and you are using you you IDs for the to
identify the records
you could potentially have millions of
these you don't simply want to have a
method that creates an array and passes
them all back that's not practical your
programs not going to work very well
there are enhanced methods that allow
you to get objects directly by index by
name and by unique ID these can be a
whole lot more efficient than just
searching a big huge array the decision
of whether or not you want to do this
it's a performance consideration you
want to build your program the simple
way first measure it and see if you need
it but in the case of millions of
records in a database it's pretty
obvious you're going to need to do this
all the details for this we're covered
in last year's session if you've got the
dvds it was section 303 if not there's a
web page on the developer site that
tells you a lot about this and on your
cds there's cocoa scripting release
notes which also describes how to do
this now we want to test our objects
we've got this skeleton it doesn't
really do anything yet we got a bunch of
objects they've got a bunch of phony
properties they've got some phony
elements we can't really do anything
useful yet but we can start writing our
test scripts first thing that I do is I
put a logging macro in every single
method that I write all the getters all
the setters all the element accessors I
put a logging macro in there and I have
a switch here that I can turn on and off
whenever I want to test my application
see what it's doing try to figure out
why it's not handling an apple event
correctly I turn this switch on and run
it and I get all sorts of stuff in the
console log but it tells me blind by
line where I've been in my program what
I did what I did right and what I did
wrong nice to know where you've been in
your program it's nicer still to know
why cocoa scripting will help you out
there that this first line here if you
type it into your terminal application
it will turn on cocoa scripting own
logging facility every time cocoa
scripting gets an incoming apple event
it uses your dictionary to parse it pull
up
figure out what all the pieces are as
soon as Carlos Krypton's reach that
point if this switch is on it logs what
it thinks that message what it thinks
that Apple event says now that you've
got that information of what the
incoming apple event looks like and then
a log of everything that your program
did to try to respond to that Apple
event can help you a lot in debugging it
if you have certain kinds of errors in
your dictionary cocoa scripting may not
be able to form a script command out of
what it is it's received in that case
you're going to have to go down one law
one layer lower and get the apple event
manager to tell you what that happen
what that Apple event looks like you
again you type these commands into your
terminal application you need the first
one and one or more of the others and
then you have to launch your application
from inside the terminal and then in the
terminal scroll you will see a plement
manager doing the same thing every time
he gets an apple event he tears the part
looks at it says what he thinks it means
and puts it in and puts it in the
terminal log this is all at a lower
level all you're going to see at this
level is for byte codes not very much in
the way of interpretation but it can
tell you it can tell you probably the
reason why cocoa scripting is having a
hard time with that event so then you
want it you want to start writing some
scripts and the first script you want to
write is one that probes your entire
object hierarchy touches every object
touches every property gives you maximum
coverage so you can see if your program
is is written correctly and with a with
apple script that's relatively easy
thing to do applescript supports the
every modifier which it's a it's a range
specifier that says I want to act over
the entire collection of objects and it
also supports cocoa scripting supports
for you for free the properties property
which returns a record of all the
properties of a given object so here in
the course of just about nine lines of
apple script I've managed to probe the
entire object hierarchy of the folder
action too sweet this script tells me
that
everything's there everything works time
to go back and start writing some code
so I'm going to go I'm going to want to
go back to all the methods that I
created before all the properties all
the set properties all the element
relationships and I want to populate
them with real data now the element
relationships are going to get their
their data from various api's or
collections of data inside your program
that may already exist and the
properties the properties are going to
draw those their data from those actual
objects once you've put some muscles
into these routines you can go back and
you can rerun all of your test scripts
and you'll see a big change from the
first time the first time you just gotta
buy it back a bunch of bureaus and
missing values this time you'll start to
get back some real data objects with
real names and real property is set to
real values once you've reached this
point you want to write even more test
scripts you want to be able to make sure
you don't have any regressions as you
add more features as you add more
capability you want to make sure you
don't break anything that was already
working before and you know one of the
things you want to do is test accessing
your objects by all the various means
that they can be accessed simplest is
index you can just count them and loop
through them and get each one and get
its properties to do a thorough test
here for folder actions you'd have to
have an inner loop that did the same
thing to every script but I ran out of
room on this slide you can also access
things by name you want to make sure
that that works this is going to this is
going to test an important part of your
program that Apple script does not
require that that the object names be
unique you may in the implementation in
your program require that these names be
unique but one way or the other you need
to run this test if you've got two
objects with the same name if you allow
that you should find in this test but
you can only ever really get to the
first one if you support unique IDs you
want to make sure that that kind of
access works so you want to write nested
loops here that access every object by
its unique ID
and this was one of the most important
every scriptable object needs to offer
up an object specifier for itself so
that you can find that same object again
later and do something new to it you got
to make sure that those object
specifiers really work that they really
get you back to the same object that
they were supposed to be and so you want
to write a test for that loop through
every object X get an object specifier
for it then go back and get the
properties using that object specifier
and make sure that it's the object you
thought it was and you want to make
something new you want to create a new
element and insert it into a collection
of elements you do that with the make
new verb that's part of the standard
suite this is particularly interesting
if you do this if you do this with all
of the logging turned on you'll find out
a lot about how your program works
you'll find out a lot about how cocoa
scripting works and you'll see that just
to create a simple to create a single
object and insert it into into a
collection will end up calling every
property access Iran that object and
every element access or in the hierarchy
all the way back to the application one
of the most powerful features of Apple
scripts are whose clauses that I'll
allow you to select objects based on
whether or not they satisfy a certain
test so you want to make sure that you
write some good tests of whose clauses
the folder action supports an enabled
flag for every object so here I've
written some whose clauses based on the
setting of the enabled flag to go into
your folder actions set some of the
enables legs on some of them to off and
run this script you should get varying
results and even though the last two
events look very similar there is a
subtle difference the presence of those
parentheses will cause those last two
events to actually return different
collections of objects we talked about
some other scenarios that you could find
yourself in most common is adding script
ability to an existing application it's
a little bit less flexibility than you
had when you were starting from scratch
but you do a lot of the same things you
one thing that I would suggest is that
you use objective-c categories to add
the scripting methods to an existing
application you're not you don't have to
go into the source files for the
existing objects and actually change
them you can put your scripting in a
separate file created in the form of a
category it's a very powerful way of
modifying existing objects but it's also
non intrusive if there's any point in
the development cycle where you have a
crisis of faith and you think that your
scripting implementation is horribly
screwed up your application and you
don't know what to do about it you can
go into Xcode and simply uncheck the
scripting files rebuild your app and try
it again and find out that maybe it was
that guy next to you have messed it up
not you mom or maybe it wasn't you and
then you can fix it objective-c
categories are a great way of building
script ability alongside your existing
objects without mucking them up too much
you still do have the issue of an it
method that doesn't take any parameters
you might find that your existing
objects aren't built that way that your
existing objects having an it method
that takes a whole bunch of parameters
basically setting all of the properties
at once at the same time that the object
is created Coco scripting isn't going to
work that way it's going to want in an
interpreters and again you've got to
make sure that the result at the end of
that init method is a safe object whose
methods can be called right now and it
isn't going to be reference any nil
pointers and again you're going to need
a deallocate method because you're going
to be creating and deleting a lot of
these things in the course of handling
apple event so you don't want gleek once
you've created your categories alongside
your existing objects you're going to
have to implement all of your various
properties together and setters and your
element names and your element
relationships you may find that some of
the properties that you need already
exist in the object so you just go ahead
and reuse them on the X of the way that
the dictionary has constructed the
external name for a property and its
internal name don't have to be closely
related so
you've got a getter in a setter for the
name for instance you can just go ahead
and reuse that if you find that the
Apple stripped version of this getter
and setter need to be slightly different
than the other then you can wrap one
around the other but one way or another
you have to satisfy all of these
properties by creating methods to access
them same thing with the element
relationship if you'll you'll need to
create the element relationships in your
scripting categories if you can't reuse
any of the existing ones for instance NS
application already has an ordered
documents method and cocoa scripting
reuses that for its own purposes there's
no reason to create a new one and again
you want to extend the NS applications
so that your top-level objects are all
elements of the application and again we
would suggest to use active c category
or a delegate to do that for the same
reason is it's not intrusive you don't
have to mess with the real NFL acacia
knob ject and while you're doing this
you should add your logging macro to
every method that you create then we're
going to go through the same steps we
went through before we're going to write
want to write a bunch of scripts to test
this with even though some of the
functionality might not be there yet and
we want to go back and add some muscle
to our objects still in those property
accessors so that they get at real data
still in those are those element
accessors so they pass back collections
of real objects then go back and rerun
all of your scripts and make sure that
the differences you see and the results
are the ones that you expected the last
situation is the toughest one and that's
a adding script ability to to a large
application that depends on a framework
that is not itself scriptable and cannot
easily be made scriptable um again
though you want to go through most of
the same steps you want to define a real
good dictionary first then you want to
write then you want to define the
scriptable objects properties and
element relationships that that bring
that real
bring that dictionary to life and you
want to do this as if you were starting
from scratch you've got this existing
framework that you can't penetrate too
easily and you want to add cocoa
scripting to it just create the cocoa
scripting objects as if you were
starting from scratch as if this other
application didn't even exist do the
same thing we did before give them just
enough functionality so that you can
write some interesting test then you're
going to want to go back and add muscle
to these objects by taking all the
property accessors and element accessors
and tying them back into existing api's
and existing objects inside the
impenetrable framework this is where the
complexity can arise the object model
that you chose to express in your Apple
script dictionary and the object model
that exists in this impenetrable
framework might not match up you might
have to do some sorting and searching
and recombining of things to get them to
work right this is where this scenario
can become difficult but when you're
done or you think you're done you can go
back and rerun all of your scripts that
you wrote and see if you've got the
results that you were expecting till it
should give you an indication that
you've done it correctly we promised
that we would talk about cocoa and
carbon and we haven't said anything
about carving yet so what about carbon
um well you can still script a carbon
application in the same way that you
always have the the the OSL is still
there it still works and you can use it
and it's so that's very well documented
in the inner application communication
document and there's also Mac Tech is
now the guardian of all the old develop
articles this one is a particularly good
one a cookbook a recipe for taking
carbon application and making it
scriptable they weren't even called
carbon applications back when this was
written um so you can do it that way
it's not easy but we've all done it at
least once and it can be done um you I
would suggest that you seriously
consider migrating to Coco it's not I
know it's not trivial
carbon is is a first-class citizen and
it's it's going to be supported forever
um but Coco is the way we encourage you
to develop new apps if you reach a point
in your development cycle where you're
really considering to chucking it all
and starting over again consider
starting over again in cocoa I wouldn't
start over again just for scripting but
it's certainly a factor if you do
rewrite your application in Cocoa
objective-c and cocoa scripting will
make the scripting part of your job very
easy a year ago we promised that we
would come up with a API for carbon
scripting that was just as easy to use
as cocoa just as powerful to all the
same things for you leveraged all of
that existing power and we thought and
thought and thought of how to do this
and it was really hard and we were going
to end up having to rewrite almost
everything that cocoa scripting did and
it occurred to us well maybe we could
just use cocoa scripting um so we
conducted an experiment and found out
that yes as a matter of fact it pretty
much just works you can use cocoa
scripting in an otherwise carbon
application this is really a special
case of the third scenario you've got
this big impenetrable framework that's
hard to make scriptable you want to
build a cocoa scripting implementation
alongside of it and tie it into the
existing implementation you can actually
do that with any existing carbon
application it's not hard but it's not
trivial there's a few tricks that you
need to know few modifications you need
to make to your application startup code
but once you've done that cocoa
scripting just works um there is a price
though you don't get this for free um it
can have a performance impact on your
application and the only way for you to
find out what that is is to just measure
it yourself and the two things that
you're going to need to measure a launch
time and memory usage so you want to get
a baseline for those before you start
your work
you don't have to do your entire
scripting and implementation to find out
what this what this impact is going to
be what you do have to make the changes
to your startup code once you change
your startup code you can relaunch your
application and you'll get a pretty good
idea of what pulling in cocoa scripting
is going to do to your application it'll
slow down the launch it will increase
the footprint now you haven't written
your code yet but you haven't written
any carbon script ability code yet
either and the presumption is that they
will be about equivalent that the hit
that you're taking is the overhead for
cocoa scripting and you can measure that
without having to write all the code
first if you really want to do this
contact developer technical support and
put scripting hybrid in the subject of
the of your email and you will get a
response from John mantri on about how
to go about doing this um like I said
it's not hard but you got to know a few
things um there's lots and lots of
documentation to help you make your
application scriptable if you're the the
most important part of it is the design
in your dictionary and these are these
places here good places to go to find
out information about that you also need
to implement objective-c or other
objects to bring your dictionary to life
there's more detailed information about
how to do that at these places cocoa and
carbon are both are both documented here
and the apple script language guide is
going to be valuable to anybody that
writing scriptable applications or
writing Apple scripts any anybody along
the line and users testers engineers
marketers everybody should be looking at
the apple script language guide it
teaches you how Apple script itself
works and teaches you a lot about how
your object about how your object model
needs to inter interface with that each
time we release new software we keep you
up to date on the latest changes those
are
in these release notes which should be
on your CDs and the interpretation
communication technote is kind of an
umbrella where you'll find almost all
the rest of the stuff that we mentioned
plus a whole bunch of other stuff about
apple event an applescript if you're
afraid you don't want to ask any new big
questions you can go to the applescript
QA and see if maybe the answer is
already there um but don't be afraid to
ask newbie questions they're really easy
for us the answer and we feel like we've
done a good deed and you can get sample
code also and you can get information
from outside the applescript website has
a wealth of information including dozens
and dozens of sample scripts for apple
applications and other applications
creating synergy between them you should
definitely visit that site and there's
books and websites published by third
parties they also have very valuable
information and the applescript website
is a good place to start to find most of
those there's a section in there that's
just all about third-party websites that
you can go to to learn even more if
these are all the sessions that you
missed on but if you get the dvds you
can watch them there or maybe some of
you guys were at them this is today's
session and the rest of the ones that
we're going to have I mentioned tomorrow
we're going to talk about using Apple
script to test your applications and
also we're going to there's going to be
a session where self-knowing is going to
talk about apple script for system
administrators alva scripts a tremendous
tool for system administrators save them
a lot of time if you want your system
administrator to love you you should
write a good scriptable app and if you
need to get to get to us directly Todd
Fernandez is my boss South Egwene is our
marketing manager Jason's our technology
manager and John Mondrian is our DTS
contact should always go through John
Mondrian first he's going to have the
quickest answer for you if it's already
been asked and he's going to direct it
to the right person if it hasn't
already been asked
you