Go Card Error Handling
dunbarx at aol.com
dunbarx at aol.com
Sat Jun 25 10:29:35 EDT 2016
I am a HC'er from way back.
But it seems like the "correct" way is to throw an error in all cases, simply as a matter of purity and consistency.
That legacy stacks might break is a point, but then, how would they break? In other words, how could this arise? Likely a user entered an invalid card reference somewhere, or a card was deleted.
The old way is that the code notes the result (or does not), does something with that condition (or not) and either continues or throws its own error notification. By continues, I mean fails to access a card and ignores that case.
But if the process always stops dead if a "normal" error is now built in, legacy code would only break where it did not matter if accessing a non-existent card made no difference at all. So would that be unreconcilable in all cases, that is, might the user find himself in a trap he could not extricate from? That is the reason for leaving the old way alone.
Craig Newman
-----Original Message-----
From: Mark Waddingham <mark at livecode.com>
To: How to use LiveCode <use-livecode at lists.runrev.com>
Sent: Fri, Jun 24, 2016 1:09 pm
Subject: Re: Go Card Error Handling
Thanks Dar and Jacque,
That puts it nicely in context. I'd class this behavior, then, as being
for 'HyperCard compatibility'.
LiveCode does have a slightly different model from HyperCard though,
which is why it is perhaps a behavior which should be reviewed at some
point. Indeed, it actually suggests there are a few other places where
the error behavior for stacks and cards aren't quite right.
For example, the engine will try to load a stack from disk if a
reference 'stack "mystack"' isn't in memory - in this case *this* is
file I/O and such should probably set the result rather than throw an
error.
When the engine does have a stack in memory, going to a card cannot fail
due to file I/O (as all objects in a stack are in memory all the time)
and thus a non-existant card should throw an error. Indeed, you can
check whether a card exists before accessing it by checking 'the
cardNames'.
Indeed, this does suggest that *perhaps* the fact that you can do:
go stack <named_of_stack_in_memory>
Or
go stack <stack filename>
Suggests that these are two distinct operations and a 'cleaner' model
would be perhaps to have:
load stack <stack filename>
To load a stack from disk which, as it involves file I/O, should set the
result.
And, furthermore, make:
go stack <name_of_stack>
Only succeed if the named stack is in memory, if it is not then it
should throw an error.
I'm minded to think here that there is actually a nice separation here.
In any applications there are stackfiles which can be considered to be
an intrinsic part of the application, and then all other stackfiles. The
former will typically have named references somewhere (usually in the
stackfiles property of another stack), or be included in the description
of what the application consists of (i.e. the stackfiles which are
included with a standalone).
The distinction here is between stackfiles for which their non-existence
should be considered an application failure (just as if a dynamic
library is not present for a native app, the app will usually not work)
and stackfiles which the application manipulates (like any other data
file).
From an error handling point of view, these present two entirely
different cases.
For operations which you should always expect to succeed *or* can
guarantee will succeed by a preceding check in code, the correct error
approach is to throw.
For operations which could fail and you cannot 'precheck' for failure,
the correct error approach is to set the result.
To put it slightly more abstractly:
An operation should throw an error for all errors which occur as a
result of 'system failure' (for some definition of system) which the
application has done all it can to ensure it cannot happen. In this
case, if you include a set of stackfiles in your standalone application,
and one of them fails to load then you can reasonably take this to be an
'exceptional' circumstance - the problem will be due to something you
(as a programmer) can in no-way control. (For example, if one of the
stackfiles on disk is corrupted).
An operation should set the result for all errors which occur which
cannot be checked for beforehand - typically this will be because there
is a time-of-check to time-of-use problem. In this case, if you have a
stackfile which is not considered directly part of the application and
is perhaps chosen by the user - or indirectly by the user - then it is
impossible to check before you try and load the stackfile that the
operation will succeed. Certainly you can check that the stackfile
exists before you try to load it using 'there is a file', but since OSes
are pre-emptive, in between doing that check and trying to load it,
another process could have done something to invalidate the check.
Of course, in the above the assumption we are making is that the
'stackfiles which are part of the application' are not amenable to being
fettled with by other processes - in the sandboxed model (such as you
get on iOS and Android) this is enforced, in unsandboxed worlds you have
to squint a bit to convince yourself that this is actually a reasonable
thing to assume. (After all, if you go into an installed applications
folder on any platform and start deleting arbitrary files from them, you
can't really expect them to function at all!).
So, anyway, my question has been answered :)
Warmest Regards,
Mark.
--
Mark Waddingham ~ mark at livecode.com ~ http://www.livecode.com/
LiveCode: Everyone can create apps
_______________________________________________
use-livecode mailing list
use-livecode at lists.runrev.com
Please visit this url to subscribe, unsubscribe and manage your subscription preferences:
http://lists.runrev.com/mailman/listinfo/use-livecode
More information about the use-livecode
mailing list