Mon Mar 2 16:30:00 2015

Moo 2 and strictures 2

By the time you read this, Moo 2 will already be percolating its way gently through the CPAN mirror system.

While there are assorted changes - mostly fixing up long standing inconsistencies - the biggest one isn't so much a mechanism as a policy change and that's what I want to talk about today.

Said change is: Moo 2 no longer implicitly exports strictures.

How we got here

When I first implemented Moo, I believed both that strictures was a pure net win from a safety point of view, and that our primary audience would be for newbies and sysadmins as their first taste of M* style OO.

Looking back? Zero for two.

In fact, the first belief was wrong twice. Firstly, I thought that having warnings be fatal in the name of test code failing fast and in the name of production code not falling into undefined behaviour would be a universal win; it turns out that some people's programming styles very much suit doing things that way and some people's don't - "get the tests written, get the code to pass the tests, then get the code to be warning free" is actually a perfectly reasonable workflow, even if it isn't to my taste.

Secondly, I'd been using fatal warnings in my own code for quite a while without running into a single problem ... but it turns out that the edge cases were more extensive than one might hope and I'd just not run into them. The key problem is that fatal warnings are sort of bolted on implementation wise, and it's occasionally possible to end up die()ing somewhere that really didn't expect that to be possible.

Thirdly (I said 'twice' because this one wasn't true when I started) the increasing use of the experimental and deprecation warning categories by perl core (for good reason, no complaints here) means that you're buying into "upgrading your perl could make your code blow up even though there's nothing necessarily wrong with it" (I was mostly ok with it blowing up due to perl detecting a new potential problem). This ... is not optimal.

strictures 2

So, in support of minimising the second and third of those, we've released strictures version 2, which now fatalizes most but not all warnings - and is careful to turn off anything that's been proven to be unsafe to catch, and anything that we expect to reflect only a changing environment rather than the validity of the code. Much love to haarg (Graham Knop) for his work figuring out which was which, and ribasushi (Peter Rabbitson) for gathering together a master list of footguns for us to double check against.

Even so, some things we can't paper over - notably, before 5.22 a compile time warning fatalizes immediately and therefore can obscure a compile time error that would've made the problem clearer, which is intensely irritating - and perhaps more importantly, it's now very clear that fatal warnings aren't as battle tested as we might like.

So, at this point, I must publically state that I no longer recommend strictures as a fully general positive, but instead recommend considering it as a set of trade-offs that may, depending on your requirements and workflow, do more good than harm. Certainly I believe it does for me and choose to continue to use strictures in my own projects, but I definitely now consider it to be a net win overall rather than universally.

Moo 2

Anyway. All of this is a good discussion of why you should/shouldn't use strictures, and I think implies a convincing case for it having to be opt-in, but it misses the other mistaken belief, which is actually a killer on its own.

Our primary audience is not, at this point, people new to Moo(se) OO, it's people coming from Moose. Which means that the principle of least surprise requires us to switch back to the 'use strict; use warnings;' only behaviour that Moose stole from my Reaction project somewhere close to a decade ago.

We're still going to document 'use strictures 2; use Moo;' because we still believe that, on average, newbies will derive more safety than pain from the suggestion, but the additional strictures should be explicit, not implicit.

I would, however, strongly recommend that if you continue to use strictures or adopt it in the future, you require version 2, because I no longer believe 'fatalize ALL the things' is a remotely adequate approach.

In Summary

Or, tl;dr

  • Moo <2 used to implicitly export strictures.
  • Moo 2+ will only do this for basic strict+warnings.
  • strictures is, nonetheless, worth considering using explicitly.
  • If you're using strictures at all, make sure to require version 2.
  • If you aren't, require Moo 2 to avoid it.

Enjoy Moo 2. Thanks to haarg for doing most of the actual work while I argued with people.

-- mst, out.