More Moose, More Discipline
One of the things that makes Moose so convenient is that it makes it easy to validate data without much effort. Perl code tends to be extremely permissive. That is: it's quite common not to find much type checking code, so if bad data is passed in, it's not caught until it's used, at which point the error message can be pretty weird. I know I have seen "
not an ARRAY reference" from weird places more times than I'd like to remember.
The reason, at least in part, is simple: type checking is a pain.
Moose makes it easy by associating type data with attributes. When your class includes:
...then you can feel confident at any point in your program that an object's
weight is a positive integer. Either the constructor will have thrown a clear exception when the object was constructed or it got the right kind of data.
Types can even be re-used outside the context of attribute definition to keep making data validation really pervasive.
Unfortunately, Moose has a gaping hole into which bad data can fall: the constructor.
So, we've got code representing the gift we're carefully picking out and painstakingly wrapping, but we stupidly do this:
Not only do we get no error, but our friend gets a package wrapped in thoughtless-seeming Amazon wrapping paper. Argh!
Only one change is needed:
MooseX::StrictConstructor causes the constructor to throw an exception on unknown input. For example, our bogus
wrappingpaper argument, above, would get us the exception:
Found unknown attribute(s) init_arg passed to the constructor: wrappingpaper
Sometimes, it's useful to accept an unknown set of extra arguments to your constructor. Maybe you do something like this:
Now you can pass
free_shipping => 1 to your constructor to clear out the otherwise-computed shipping cost… but it won't work with MooseX::StrictConstructor, because
free_shipping isn't the
init_arg of any attribute. Fortunately, there's a trivial fix. If you want to accept an argument for use in
BUILD just delete it so that it's not there anymore when
BUILD is done: