Method::Signatures : Some relief for MooseX::Declare users
I have been excited about OO programming in Perl thanks to MooseX::Declare but I have never especially liked its performance hit and its cryptic warnings. It turns out that much of this problem is due to MooseX::Method::Signatures, which is used under the hood.
Many moons ago, I was curious about Moose and MooseX::Declare and I posted a question on StackOverflow. Venerable Perl guy Schwern then posted as a comment, that Method::Signatures was better than MooseX::Method::Signatures, and that there was a mod in the works to use it with MX::D.
Recently I have been working on a side-project (non-sciency) which lent itself to an OO design and so I chose MX::D as I often do, but the warning messages I was getting were killing me! I remembered the SO exchange and decided to look for that mod. Turns out it isn’t so much a mod(ification, read: patch) as an extra module, Method::Signatues::Modifiers, which overrides MX::M::S with its own magic when loaded. So I decided to give it a whirl. Here is a test:
use MooseX::Declare;
#use Method::Signatures::Modifiers;
class MyTest {
method do_something ( Ref $thingy ) {
print "Hello World";
}
}
my $obj = MyTest->new();
$obj->do_something( 1 ); # called with incorrect type
Without M::S::M (commented out) the error you get is the totally unreadable:
Validation failed for 'Tuple[Tuple[Object,Ref],Dict[]]' with value "[ [ MyTest=HASH(0x20fa7d0), 1 ], { } ], Internal Validation Error is: \n [+] Validation failed for 'Tuple[Object,Ref]' with value "[ MyTest{ }, 1 ]"\n [+] Validation failed for 'Ref' with value 1" at /home/joel/perl5/perlbrew/perls/perl-5.14.1/lib/site_perl/5.14.1/MooseX/Method/Signatures/Meta/Method.pm line 435 MooseX::Method::Signatures::Meta::Method::validate('MooseX::Method::Signatures::Meta::Method=HASH(0x20faa28)', 'ARRAY(0x20dce30)') called at /home/joel/perl5/perlbrew/perls/perl-5.14.1/lib/site_perl/5.14.1/MooseX/Method/Signatures/Meta/Method.pm line 151 MyTest::do_something('MyTest=HASH(0x20fa7d0)', 1) called at test.pl line 13
however WITH M::S::M (not commented) you get the far more pleasant and useful:
In call to MyTest::do_something(), the 'thingy' parameter ("1") is not of type Ref at test.pl line 13.
In the documentation, the authors (including Schwern, and Barefoot) note that M::S::M is not perfectly a drop-in replacement for MX::M::S, however the differences they note, I almost never use. So be aware, but don’t let that stop you from switching, you’ll be glad you did.
I haven’t done any compile timing tests, but Schwern seemed convinced that this would be improved too. Doesn’t matter, having useful error messages back is well worth the extra dependency and keystrokes.
Hey Joel, I’m so glad people are finding this module and making use of it. I wrote it primarily for myself/my company, but I think it has a lot of potential to make MooseX::Declare a viable option, even for people who have previously written it off. Besides the improvements in performance and error messages (which you note), there is also a weird whitespace bug in MXMS that shows up starting with Perl 5.12, and MSM fixes that too. So I think MSM is a great option, I’m so glad Schwern let me build it on top of MS, which is truly the heart of the system, and I’m glad you found it and found it useful. :-)
Joel,
For me it’s better late than never. Your initial post was back 2011, but it is a jewel of information.
I was getting what I refer to as “the Tuple errors”, on applications, from time to time. It took me so long to determine what the problem was.
Now I am working on a project that requires me to migrate an old Catalyst app to a Catalyst app with MooseX::Declare. There were a number of sections in the app where I received the Tuple error. It was a nightmare of a task to try and figure where the problem was.
After installing Method::Signatures::Modifiers and including the line of code to call the package, I was resolving all of the errors in lightning speed.
Thanks for posting this. It really helps and made a huge difference.
-Phil-
Hi Phil, since I wrote this, there have been other improvements, mostly in the Perl core itself. With these improvements that allowed MooseX::Declare to work, albeit with some scary side effects, newer modules can do similar things in a much better/safer way. I would suggest rather than MXD you might want to look into Moops which also brings in the highly recommended Type::Tiny module as well. Still if even this post is helping, then I’m glad I made it!