Я был сторонником принятия Moose (и MooseX :: Declare) на работе в течение нескольких месяцев.Стимулируемый им стиль действительно поможет поддерживать нашу кодовую базу, но не без первоначальных затрат на изучение нового синтаксиса и особенно на изучение того, как анализировать ошибки проверки типов.
Я имеювидел обсуждение этой проблемы в Интернете и думал, что я отправлю запрос в это сообщество:
а) известные решения
б) обсуждение того, как должны выглядеть сообщения об ошибках валидации
в) предложить доказательство концепции, которая реализует некоторые идеи
Я также свяжусь с авторами, но я также видел несколько хороших обсуждений на этом форуме, поэтому я решил опубликовать что-то публичное.
#!/usr/bin/perl
use MooseX::Declare;
class Foo {
has 'x' => (isa => 'Int', is => 'ro');
method doit( Int $id, Str :$z, Str :$y ) {
print "doit called with id = " . $id . "\n";
print "z = " . $z . "\n";
print "y = " . $y . "\n";
}
method bar( ) {
$self->doit(); # 2, z => 'hello', y => 'there' );
}
}
my $foo = Foo->new( x => 4 );
$foo->bar();
Обратите внимание на несоответствие в вызове Foo :: doit с подписью метода.
В результате появляется сообщение об ошибке:
Validation failed for '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 with value [ [ Foo=HASH(0x2e02dd0) ], { } ], Internal Validation Error is: Validation failed for 'MooseX::Types::Structured::Tuple[Object,Int]' failed with value [ Foo{ x: 4 } ] at /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 at /usr/local/share/perl/5.10.0/MooseX/Method/Signatures/Meta/Method.pm line 145
Foo::doit('Foo=HASH(0x2e02dd0)') called at ./type_mismatch.pl line 15
Foo::bar('Foo=HASH(0x2e02dd0)') called at ./type_mismatch.pl line 20
Я думаю, чтобольшинство согласны с тем, что это не так прямо, как могло бы быть.Я реализовал хак в моей локальной копии MooseX :: Method :: Signatures :: Meta :: Method, который выдает этот вывод для той же программы:
Validation failed for
'[[Object,Int],Dict[z,Optional[Str],y,Optional[Str]]]' failed with value [ [ Foo=HASH(0x1c97d48) ], { } ]
Internal Validation Error:
'[Object,Int]' failed with value [ Foo{ x: 4 } ]
Caller: ./type_mismatch.pl line 15 (package Foo, subroutine Foo::doit)
Супер-хакерский код, который делает это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/:/;
}
my ($pkg, $filename, $lineno, $subroutine) = caller(1);
$msg .= "\n\nCaller: $filename line $lineno (package $pkg, subroutine $subroutine)\n";
die $msg;
}
[Примечание: после нескольких минут обхода кода это выглядит как MooseX :: Meta :: TypeConstraint :: Structured :: validate немного ближе к коду, который нужно изменить,В любом случае, вопрос об идеальном сообщении об ошибке и о том, активно ли кто-то работает или думает о подобных изменениях, стоит.]
, который выполняет 3 вещи:
1) Меньше многословно, большепробел (я обсуждал, включая s / Tuple //, но пока придерживаюсь его)
2) Включая вызывающий файл / линию (с хрупким использованием вызывающей стороны (1))
3)умереть вместо признания - поскольку, на мой взгляд, главным преимуществом признания было нахождение точки входа пользователя в проверку типов в любом случае, чего мы можем достичь менее подробными способами
Конечно, я на самом деле не хочуподдержать этот патч.Мой вопрос: каков наилучший способ сбалансировать полноту и краткость этих сообщений об ошибках, и есть ли в настоящее время какие-либо планы по внедрению чего-то подобного?