Re: Writing large scripts
Re: Writing large scripts
- Subject: Re: Writing large scripts
- From: Bill Cheeseman <email@hidden>
- Date: Wed, 09 May 2001 18:48:16 -0400
on 5/9/01 12:13 PM, Jan Erik Mostrvm at email@hidden wrote:
>
I would like to ask those of you who write large programs, how do you organize
>
your code?
That's a really good question. As you might expect, there are several good
answers. I've written some very big scripts and I've tried a lot of
solutions, so let me give you some off-the-top-of-my-head answers.
1. I can often live with leaving everything in one file, although for big
scripts that means using Script Debugger or another editor that handles more
than 32K of text. I put special organizational titles and subtitles in them
using the "-->>" marker that both Script Debugger 2 and Scripter support, so
that the "Markers" menu allows me to see and navigate my organizational
markers instantly. I habitually break my scripts down into handlers that are
relatively small; I name them consistently and descriptively; and I place
them in subsections of the file (see the Markers discussion above) that make
logical sense. Something like this: run and open handlers at the top; a
"main event loop" or "main controller" handler next; major subroutines after
that, each grouped with important subroutines that it uses; and "common" or
"utility" handlers at the end. I am a natural-born commenter, too. I always
put explanations of my strategy and usage notes at the top, and version
notes at the bottom, with lots and lots of comments mixed in throughout the
code to explain what I'm doing. This is vital, especially at my age.
I haven't yet written a script that I couldn't live with in this form.
2. Nevertheless, I often break my scripts down into groups of source files.
When I do this with scripts that will be distributed in executable,
"run-only" form, I use the 'load script' command in such a way that it is
the functional equivalent of a C 'include'. This allows me, as in the C
paradigm, to use lots of separate text source files, but a built script is a
single file containing all the compiled code needed to run by itself.
To do this, your main script should have a property into which you load the
separate script libraries the first time you run it. Then you distribute the
script without separate library files. The property will retain the compiled
script libraries as executable code forever, since the script is run-only
and will never again be recompiled. Just make sure your script does not
reset the property to an empty string or an empty list before it quits.
This technique is useful when the libraries are reusable code snippets that
you have already written or plan to use again in the future. But it is also
useful when the libraries are not "reusable" code, but are instead just
pieces of one big, unique script that you find easier to manage as separate
files. In this case, my separate script files are often organized on the
same model described in 1., above.
There are disadvantages to this technique, however, compared to 1. For
example, you can't use the Markers menu to navigate instantly to any
location in the entire logical script; you can't run find commands on the
logical script (unless your editor supports cross-file searches); and you
can lose pieces of your logical script if you aren't well organized. One
advantage of this technique, though, is that it allows you to use an editor
that has a 32K text limit, if that is your preference. Also, I suppose, if
you're in a shop and want to farm out pieces of the script writing to
several people.
Another downside to this technique is that you have to remember to run the
script once before you distribute it. It is a good idea to include a
'display dialog' call in the run handler to explain what happened if
somebody (hopefully you, not your customer) runs the script and discovers
that the libraries aren't in it and also aren't available to be loaded.
3. I sometimes, especially when writing scripts for myself, use genuinely
reusable script library files for handlers that are useful in most of my
scripts -- if only because I have daydreams about the advantages of reusable
code libraries. These are usually well debugged, reliable workhorses that I
don't need to think about while writing a new script. In this case, my
scripts reload the libraries either (a) every time they run or (b) only when
the script detects that a newer version of the library is available. The
latter method is preferred, at least by me since I have more hard disk space
than I know what to do with but am usually pressed for time. In these cases,
I stick the script libraries in the Scripting Additions folder, since that
is the official location for code snippets that provide commands to scripts.
(The Application Support folder might do just as well.)
This technique also uses the 'load script' command to load the script
libraries into a property. If you are using method (a), loading the
libraries anew every time you run the script, you might want to save space
on disk by setting the property back to an empty string or empty list before
the script quits. This has the effect of "unloading" the library, since the
script will then resave itself on disk without the loaded library code.
There is, of course, a speed penalty for doing it this way, because it takes
a little time to load the libraries every time you run the script. If the
script is, for example, a stay-open background applet that launches at boot
time from the Startup Items folder, this doesn't matter. Nor if you have a
733-MHz PowerMac G4.
If you are using method (b), it is easy to check whether a new version of
the library has been placed in the Scripting Additions folder since the
script was last run. Just put the modification date of the library in a
property in the script every time the library loads, and test the
modification date of the library file on disk against that script property
every time you run the script.
4. I am also fond of script servers. For example, I have a set of speech
handlers that make it easy to speak messages from my scripts. My speech
server launches from the Startup Items folder at startup and runs in the
background all the time. Other scripts can call its handlers at will, so
they don't have to include all that speech code themselves. There are disk
memory advantages to this since multiple copies of the library code are not
saved in every script that uses it, and also time savings because the
libraries don't have to be reloaded every time a script is launched.
I'm sure other people have other techniques.
--
Bill Cheeseman - email@hidden
Quechee Software, Quechee, Vermont, USA
The AppleScript Sourcebook - www.AppleScriptSourcebook.com
Vermont Recipes - www.stepwise.com/Articles/VermontRecipes