Re: Scope of globals, parents and children, "load script" an
Re: Scope of globals, parents and children, "load script" an
- Subject: Re: Scope of globals, parents and children, "load script" an
- From: email@hidden
- Date: Mon, 21 May 2001 21:09:19 -0400
On Sun, 20 May 2001 04:32:42 +0200,
Sander Tekelenburg <email@hidden> asked,
>
>>why did I need to:
>
>> 1) declare those same globals again, at the top of the script
>
>> 2) declare them yet again within each handler! (well, only those globals
>
>> that apply to that particluar handler)
>
>
>
> First off, you don't need the original declarations any more: the data are
>
> stored in the object, so having them in the main handler is redundant.
>
>
When I delete those lines that declare the globals to be globals from the
>
main script, the script tells me that some variables are not defined. Perhaps
>
I didn't explain myself right. I did not mean I need to define the values of
>
those globals. I mean that I (for a reason I still don't understand) need to
>
define those variables as globals again in the child.
The order of declaration is significant. If you put "global x" before "to
myhandler()" then you don't need to put "global x" inside myhandler().
We need to be very careful about the words "declared" and "defined." "Defined"
(in the sense of "a variable not defined") means that it has not been set to a
value. So if my script is,
global x
display dialog x
--> error--"x is not defined"
I get the "variable is not defined" even though the variable is *declared*
Also note that the reply ("You don't need the original declarations any more")
was predicated on rewriting the script to use script objects. The map for that
transformation is like this:
Procedural ("structured programming") script:
global a,b,c,x,y,z
on h1()
-- Do things with a,b, and c.
end h1
on h2()
-- Do things with a,b, and c.
end h2
on h3()
-- Do things with a,b, and c.
end h3
on h4()
-- Do things with x,y, and z.
end h4
on h5()
-- Do things with x,y, and z.
end h5
on h6()
-- Do things with x,y, and z.
end h6
on run
h1()
h2()
h3()
h4()
h5()
h6()
end run
Object-oriented script
script object1
property a : 0
property b : 5
property c : "Hello"
on h1()
-- Do things with a,b, and c.
end h1
on h2()
-- Do things with a,b, and c.
end h2
on h3()
-- Do things with a,b, and c.
end h3
end script
script object2
property x : -1
property y : 42
property z : "Goodbye"
on h4()
-- Do things with x,y, and z.
end h4
on h5()
-- Do things with x,y, and z.
end h5
on h6()
-- Do things with x,y, and z.
end h6
end script
on run
tell object1
h1()
h2()
h3()
end tell
tell object2 to h4()
h5() of object2
object2's h6()
end run
(The final calls of h4, h5, and h6 are written differently just to show the
options available in directing the handler call to the script object.)
The key issue here is that you don't break the script's code down into modules,
and leave the data floating freely in the global space. The data and the code
that manipulates it together form the units of abstraction and implementation.
In the example, a,b,c and h1,h2, h3 group together into one object, and x,y,z
and h4,h5,h6 group together into a different object, with different data and
different operations on that data.
>
How would a variable name ever be used without my knowing? I am the author. I
>
decide how to name my variables. I make it a point to never use the same name
>
for a variable within 1 script.
And how did my keys end up on the kitchen table this morning? I make it a
point to put them on the hall table. ;-)
The challenge of writing a complicated script is to manage the complexity, so
you can work on it without memorizing all the variables the script uses. You
want to group things into objects that are simple enough that you can absorb and
work on the totality of the object without overtaxing your short term memory.
>
Am I missing a key issue?
>
> think "objects are like people, I find out what they believe by asking them
>
> questions, not by reading their minds"
>
But doesn't the very fact that globals exist mean that objects are _not_ like
>
people? :)
Globals are not objects. Globals are just a way of getting access to the shared
data, without knowing who is sharing it. Looking in a global is more like
looking in the dumpster of a building to see what the people working there do.
You don't know which division or which office generated data you find in the
dumpster; and you can't immediately see how or why they did it. But find that
same data on the conference table in the office suite, and its a lot easier to
understand what it is doing there.
>
To stay with your analogy: Up until now I've considered globals to be
>
something like public knowledge, available to and known by all 'people'. It
>
certainly worked like that in every all-in-one script I wrote so far.
Mac users will probably best understand globals by looking at their individual
Mac desktop. How many files can you keep there before it gets out of control?
Globals certainly work; the problem is that beyond a certain point, this
unstructured, unorganized pile of data makes for scripts that are difficult to
write and much more difficult to understand six months later. The problem is
not that globals don't work; its that they work too well. They provide too much
visibility and too little organization. (Hey, its all ones and zeros. Ones and
zeros work great. But you don't want to program in them.)
>
>> apparently both the parent and the child must be 'manually'
>
>> informed of each other's globals. Why? And is there a more elegant way to
>
>> do this?
>
> the key here is to think "if I have to tell the object about this variable,
>
> maybe it should be a property of that object, and not of my script?"
>
>
Are you saying I should get rid of globals altogether?
As a general rule, yes. I've developed some fairly big AppleScript projects
(the largest one is 45 script applications and 15 script libraries), and have
only used global variables twice. And that was not to provide global
visibility, but to be able to pass a reference as a parameter, for efficiency.
>
In general I try to not use globals too easily. But in this script, some
>
things are referred to over and over again; both in several handlers and
>
within the main script. I doubt I can get rid of all globals _and_ keep the
>
whole thing comprehensible...
Put the "several handlers" and the globals they access in a script object. Then
access any data you need to from the main script by using "varname of
scriptname".
A further refinement would be to avoid accessing the properties of the script
object directly, particularly if they don't naturally represent things you
should meddle with. That is, if a script object contains a list of tasks to do,
accessing the list of tasks itself is letting too much of the details of the way
the list is put together leak out of the script object. Its better to have a
handler that adds a task to the list, one that removes a task, one that finds a
task, and one that executes a task, than to go in and manipulate the list from
outside the script object. If you always use the object's handlers to do the
work, you can rewrite how the data is stored, without having to rewrite any of
the script outside the script object. That's a big advantage in time and
troubleshooting when you need to change what the script does.
(This is what is meant by, "Objects are like people, I find out what they
believe by asking them questions, not by reading their minds". The best way to
interact with the data in an object is through the handlers provided in the
object.)
The way to work with a complex thing is to break it into a simple arrangement of
simpler things. That's what script objects are--the way to build the simpler
things. Using handlers to break your script up is part of the solution to the
problems of complexity, but doesn't address the complexity of the data. Script
objects group the data and the handlers together, and reduce the complexity of
both the data and the operations on the data.
This dictum is important even if you are the only author of the script. You can
write a script object, define clearly what it should do, test all that
functionality, and then put it aside, and no longer worry about the details that
go on inside. Now, once the script object is implemented, you only have to
think about the handlers and perhaps a small list of properties that the object
makes available to you. You don't have to worry about the details of the
handlers and how they fiddle with the internal data structure of the object.
--
Scott Norton Phone: +1-703-299-1656
DTI Associates, Inc. Fax: +1-703-706-0476
2920 South Glebe Road Internet: email@hidden
Arlington, VA 22206-2768 or email@hidden