Closed paultcochrane closed 6 years ago
For the external API, this 100% must be done how Minion::Backend::Pg (the official backend) does it. So, if it's got bare returns, we can do bare returns. If it has explicit undef
, we've got to do explicit undef
. The surrounding Minion classes expect the sub to return either a list or a scalar, and we've got to give it what it expects.
The problem with defaulting to list context is that it can also create undesired behavior: Bare return
can cause problems when a single, explicit value was expected:
my %vars = (
worker_info => $minion->worker(1)->info,
);
With return undef
, that does what we expect: Worker 1 doesn't exist. With return
, it turns into an odd-sized list (which Perl will warn us about). This was the cause of the Bugzilla security vulnerability a couple years back, and a few years worth of under-informed security-related bashing of Perl by Netanel Rubin.
I recall sri being proactive when that Bugzilla issue hit, so he probably went through and made sure every method had a single expected return context.
For the internal API (sub _update
), it doesn't largely matter, but I tend to make sure that subroutine names that seem singular return singular things. _update
doesn't sound like it should return anything, but it's only working with one thing, so it makes sense that one thing should be returned (the thing after we've updated it).
So, if Minion::Backend::Pg also does bare return, then we must. Otherwise, we must keep it as-is to keep compatibility with the API.
Wow, what an awesome answer! Clear, precise, and with lots of background information, mate that's fantastic! I'll have a look at Minion::Backend::Pg to see what it does, and give feedback here as to what I find out.
I've tried to grok the code in https://github.com/kraih/minion/blob/master/lib/Minion/Backend/Pg.pm and it looks like explicit undef
s should be returned. In two locations (https://github.com/kraih/minion/blob/master/lib/Minion/Backend/Pg.pm#L23 and https://github.com/kraih/minion/blob/master/lib/Minion/Backend/Pg.pm#L264) it explicitly returns undef
. Many of the other methods return the value of a query directly, which (I'm guessing) are probably also be undef
. Hence I think it's best in this case to leave the undef
s where they are. Thanks for the pointers about bugs resulting from bare return
. That's really interesting; I didn't know how potentially dangerous bare return
s were. It's good to know that one has to be very careful with return values, possibly more than instinct would suggest.
Explicitly returning undef can cause a subtle bug, where the return value evaluates as true instead of false as intended. It turns out that using the default return behaviour is actually safer, and hence why this is marked as a problem at the default perlcritic level.
This could be considered a controversial change, nevertheless, I thought I'd submit it just in case you want perlcritic compatability. If you don't want the change, just close unmerged, I won't be offended :-)