Ouch!

TL;DR

Ouch is a great module.

I really thought that I already wrote something about Ouch, but apparently I’m not able to find anything. Maybe it was another personality, go figure.

What is this about?

Anyway, Ouch. It’s an opinionated way of throwing exceptions, which I found extremely attractive considering its simplicity and web-esque-enabling way of working.

This is how you throw an exception, typically:

ouch 404, 'Sorry, I miss this resource'
   unless exists $store{$requested_item_id};

ouch 500, "Ooops, seems there's an error in my logic!"
   unless makes_sense($current_status);

That’s it, a code for the machine and a message for the human.

I said typically because you can also add a third opaque $data parameter and basically pass whatever can make sense to track at higher levels, e.g. to produce better logs:

ouch 401, "Sounds like you can't do that", {
    request => $req,
    user    => $authenticated_user,
};

As I said, a code for the machine and a message for the human, plus data for the digger. Nothing prevents you to use different codes (strings, for example, or different numbers), so it can adapt pretty well to your style.

Catching exceptions

Ouch also provides some syntactic sugar when you catch exceptions. First of all, anyway, let’s see what happens when we’re not doing this:

$ perl -MOuch -e 'ouch 500, "Internal Server Error"'
Internal Server Error at -e line 1.
$ perl        -e 'die "Internal Server Error"'
Internal Server Error at -e line 1.

So we’re pretty confident that nothing bad happens when we don’t catch the exception. Let’s do this anyway:

$ perl -MOuch -E '
    eval {ouch 500, "Internal Server Error"};
    if (kiss 500)    {$bugs++; say bleep $@}
    elsif (kiss 404) {say bleep $@, ($misses++ > 1) ? ", again" : ""}
'
Internal Server Error

It’s basic Perl exception handling machinery, plus a way to figure out which exception was last thrown, and possibly act on it.

What’s with these function names?

I like the metaphor where the exception is treated like a (hopefully) minor wound. That’s why you say ouch when something happens, and receive a kiss for any different of these something or an overall hug that addresses them all at once. Also, swearing is not good - so you bleep your messages (which actually gets rid of the user-confusing indication of where the error happened in the code).

It’s not the only interface available, altough I can’t see anything wrong with it. Anyway, in JT Smith’s own words:

Some users are sticks in the mud who can’t bring themselves to ouch and kiss. For them, there is the :trytiny interface.

So yes, you can use more corporate-y names like throw instead of ouch and caught instead of kiss.

Try not to be a stick in the mud though.

Safer handling

There are a few issues with using basic eval for exception handling in Perl. I will not trace back to the first who pointed out this, and just provide you a hook to understand more on this: Try::Tiny’s BACKGROUND.

Which usually prompts me to use Try::Catch, i.e. Try::Tiny’s drop-in replacement that addresses these concerns without introducing other ones (from my perspective, at least).

Alas, this means that the exception variable gets changed from $@ (or $EVAL_ERROR for those fond of English) to $_ (i.e. $ARG or the topic). Which messes up with Ouch, that uses the traditional $@.

Confession time: I defined this as an impedence mismatch, which I admit: even with a typo, it’s jargon from electronics that might not make any sense for people from other backgrounds. Sorry, my bad, both for the jargon and the typo. But you can learn more about Impedance matching!

Anyway, if you’re into using Try::Tiny or Try::Catch, make sure to pass option :trytiny_var when useing the module, like this:

use Ouch ':trytiny_var';

so that Ouch will do the right thing and work with $_ by default, saving you some typing.

Did I convince you?

Let me know! If you want to try this out and don’t know where to start, take a look at Installing Perl Modules!


Comments? Octodon, , GitHub, Reddit, or drop me a line!