简洁的 MooseX::Declare 方法签名验证错误 [英] Succinct MooseX::Declare method signature validation errors

查看:51
本文介绍了简洁的 MooseX::Declare 方法签名验证错误的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

几个月来,我一直支持在工作中采用 Moose(和 MooseX::Declare).它所鼓励的风格确实有助于我们代码库的可维护性,但并非没有学习新语法的一些初始成本,特别是学习如何解析类型验证错误.

I've been a proponent of adopting Moose (and MooseX::Declare) at work for several months. The style it encourages will really help the maintainability of our codebase, but not without some initial cost of learning new syntax, and especially in learning how to parse type validation errors.

我在网上看到了关于这个问题的讨论,我想我会向这个社区发布一个查询:

I've seen discussion online of this problem, and thought I'd post a query to this community for:

a) 已知的解决方案

b) 讨论验证错误消息应该是什么样子

b) discussion of what validation error messages should look like

c) 提出实现一些想法的概念证明

c) propose a proof of concept that implements some ideas

我也会联系作者,但我在这个论坛也看到了一些很好的讨论,所以我想我会发布一些公开的内容.

I'll also contact the authors, but I've seen some good discussion this forum too, so I thought I'd post something public.

#!/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 与方法签名的不匹配.

Note the mismatch in the call to Foo::doit with the method's signature.

导致的错误信息是:

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 的本地副本中实现了一个 hack,它为同一个程序产生了这个输出:

I think that most agree that this is not as direct as it could be. I've implemented a hack in my local copy of MooseX::Method::Signatures::Meta::Method that yields this output for the same program:

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)

执行此操作的超级黑客代码是

The super-hacky code that does this 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 更接近应该更改的代码.无论如何,关于理想的错误消息以及是否有人正在积极致力于或考虑类似更改的问题仍然存在.]

[Note: With a few more minutes of crawling the code, it looks like MooseX::Meta::TypeConstraint::Structured::validate is a little closer to the code that should be changed. In any case, the question about the ideal error message, and whether anyone is actively working on or thinking about similar changes stands.]

完成三件事:

1) 不那么冗长,更多的空白(我讨论过包括 s/Tuple//,但我现在坚持使用它)

1) Less verbose, more whitespace (I debated including s/Tuple//, but am sticking with it for now)

2) 包括调用文件/行(调用者(1)的脆弱使用)

2) Including calling file/line (with brittle use of caller(1))

3) 死而不是承认——因为在我看来,承认的主要优点是无论如何都能找到用户进入类型检查的入口点,我们可以用不那么冗长的方式来实现

3) die instead of confess -- since as I see it the main advantage of confess was finding the user's entry point into the typechecking anyway, which we can achieve in less verbose ways

我当然不想支持这个补丁.我的问题是:平衡这些错误消息的完整性和简洁性的最佳方法是什么,目前是否有计划将这样的内容落实到位?

Of course I don't actually want to support this patch. My question is: What is the best way of balancing completeness and succinctness of these error messages, and are there any current plans to put something like this in place?

推荐答案

很高兴您喜欢 MooseX::Declare.但是,方法签名验证你所说的错误并不是真的来自那里,而是来自MooseX::Method::Signatures,它依次使用 MooseX::Types::Structured它的验证需求.您当前看到的每个验证错误都未经修改来自 MooseX::Types::Structured.

I'm glad you like MooseX::Declare. However, the method signature validation errors you're talking about aren't really from there, but from MooseX::Method::Signatures, which in turn uses MooseX::Types::Structured for its validation needs. Every validation error you currently see comes unmodified from MooseX::Types::Structured.

我还将忽略错误消息的堆栈跟踪部分.我碰巧发现它们非常有用,Moose 阴谋集团的其余部分也是如此.我不去默认情况下删除它们.

I'm also going to ignore the stack-trace part of the error message. I happen to find them incredibly useful, and so does the rest of Moose cabal. I'm not going to removed them by default.

如果你想关闭它们,Moose需要改成抛出异常对象而不是字符串用于类型约束验证错误和可能其他事情.那些总是可以捕获回溯,但决定是否显示它,或者显示时如何精确地格式化它,可以在其他地方制作,用户可以自由修改默认行为 -全局、本地、词汇等等.

If you want a way to turn them off, Moose needs to be changed to throw exception objects instead of strings for type-constraint validation errors and possibly other things. Those could always capture a backtrace, but the decision on whether or not to display it, or how exactly to format it when displaying, could be made elsewhere, and the user would be free to modify the default behaviour - globally, locally, lexically, whatever.

我要解决的是构建实际的验证错误消息方法签名.

What I'm going to address is building the actual validation error messages for method signatures.

正如所指出的,MooseX::Types::Structured 进行实际的验证工作.当某些事情无法验证时,它的工作就是引发异常.这异常当前恰好是一个字符串,因此当想要构建漂亮的错误,因此需要更改,类似于问题上面有堆栈跟踪.

As pointed out, MooseX::Types::Structured does the actual validation work. When something fails to validate, it's its job to raise an exception. This exception currently happens to be a string, so it's not all that useful when wanting to build beautiful errors, so that needs to change, similar to the issue with stack traces above.

一旦 MooseX::Types::Structured 抛出结构化异常对象,这可能有点像

Once MooseX::Types::Structured throws structured exception objects, which might look somewhat 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')

我们将有足够的可用信息来实际关联个人MooseX::Method::Signatures 中部分签名的内部验证错误.在上面的例子中,和给定你的 (Int $id, Str :$z, Str :$y) 签名,很容易知道的第二个元素的非常内部的 Validation::MissingValue位置参数的元组应该为 $id 提供一个值,但是不能.

we would have enough information available to actually correlate individual inner validation errors with parts of the signature in MooseX::Method::Signatures. In the above example, and given your (Int $id, Str :$z, Str :$y) signature, it'd be easy enough to know that the very inner Validation::MissingValue for the second element of the tuple for positional parameters was supposed to provide a value for $id, but couldn't.

鉴于此,很容易产生诸如

Given that, it'll be easy to generate errors such as

http://files.perldition.org/err1.png

http://files.perldition.org/err2.png

这就是我想要的,而不仅仅是格式化可怕的我们现在有更好的消息.但是,如果有人想这样做,它会一旦我们有结构化的验证异常而不是普通字符串.

which is kind of what I'm going for, instead of just formatting the horrible messages we have right now more nicely. However, if one wanted to do that, it'd still be easy enough once we have structured validation exceptions instead of plain strings.

这实际上并不难 - 只需要做.如果有人想帮忙有了这个,请在​​ irc.perl.org 上的 #moose 中与我们交谈.

None of this is actually hard - it just needs doing. If anyone feels like helping out with this, come talk to us in #moose on irc.perl.org.

这篇关于简洁的 MooseX::Declare 方法签名验证错误的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆