John,
I'm playing devils-advocate, here... By and large I do agree with your
premise, but there are sometimes exceptions to the rule that "monitor
should only be used for unexpected errors".
There are some advantages in code readability to using monitor blocks
for naturally occurring errors, however.
To be sure, it's very simple/elegant to check the divisor for a simple
equation like this:
if divisor = 0;
result = 0;
else;
result = whatever / divsor;
endif;
But what if the formula isn't that simple? For a complex formula where
there are multiple calculations going on inside an expression, it's not
so easy.
result = (b*-1 / b**2-4*a*c) / (2*a);
(This isn't from a real program, just picked it as an example. I think
we can agree however that sometimes there are equations of similar
complexity in our programs.)
For something like this, it's much easier to do:
monitor;
result = (b*-1 / b**2 - 4*a*c) / (2*a);
on-error;
// handle error
endmon;
Sure you could pick it apart and calculate each piece separately and
check the divisor separately, but for code readability-sake, it's
probably nicer to keep the equation as a one-liner.
Not just mathematical expressions, either... though divide by zero was
the example at-hand. Consider stuff like this:
monitor;
ifs_path = %str(getEnv('BASE_PATH')) + '/'
+ getConfigDirectory(myApplication)
+ StreamFile;
on-error;
ifs_path = DefaultDir + '/' + StreamFile;
endmon;
In this case, getenv() returns *NULL if an environment variable is not
found, so %str() would throw an error that we can catch with monitor.
Similar to the earlier example, you could separate out the getenv() from
the rest of the logic, but sometimes it's just more elegant to not have
to do that, even if it's naturally occurring... Though, honestly, this
probably isn't a great example, since it wouldn't be that hard to
separate in this case, but my brain doesn't always come up with the best
examples when put on the spot. Hopefully, though, you can see what I mean.
When naturally occurring errors are easy to separate out of an
expression and test for, then I agree with you 100%. Also when
programming for performance, the sacrifice in readability is often worth
the tradeoff. But occasionally, you have situations where the
additional readability is worth using a monitor group even for naturally
occurring conditions.
-SK
On 7/1/2015 3:56 PM, John Yeung wrote:
On Wed, Jul 1, 2015 at 3:11 PM, Robert Rogerson <rrogerson@xxxxxxxxxxx> wrote:
I know that checking the divisor before doing the divide operation would
avoid this issue, but I thought this was one of the purposes of the monitor
group.
Besides the performance, it's worth considering the code readability.
A monitor group is particularly attractive if the alternative
(checking beforehand to ensure the error condition(s) can't occur)
makes the main logic of your code much more verbose or much harder to
read.
Also, some would argue that the true intended purpose of monitor
groups is to handle real errors, not just "infrequent but naturally
occurring conditions". That is, you never *expect* ON-ERROR blocks to
be needed at all, but you include them anyway so that your
mission-critical program can cope with the errors (without sweeping
them under the rug!) and soldier on.
In this particular case, I think checking the divisor is very cheap in
terms of execution time, and moderately cheap in terms of code
clutter. Unless the divide-by-zero condition will almost never occur
(and *should* never occur), I think I would go with the explicit test
for zero.
John Y.
As an Amazon Associate we earn from qualifying purchases.