[英]Determine where Moose attributes and methods were inherited from?
I often work on a huge, not-very-well-documented, object-oriented Perl repo at my place of employment. 我经常在我的工作地点处理一个庞大的,没有很好记录的,面向对象的Perl回购。 While maintaining the code, I frequently need to trace things that are inherited from other classes so that I can understand what they're doing.
在维护代码的同时,我经常需要跟踪从其他类继承的内容,以便我能够理解他们正在做什么。 For example, I need to figure out what
$self->mystery
is and what it's doing: 例如,我需要弄清楚
$self->mystery
是什么以及它正在做什么:
package Foo::Bar;
use Moose;
use Method::Signatures;
use Foo::Bar::Element;
use Foo::Bar::Function;
use base qw (Baz::Foo::Bar);
method do_stuff ($some_arg) {
# mystery is not defined in Foo::Bar
my $mystery = $self->mystery;
$mystery->another_mystery($some_arg);
}
I usually find myself spending way too much time tracing through parent classes. 我经常发现自己花费太多时间来追踪父类。 So my question is, is there an easy way for me to figure out where
$self->mystery
comes from? 所以我的问题是,有一个简单的方法让我弄清楚
$self->mystery
来自哪里? Or in other words, I need to find where mystery is declared. 或者换句话说,我需要找到声明神秘的地方。
And by "easy way", I don't mean using ack
or grep
to string search through files. 通过“简单的方法”,我并不是说使用
ack
或grep
来搜索文件。 I'm hoping there's some sort of debugging module I can install and use which could help give me some insight. 我希望有一些我可以安装和使用的调试模块,这可以帮助我一些见解。
Thank you. 谢谢。
comes_from
Method! comes_from
方法! You don't need to download any special tool or module this, let alone some giant IDE because your undocumented class structure has gotten too complicated for mere humans ever to understand without a hulking IDE. 你不需要下载任何特殊的工具或模块,更不用说一些巨大的IDE,因为你的未记录的类结构已经变得太复杂,只有人类才能理解而没有笨重的IDE。
Why not? 为什么不? Simple: Standard Perl contains everything you need to get the answer you're looking for.
简单: 标准Perl包含您获得所需答案所需的一切 。 The easy way to find out where something comes from is to use the very useful
comes_from
method: 找出问题来源的简单方法是使用非常有用的
comes_from
方法:
$origin = $self->comes_from("mystery");
$secret_origin = $self->comes_from("another_mystery");
$birthplace = Some::Class->comes_from("method_name");
That will return the original name of the subroutine which that method would resolve to. 这将返回该方法将解析的子例程的原始名称。 As you see,
comes_from
works as both an object method and a class method, just like can
and isa
. 如您所见,
comes_from
可以作为对象方法, comes_from
可以作为类方法,就像can
和isa
。
Note that when I say the name of the subroutine it resolves to, I mean where that subroutine was originally created, back before any importing or inheritance. 请注意,当我说出它解析为的子例程的名称时,我指的是最初创建子例程的位置,在任何导入或继承之前。 For example, this code:
例如,这段代码:
use v5.10.1;
use Path::Router;
my($what, $method) = qw(Path::Router dump);
say "$what->$method is really ", $what->comes_from($method);
prints out: 打印出来:
Path::Router->dump is really Moose::Object::dump
Similar calls would also reveal things like: 类似的电话也会发现:
Net::SMTP->mail is really Net::SMTP::mail
Net::SMTP->status is really Net::Cmd::status
Net::SMTP->error is really IO::Handle::error
It works just fine on plain ole subroutines, too: 它也适用于普通的ole子程序:
SQL::Translator::Parser::Storable->normalize_name
is really SQL::Translator::Utils::normalize_name
The lovely comes_from
method isn't quite built in though it requires nothing outside of Standard Perl . 可爱的
comes_from
方法并不是完全内置的,尽管它不需要标准Perl之外的任何东西。 To make it accessible to you and all your classes and objects and more, just add this bit of code somewhere — anywhere you please really :) 为了使您和您的所有类和对象可以访问它,只需在某处添加这些代码 - 您真正喜欢的任何地方:)
sub UNIVERSAL::comes_from($$) {
require B;
my($invocant, $invoke) = @_;
my $coderef = $invocant->can($invoke) || return;
my $cv = B::svref_2object($coderef);
return unless $cv->isa("B::CV");
my $gv = $cv->GV;
return if $gv->isa("B::SPECIAL");
my $subname = $gv->NAME;
my $packname = $gv->STASH->NAME;
return $packname . "::" . $subname;
}
By declaring that as a UNIVERSAL
sub, now everybody who's anybody gets to play with it, just like they do with can
and isa
. 通过声明作为
UNIVERSAL
子,现在每个人都可以使用它,就像他们使用can
和isa
。 Enjoy! 请享用!
Are you sure you don't want an IDE? 您确定不需要IDE吗? It seems to be what you are asking about.
这似乎是你在问什么。 Padre , Eclipse EPIC , Emacs , and vim and many other editors offer some variation on the features you mention - probably simpler than you seem to want.
Padre , Eclipse EPIC , Emacs和vim以及许多其他编辑器对您提到的功能提供了一些变化 - 可能比您想要的更简单。 If you have big project to navigate
ctags
can help - it's usually easy to integrate into an editor and you are allowed to hack on your configuration file (with regexes BTW) to get it to recognize bits of a complicated set of source files. 如果您有大型项目导航
ctags
可以提供帮助 - 通常很容易集成到编辑器中,您可以破解配置文件(使用正则表达式 BTW),以使其识别一组复杂的源文件。
There is a related PERL FAQ entry about IDEs and a SO question: What's a good development environment for Perl? 有一个关于IDE的相关PERL FAQ条目和一个SO问题: Perl的开发环境是什么? .
。 There are also a host of CPAN modules you will want to use when developing that let you look into your code programmatically:
您还需要在开发时使用许多CPAN模块,以便以编程方式查看代码:
You can see an example of a script that looks for methods in classes in the SO node: Get all methods and/or properties in a given Perl class or module . 您可以看到一个脚本示例,该脚本在SO节点的类中查找方法: 获取给定Perl类或模块中的所有方法和/或属性 。
You might be able to get tools like these to help you hop around in your source in a way you find useful from a shell or from inside the debugger. 您可以使用这些工具来帮助您以一种从shell或调试器内部发现有用的方式在源代码中跳转。 Trepan has a good short summary of debugging tools as part of its documentation.
作为文档的一部分, Trepan对调试工具有一个很好的简短总结。 Generally though you can be very productive combining
Data::Dumper
the B::
modules ( B::Xref
, B::Deparse
, etc. , etc .) with the debugger and ack
. 但是总的来说,你可以非常高效结合
Data::Dumper
的B::
模块 ( B::Xref
, B::Deparse
, 等等 , 等等 。)与调试器和ack
。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.