我一直支持在工作中使用Moose(和MooseX :: Declare)几个月.它鼓励的风格将真正有助于我们的代码库的可维护性,但不是没有学习新语法的初始成本,特别是在学习如何解析类型验证错误.
我已经在网上看到了这个问题的讨论,并认为我会向这个社区发布一个查询:
a)已知的解决方案
b)讨论验证错误消息应该是什么样子
c)提出实现一些想法的概念证明
我也会联系作者,但我也看到了这个论坛的一些很好的讨论,所以我想我会公开发布一些东西.
#!/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();
Run Code Online (Sandbox Code Playgroud)
注意使用方法的签名调用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
Run Code Online (Sandbox Code Playgroud)
我认为大多数人都认为这不是那么直接.我在我的MooseX :: Method :: Signatures :: Meta :: Method的本地副本中实现了一个hack,它为同一个程序产生了这个输出:
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)
Run Code Online (Sandbox Code Playgroud)
执行此操作的超级hacky代码是
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;
}
Run Code Online (Sandbox Code Playgroud)
[注意:再过几分钟爬行代码,看起来像MooseX :: Meta :: TypeConstraint :: Structured :: validate更接近应该更改的代码.无论如何,关于理想错误信息的问题,以及是否有人正在积极研究或考虑类似的变化都是有效的.
这完成了3件事:
1)更简洁,更多的空白(我辩论包括s/Tuple //,但我现在坚持使用它)
2)包括调用文件/行(使用调用者(1))
3)死而不是忏悔 - 因为我认为忏悔的主要优点是找到用户进入类型检查的入口点,我们可以用更简洁的方式实现
当然我实际上并不想支持这个补丁.我的问题是:平衡这些错误消息的完整性和简洁性的最佳方法是什么,是否有任何当前的计划将这样的东西放到适当的位置?
raf*_*afl 10
我很高兴你喜欢MooseX::Declare.但是,您所讨论的方法签名验证错误并非真正来自那里,而是来自
MooseX::Method::Signatures,而后者又MooseX::Types::Structured用于其验证需求.您当前看到的每个验证错误都未经修改MooseX::Types::Structured.
我也将忽略错误消息的堆栈跟踪部分.我碰巧发现它们非常有用,其余的Moose cabal也是如此.我不会默认删除它们.
如果你想要一种关闭它们的方法,需要改变Moose以抛出异常对象而不是字符串,以用于类型约束验证错误和可能的其他事情.这些可能总是捕获回溯,但是关于是否显示它,或者在显示时如何格式化它的决定可以在其他地方做出,并且用户可以自由地修改默认行为 - 全局,本地,词法,随你.
我要解决的是为方法签名构建实际的验证错误消息.
正如所指出的,MooseX::Types::Structured实际验证是否有效.当某些内容无法验证时,它的工作就是引发异常.这个异常当前碰巧是一个字符串,所以当想要构建漂亮的错误时,它并不是那么有用,所以需要改变,类似于上面的堆栈跟踪问题.
一旦MooseX :: Types :: Structured抛出结构化的异常对象,它们可能看起来有些像
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')
Run Code Online (Sandbox Code Playgroud)
我们将有足够的信息来实际将各个内部验证错误与部分签名相关联MooseX::Method::Signatures.在上面的例子中,并给出了你的(Int $id, Str :$z, Str :$y)签名,很容易知道Validation::MissingValue位置参数的元组的第二个元素的内部应该提供值$id,但不能.
鉴于此,生成错误很容易
http://files.perldition.org/err1.png
要么
http://files.perldition.org/err2.png
这就是我想要的,而不仅仅是格式化我们现在更好的消息.但是,如果有人想这样做,一旦我们有结构化验证异常而不是普通字符串,它仍然很容易.
这些都不是很难 - 它只是需要做.如果有人感觉就像帮助了这一点,再来说说我们#moose的irc.perl.org.
| 归档时间: |
|
| 查看次数: |
691 次 |
| 最近记录: |