Re: Inheritance and Loaded Libraries
Re: Inheritance and Loaded Libraries
- Subject: Re: Inheritance and Loaded Libraries
- From: has <email@hidden>
- Date: Tue, 2 Nov 2004 11:32:54 +0000
David Weiss wrote:
Let me provide more detail.
I'm trying to do two things at once here:
1. I need to have a text script that when compiled and run has access
to all properties and methods of around 26 dynamically loaded
libraries. The libraries will be loaded as needed. Additionally each of
the libraries needs to have access to each other's properties and
methods.
Considering program architecture for a moment: you really want your
module dependency graph to look like a tree, not a cat's cradle. By
connecting every module to every other module you vastly increase the
amount of complexity in your program: the number of connections
increases as the square of the number of modules. That's a huge
amount of information for you as author and maintainer to keep track
of and enormous room for things to go wrong, and such rampant
connectivity completely defeats the purpose of modular programming:
minimising coupling between code to reduce complexity, ease testing
and maintenance and maximise reuse. (This applies at every level,
whether it's coupling within or between handlers, objects/classes,
modules, frameworks, etc.) For example, if module A is dependent on
module B and B is dependent on A, it's impossible to test or use
either one in isolation. The solution is to redesign one or both
modules so that A is dependent on B, *or* B on A, *or* A and B are
both dependent on a new module created to hold the shared
functionality.
I've succeeded in doing this in a single script file with
inheritance,
That's a misuse of inheritance (or, in AppleScript's case,
delegation), which is for extending objects' behaviour, not binding
modules.
Here's the test script that I wrote to show and test the exact
solution I want:
That's just plain bad design. By way of comparison, I once wrote a
3KLOC program with spaghetti dependencies between just 6 or 7
scripts, and it was a complete disaster, utterly unmaintainable and
murder to debug; it took me weeks just to get it working at all. It
was a harsh lesson in how NOT to manage complexity: in the end I had
to throw everything away and rearchitect the whole lot from scratch.
...
OK, rules for developing modules to minimise coupling and thus complexity:
1. Each module should look after itself, importing its own
dependencies - and ONLY those dependencies - for itself.
2. Avoid circular dependencies. Where they crop up, they can always
be coded out of the design.
3. Minimise the number of dependencies between modules.
4. Build 'em so ye can test 'em. If the only time you can test your
program is when it's fully assembled, that isn't modular programming.
If something is hard to test in isolation, it's a good indication
that you've a problem with 1, 2 and/or 3 above and should redesign to
eliminate it.
2. So why do I need an applet? I need this code to be location
independent. That is, I need to be able to simply copy the folder of
libraries and scripts to any location on any machine and have it all
just work.
I think you can partly blame AppleScript here: its lack of a built-in
module import system is, IMO, its single biggest design goof (and
that's saying something). OK, it won't solve the problem, but at
least it'll make you feel a little better. One of the things I like
about moving to Python: its module system may not be perfect, but at
least it's *got one*. :p
Duplication of Script Objects
I do have one solution for all this, but it results in duplication of
libraries, and all my attempts to use references have failed! There can
and must be only ONE copy of each library, as they are interconnected.
If library A changes a property in library B, library C must be able to
see that along with the script that is running.
Rule 5: Avoid mutable state in modules like the plague. 99 times out
of 100 it's just a real quick route to creating a total mess of
unmanageable, incomprehensible and frequently unwanted interactions.
There is, of course, the odd exception where shared, mutable state is
desireable, e.g. in an application that contains a number of shared
preferences that are accessed by other modules within the same
application, one would create a 'config' module specially to hold
this information and share it amongst the other modules. In general
though, if you think you need mutable state in a library, what you
really need is an object-oriented design instead, with the library
simply providing the handlers to construct those objects.
Any help with this would be greatly appreciated!
First, I'd suggest finding yourself a good book on software design,
before you end up buried beneath an utterly unmanageable amount of
complexity. (I found Steve McConnell's Code Complete a good place to
start <http://www.stevemcconnell.com/>.
Second, you'll find the module problem has already been solved,
albeit as a third-party solution. Go to AppleMods
<http://applemods.sourceforge.net> and get a copy of their library
Loader system (which I wrote) from their 'Getting Started' page. You
should also look at some of their libraries (which I also wrote) to
get an idea of how they're constructed before attempting to port your
own to it. One teensy problem as far as making your own libraries use
it: I'm still waiting to be asked to write up the official Library
Developer Guide, which means that the version available on the side
only contains the end-user instructions for working with existing
libraries. But I can email the developer notes that do exist upon
request, and there's plenty of good working examples amongst the
libraries already released that you can grok for yourself.
HTH,
has
--
http://freespace.virgin.net/hamish.sanderson/
_______________________________________________
Do not post admin requests to the list. They will be ignored.
Applescript-users mailing list (email@hidden)
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden