Beefy Boxes and Bandwidth Generously Provided by pair Networks
more useful options
 
PerlMonks  

Re^7: eval to replace die?

by BrowserUk (Pope)
on Oct 04, 2010 at 17:57 UTC ( #863390=note: print w/ replies, xml ) Need Help??


in reply to Re^6: eval to replace die?
in thread eval to replace die?

Imagine instead I wrote "the risk and fragility of using fuzzy regular expression matches for exception handling, especially when type checks and polymorphism are much more reliable".

And I say you are talking bollocks.

  • Because "type checks" are just string compares.

    Pretty much exactly:

    if( ref( $obj ) eq $type ) { ... ## or if( $obj =~ m[=$type$] ) { ...
    .
  • And polymorphism--of the type you are alluding to--is just multiple string compares.

    Pretty much:

    if( ref( $exception ) eq $type ) or grep{ ref( $exception ) eq $_ } @{ $type::ISA } ) { ... ## or if( $exception =~ m[=$type$] or grep{ $exception =~ m[=$_] } @{ $type::ISA } ) { ...

which demonstrates the lie of "more reliable, never mind "much more reliable.

You are selling a philosophy--your own home-spun, personal prejudice--on the basis of a technical merit which it simply does not live up to.

Exception::Class exceptions are:

  1. defined in terms of strings:
    use Exception::Class ( 'MyException', 'AnotherException' => { isa => 'MyException' },
  2. thrown in terms of strings: MyExceptions->throw( error => 'Divisor undefined' ) unless defined $d;
  3. and caught in terms of strings: if ( $e = Exception::Class->caught('MyException') ) {

Which means you're even more reliant upon string compares, but now you have more places to change in order to maintain them.

I really wonder if you think through your justifictions at all. It sure doesn't look like it.


Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
"Science is about questioning the status quo. Questioning authority".
In the absence of evidence, opinion is indistinguishable from prejudice.


Comment on Re^7: eval to replace die?
Select or Download Code
Re^8: eval to replace die?
by chromatic (Archbishop) on Oct 04, 2010 at 18:28 UTC

    Which version of Exception::Class did you read? The caught() method in E::C 1.32 includes the type check:

        return unless blessed($e) && $e->isa( $_[1] );

    I trust the Perl 5 core to get isa() right for a type check (and I trust that everyone following this conversation can trivially distinguish between an exact string match and a regular expression match in terms of fragility).

      The caught() method in E::C 1.32 includes the type check: return unless blessed($e) && $e->isa( $_1 );

      Yep! Same code. Which brings us right back to my first question way back up there.

      What does isa() do?

      This is what it does:

      int Perl_sv_isa(pTHX_ SV *sv, const char *const name) { const char *hvname; PERL_ARGS_ASSERT_SV_ISA; if (!sv) return 0; SvGETMAGIC(sv); if (!SvROK(sv)) return 0; sv = SvRV(sv); if (!SvOBJECT(sv)) return 0; hvname = HvNAME_get(SvSTASH(sv)); if (!hvname) return 0; return strEQ(hvname, name); }

      It check you've given it an sv, checks it's a reference; checks the refenced thing is an object; gets the package name from the stash where the object is stored; and then string compares that with the type-name string you passed in.

      (And all of those same check will be followed when a reference is stringified!)

      Now lets go back to where we came in with you saying:

      If you're performing an exact match, a substring match, or a regular expression, any change to the text of that message in a subsequent release of Perl 5 could change the way your code behaves.

      So are you now saying that exact matches are okay?

      That its only regex matches that are "unreliable"? (Or are substring matches still verbotten?)

      If so, why are you ignoring the ref versions that used string compare instead of the regex engine?

      And why are you still insisting that Perl's regex engine is unreliable?

      What all your snide asides and unstated implications resolve to, is that the regex engine is incapable of safely comparing strings.

      Which you know is rubbish!

      (And once again I'll ask you to post code so we can all test your assertions!)


      Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
      "Science is about questioning the status quo. Questioning authority".
      In the absence of evidence, opinion is indistinguishable from prejudice.
        What all your snide asides and unstated implications resolve to, is that the regex engine is incapable of safely comparing strings.

        You skipped over the simpler (and verifiable, per my use of the word "parsing" in my first post in this thread) implication that the unreliable part is writing good regular expressions which are not fragile in the face of simple changes to unstructured data. (That's the same reason many people suggest not parsing HTML with regular expressions, for example.)

Re^8: eval to replace die?
by mpeters (Chaplain) on Oct 04, 2010 at 21:24 UTC

    Come on, this is just silly. Yes isa() will use string compares, but to say it's just a string compare is like saying a marathon is "just moving your feet". Just one example is that isa() knows how to look up the inheritance tree and tell me if one of my ancestors also meets the criteria.

    Here's an example from a recent project of mine where structured exception objects helps out a lot. I have some code that runs remote commands on different servers. This code could be called from lots of different places and depending on how it's called the error handling is different. I could just die "Couldn't run $cmd on server $server", but then I have to parse that string with regular expressions to get the $cmd and $server values, every place it could be used (the same regular expression in lots of different places, not very DRY). And if I ever decide to change that error message I have to then track down all the places that regular expression lives (which is much, much harder than searching for a simple string in piles of code) and change them. It gets even worse if this module is used in places that I don't control (I'm flattered when someone uses my CPAN modules and don't want to make their job any harder than it has to be).

    But instead I can use an Exception::Class object and do something like Project::FailedRemoteCommand->throw(error => "Couldn't run $cmd on server $server", command => $cmd, server => $server). Now the code that uses this doesn't have to care about my actual error message, just the type of error. Not only is searching for "FailedRemoteCommand" in a code base easier than searching for regex, it's also more future proof. Modules that use my lib don't have to care about the exact text of my error message either. They can get the $e->server or $e->command easily. And if they don't care about the structured exception, it still works just like a string to them.

    Yes they might have problems if I ever decide to restructure my exception hierarchy (which is much rarer than changing an error message) but even that can be handled by having some special isa() magic to make the new classes still look like the old to old code. Try doing that when you're just using strings.


    -- More people are killed every year by pigs than by sharks, which shows you how good we are at evaluating risk. -- Bruce Schneier
      Just one example is that isa() knows how to look up the inheritance tree

      Actually the built-in isa() only checks one level. UNIVERSAL::isa() does a hierarchy traversal--which is a hash lookup. And a hash lookup is just a string compare at it's heart.

      But if you're using eval & die you don't need isa, so the point (in context) is moot.

      Chromatic suggested that using exceptions avoided "unreliable string comaprisons, substring comparisons and regexes". Which it doesn't. It just moves them.

      I have to parse that string with regular expressions to get the $cmd and $server values, every place it could be used

      Why do they have to parse the string? (Ie. Why do they need to obtain the the server and command from the text?).

      If you/they are going to 'fix' the error, then they will (should) be doing it at a point in the code where they already have that information at hand.

      That is, if they are at a point where they could re-issue the command to a different server; or issue a different command to the same server; then they will be at a point where they have both available, because they provided that information to the call that cause the error (exception) in the first place.

      If they are further back up the call hierarchy, all they can do is report the error (or ignore it), and they don't need to parse the error message, it already contains the relevant information.

      not very DRY). And if I ever decide to change that error message I have to then track down all the places that regular expression lives (which is much, much harder than searching for a simple string in piles of code) and change them.

      The DRY solution is don't put copies of the same regex in multiple places. Define the regex once, name it, and import it wherever it is needed.

      Yes they might have problems if I ever decide to restructure my exception hierarchy (which is much rarer than changing an error message) but even that can be handled by having some special isa() magic to make the new classes still look like the old to old code. Try doing that when you're just using strings.

      You're fixing the symptoms, not the problem.

      If the error applies to the same condition, it is the same error. The error handler shouldn't need to change because you changed the description of the error. And that is just as easily achieved using a regex as it is exception objects.


      Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
      "Science is about questioning the status quo. Questioning authority".
      In the absence of evidence, opinion is indistinguishable from prejudice.

        Chromatic suggested that using exceptions avoided "unreliable string comaprisons, substring comparisons and regexes". Which it doesn't. It just moves them.

        Yes it does. It's not the string comparisons and regular expression matches that are unreliable. It's the process of determining the type of an error by the representation of it (the message).

        For example, if you check if the error starts with "Foo", I will break your exception handling by throwing any error that starts with "Foo". That can't happen if the type of the error is carried externally to the representation shown to the user. And an object with a class is just that kind of an error. If you throw a MyError::Foo, I would have to explicitly throw that error or a subclass of it for it to be recognised by your error handling.

        Handling errors by message inspection works fine as long as you're the only developer in the code base. And never upgrade.


        Ordinary morality is for ordinary people. -- Aleister Crowley
        If you/they are going to 'fix' the error, then they will (should) be doing it at a point in the code where they already have that information at hand.

        You're assuming that the only reason to catch an error is to try to fix it. There are lots of other reasons, like ignoring it, changing the error message for a different audience, etc.

        If you think it's ok to just output an error message from a low level 3rd party module to the user of your software on the screen, then you've failed at creating usable software. If you don't use 3rd party modules (like CPAN modules) and all your users are programmers, and all of the users of your users (if you're writing modules that can be used by 3rd parties) are also programmers, then maybe you have an excuse.

        But I like the freedom to be able to decide how I want to handle different kinds of exceptions (escpecially if they have some kind of structured data) without having to resort to parsing every error message by hand. And the really nice thing about Exception::Class is that if you don't care about all the extra goodies it provides, then just ignore it an treat it like a string and leave the rest of us alone.


        -- More people are killed every year by pigs than by sharks, which shows you how good we are at evaluating risk. -- Bruce Schneier

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: note [id://863390]
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others romping around the Monastery: (6)
As of 2014-09-15 04:01 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    My favorite cookbook is:










    Results (145 votes), past polls