perl - Succinct MooseX::Declare method signature validation errors -
i've been proponent of adopting moose (and moosex::declare) @ work several months. style encourages maintainability of our codebase, not without initial cost of learning new syntax, , especially in learning how parse type validation errors.
i've seen discussion online of problem, , thought i'd post query community for:
a) known solutions
b) discussion of validation error messages should like
c) propose proof of concept implements ideas
i'll contact authors, i've seen discussion forum too, thought i'd post public.
#!/usr/bin/perl use moosex::declare; class foo { has 'x' => (isa => 'int', => 'ro'); method doit( int $id, str :$z, str :$y ) { print "doit called id = " . $id . "\n"; print "z = " . $z . "\n"; print "y = " . $y . "\n"; } method bar( ) { $self->doit(); # 2, z => 'hello', y => 'there' ); } } $foo = foo->new( x => 4 ); $foo->bar(); note mismatch in call foo::doit method's signature.
the error message results is:
validation failed 'moosex::types::structured::tuple[moosex::types::structured::tuple[object,int],moosex::types::structured::dict[z,moosex::types::structured::optional[str],y,moosex::types::structured::optional[str]]]' failed value [ [ foo=hash(0x2e02dd0) ], { } ], internal validation error is: validation failed 'moosex::types::structured::tuple[object,int]' failed value [ foo{ x: 4 } ] @ /usr/local/share/perl/5.10.0/moosex/method/signatures/meta/method.pm line 441 moosex::method::signatures::meta::method::validate('moosex::method::signatures::meta::method=hash(0x2ed9dd0)', 'array(0x2eb8b28)') called @ /usr/local/share/perl/5.10.0/moosex/method/signatures/meta/method.pm line 145 foo::doit('foo=hash(0x2e02dd0)') called @ ./type_mismatch.pl line 15 foo::bar('foo=hash(0x2e02dd0)') called @ ./type_mismatch.pl line 20 i think agree not direct be. i've implemented hack in local copy of moosex::method::signatures::meta::method yields output same program:
validation failed '[[object,int],dict[z,optional[str],y,optional[str]]]' failed value [ [ foo=hash(0x1c97d48) ], { } ] internal validation error: '[object,int]' failed value [ foo{ x: 4 } ] caller: ./type_mismatch.pl line 15 (package foo, subroutine foo::doit) the super-hacky code is
if (defined (my $msg = $self->type_constraint->validate($args, \$coerced))) { if( $msg =~ /moosex::types::structured::/ ) { $msg =~ s/moosex::types::structured:://g; $msg =~ s/,.internal/\n\ninternal/; $msg =~ s/failed.for./failed for\n\n /g; $msg =~ s/tuple//g; $msg =~ s/ is: validation failed for/:/; } ($pkg, $filename, $lineno, $subroutine) = caller(1); $msg .= "\n\ncaller: $filename line $lineno (package $pkg, subroutine $subroutine)\n"; die $msg; } [note: few more minutes of crawling code, looks moosex::meta::typeconstraint::structured::validate little closer code should changed. in case, question ideal error message, , whether actively working on or thinking similar changes stands.]
which accomplishes 3 things:
1) less verbose, more whitespace (i debated including s/tuple//, sticking now)
2) including calling file/line (with brittle use of caller(1))
3) die instead of confess -- since see main advantage of confess finding user's entry point typechecking anyway, can achieve in less verbose ways
of course don't want support patch. question is: best way of balancing completeness , succinctness of these error messages, , there current plans put in place?
i'm glad moosex::declare. however, method signature validation errors you're talking aren't there, moosex::method::signatures, in turn uses moosex::types::structured validation needs. every validation error see comes unmodified moosex::types::structured.
i'm going ignore stack-trace part of error message. happen find them incredibly useful, , rest of moose cabal. i'm not going removed them default.
if want way turn them off, moose needs changed throw exception objects instead of strings type-constraint validation errors , possibly other things. capture backtrace, decision on whether or not display it, or how format when displaying, made elsewhere, , user free modify default behaviour - globally, locally, lexically, whatever.
what i'm going address building actual validation error messages method signatures.
as pointed out, moosex::types::structured actual validation work. when fails validate, it's job raise exception. exception happens string, it's not useful when wanting build beautiful errors, needs change, similar issue stack traces above.
once moosex::types::structured throws structured exception objects, might like
bless({ type => tuple[tuple[object,int],dict[z,optional[str],y,optional[str]]], err => [ 0 => bless({ type => tuple[object,int], err => [ 0 => undef, 1 => bless({ type => int, err => bless({}, 'validationerror::missingvalue'), }, 'validationerror'), ], }, 'validationerror::tuple'), 1 => undef, ], }, 'validationerror::tuple') we have enough information available correlate individual inner validation errors parts of signature in moosex::method::signatures. in above example, , given (int $id, str :$z, str :$y) signature, it'd easy enough know inner validation::missingvalue second element of tuple positional parameters supposed provide value $id, couldn't.
given that, it'll easy generate errors such as
http://files.perldition.org/err1.png
or
http://files.perldition.org/err2.png
which kind of i'm going for, instead of formatting horrible messages have right more nicely. however, if 1 wanted that, it'd still easy enough once have structured validation exceptions instead of plain strings.
none of hard - needs doing. if feels helping out this, come talk in #moose on irc.perl.org.
Comments
Post a Comment