Re: Tell Blocks Considered Harmful (was Re: open for access)
Re: Tell Blocks Considered Harmful (was Re: open for access)
- Subject: Re: Tell Blocks Considered Harmful (was Re: open for access)
- From: Chris Page <email@hidden>
- Date: Tue, 16 Dec 2008 15:04:12 -0800
On Dec 16, 2008, at 10:26 AM, Ed Stockly wrote:
Yes. It's unnecessary and undesirable to put many of those
scripting addition commands inside that tell block.
Placing all those lines inside the tell block confuses things and
makes it more difficult for someone reading the script to know
whether the script is intended to depend upon sending those
commands to Finder.
So what? What does it matter if someone looks at the script and
doesn't know if the finder is the process that handles the OSAX or
something else? The command works, the process runs. No sweat, no
problem.
Yes, it matters. It matters if you want the script to work correctly
in the long-term, not just for a one-off or even a few months.
Applications and scripting additions change over time. They can easily
change in ways that conflict, breaking scripts, since they are created
by independent software developers who can't be expected to test every
possible combination of every application a user might be using via a
script.
Scripts that minimize the number of commands unnecessarily sent to
other processes are more likely to work correctly in a wider variety
of situations -- situations that may change over time.
It makes for a smooth, easy to read, easy to understand script.
I agree that it appears simpler, but it's behavior is more complex in
the sense that it is sending lots of unnecessary commands to another
application, making them unnecessarily subject to that application's
terminology and behavior, which is subject to change.
My goal is to see if we can't make the simpler-looking scripts also
have simpler behavior. One way to do that is to have most or all
scripting addition commands never be sent to another application
process. That way, they're guaranteed to continue working the same way
without regard to changes in those other applications.
As the scripter learns more about the technology they grow beyond
that.
The reality is that even very experienced scripters write what seems
to work and leave it at that. Languages that encourage people to pick
up bad habits from the start -- by making the worse behavior less
apparent or appear simpler -- tend to train experts to keep up those
bad habits.
If I could design AppleScript from scratch I would invert the
relationship so that sending scripting addition commands to other
applications requires more verbose code, instead of the other way
around.
Yes, but that's far more scripting structure, it's more wordy, it's
not as intuitive. Requiring that kind syntax makes it more difficult
to get started with appleScript.
Yes, sometimes it is, unfortunately, but the code has simpler and more
specific behavior.
I'd also like to point out that fewer lines of code is not always
equal to greater clarity. For example, it takes more lines of code to
break a complex script into multiple handlers/functions, but they
almost always make any non-trivial script clearer.
As the script runs I want to control what application is frontmost
in order to give the user a consistent look and feel. If I activate
app A, I don't want the UI focus to change arbitrarily to whatever
process is running the script just to display UI elements. I want to
choose which app displays UI elements.
When do you only care about having the script's dialog appear in front
of every other window on the computer, versus being displayed *by* the
frontmost application? Do you see the difference? It's possible to
display windows in front of all other windows without those windows
being a part of the frontmost application.
Issue two, do I want my modal dialogs to effectively lock out all
other user interaction with an application?
That's how it works now. If Quark is displaying a dialog, I can't do
anything else with quark. I have no problem with it.
But what I want to know is: When *do* you care about it? When is it
important for your scripts to be able to prevent the user from
interacting with an application *other than* the one running the script?
I've always thought it would be nice to display a non-modal dialog
that would give me the option to display a dialog within an
application that allows interaction, but I'd be very careful about
using it.
Sure. That might be a useful enhancement.
But short of that, I would want to limit user interference with an
app displaying a dialog...
Can you say more about why? I'm looking for concrete reasons. Actual
scripts you've used or written where it's important to prevent the
user from interacting with some other application.
Which actually brings to mind another reason it's better to include
osax calls in a tell.
Tell application "Quark"
tell document 1
set myText to contents of text box 1
display dialog xxxx
....
Once I've started the document tell block, my script is addressing
that document, even if another document becomes document 1, for as
long as I stay inside that tell.
Notice that, for someone not well-versed with AppleScript -- and even
some who are -- that script literally says "tell document 1 to display
dialog". What does that mean? The document isn't displaying the
dialog, the application is. By unnecessarily placing commands inside
tell blocks, the script becomes misleading about what it actually
means and what it intends to mean.
But if I have to end that tell to call call an osax then go back to
a new tell document 1, a different document may be frontmost and I
can't use the simple "tell document 1" but will have to do more
elaborate ways to address the document.
In this particular example, if you intend to have the application
display the dialog, then it's okay to put the ‘display dialog’ command
inside the application tell block, but it's a bad idea to place it
within the ‘tell document 1’ block.
But as I pointed out, you don't *have* to actually move things outside
tell blocks. You just need to be clear about where you intend to send
that command, and there are several options available to you, for
example:
tell application "Quark"
tell document 1
set myText to contents of text box 1
tell me to display dialog xxxx
...
end tell
end tell
though, moving commands outside tell blocks is even clearer.
OK, I'm a scripter, not a programmer ...
If you write scripts, you are a programmer. Revel in it! :-)
Exactly. Today they do. Scripting commands operate with the
privileges of whatever process is handling the command.
Right, and I guess if that's a problem you should fix it, but don't
throw the baby out with the bath water.
My goal for this discussion is for us to define what is "baby" and
what is "bath water".
What about a script run from the scripts menu when the finder is
frontmost app?
The global script menu runs each script within its own process. If a
script in the menu is an applet, that applet is run in its own
process. Bare scripts are run in an application called Script Runner,
and only one script at a time may be running in that process. The
frontmost application is only used to determine which scripts to
display at the top/bottom of the menu.
This is one reason why it's better if applications support in-
application script menus, where they actually run the script within
their process. It makes the scripts simpler, by eliminating tell
blocks, and eliminates whole classes of bugs and security risks that
can occur when sending commands between processes.
I should have said: I would really hate to see the entire language
munged just to eliminate an additional vulnerability introduced by
'do shell script'
Unfortunately, many of the scripting addition commands suffer from the
same vulnerability as ‘do shell script’. Any command that performs
file I/O (including ‘choose file’) is, for example.
Yea, well tough luck for them, all I care about is appleScripters.
The programmers should have known better. If you're going to give
people headaches give them to the programmers not the scripters.
But both populations are subject to the same risks and limitations.
And as a user, you don't want applications that you use every day to
break just because they happen to send a scripting addition command to
another process without using AppleScript to do it.
But it's not arbitrary. The process that the script runs under may
be arbitrary but the scripter decides which app displays the dialog
after careful consideration.
That's not what I meant by “arbitrary”. I meant that you are free to
choose any application you want to send scripting addition commands
to. You may arbitrarily choose any application.
Which means adding steps to making very simple commands work ...
No. I was suggesting that the goal should be to make simpler scripts
work safely and consistently and require more verbose code to do the
things that represent a compatibility or safety risk.
Tell blocks and scripting additions as they exist today enable and
even partly encourage sloppy scripts with lots of code
unnecessarily within tell blocks, and lots of events unnecessarily
being sent to other processes.
Yes, but that's not as bad as it sounds.
It is as bad as it sounds. The fact that Security Update 2008-005 was
required, and the fact that the security fix breaks some scripts and
applications are proof of that.
That's the price paid for the ease of learning to AppleScript.
But there should be no such price. It should be easy to write correct
scripts and require more knowledge and code to write unsafe scripts.
--
Chris Page - AppleScripter
The other, other AppleScript Chris
_______________________________________________
Do not post admin requests to the list. They will be ignored.
AppleScript-Users mailing list (email@hidden)
Help/Unsubscribe/Update your Subscription:
Archives: http://lists.apple.com/archives/applescript-users
This email sent to email@hidden