2015-03-06 4 views
5

Я часто работаю над огромным, не очень хорошо документированным объектно-ориентированным репо на моем месте работы. При сохранении кода мне часто приходится отслеживать вещи, унаследованные от других классов, чтобы я мог понять, что они делают. Например, мне нужно, чтобы выяснить, что $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); 
} 

Я обычно считаю себя тратить слишком много времени трассировки через родительские классы. Так что мой вопрос в том, есть ли простой способ для меня выяснить, откуда приходит $self->mystery? Или, другими словами, мне нужно найти, где объявляется тайна.

И «простой способ», я не имею в виду использование ack или grep для строкового поиска по файлам. Я надеюсь, что есть какой-то модуль отладки, который я могу установить и использовать, что могло бы помочь мне понять.

спасибо.

+0

Серьезно, если у вас нет * тон * методов в разных классах, все называемые 'mystery',' ack '^ sub mystery'' действительно являются наилучшим способом найти, где этот метод определен. –

+1

Вы не даете понять, как вы хотите использовать эту информацию. Я хотел бы, чтобы он был доступен в программной среде IDE, но поскольку вы запрашиваете * «какой-то модуль отладки» *, делает ли стандартный отладчик то, что вы хотите? Вы можете просто использовать 's' для шага * в * вызов метода и посмотреть, где он вас принимает. – Borodin

+0

@jcast - нет, не совсем. 'mystery' может быть атрибутом Moose. Или используйте для этого репо, это может быть либо 'sub', либо' method', в зависимости от того, кто его написал. Или он может быть определен как метод обработчика: 'имеет foo => (is => 'ro', handles => [qw (bar mystery baz)]' –

ответ

5

Благодаря стандартному Perl. , , Метод comes_from!

Вам не нужно загружать какой-либо специальный инструмент или модуль, не говоря уже о какой-то гигантской среде IDE, потому что ваша недокументированная структура классов стала слишком сложной для простых людей, которых когда-либо понимали без неуклюжих IDE.

Почему нет?Простой: Стандартный Perl содержит все, что вам нужно, чтобы получить ответ, который вы ищете. Самый простой способ узнать, где что-то происходит от заключается в использовании очень полезный comes_from метода:

$origin  = $self->comes_from("mystery"); 
$secret_origin = $self->comes_from("another_mystery"); 
$birthplace = Some::Class->comes_from("method_name"); 

Это возвратит оригинальное имя подпрограммы, которые этот метод позволит решить к. Как вы видите, comes_from работает как метод объекта, так и метод класса, как и can и isa.

Обратите внимание, что когда я говорю имя подпрограммы, которую он разрешает, я имею в виду, где эта подпрограмма была первоначально создана, перед каким-либо импортом или наследованием. Например, этот код:

use v5.10.1; 
use Path::Router; 
my($what, $method) = qw(Path::Router dump); 
say "$what->$method is really ", $what->comes_from($method); 

печатает:

Path::Router->dump is really Moose::Object::dump 

Подобные звонки также раскрывающие такие вещи, как:

Net::SMTP->mail  is really Net::SMTP::mail 
Net::SMTP->status is really Net::Cmd::status 
Net::SMTP->error is really IO::Handle::error 

Он прекрасно работает на равнинных Ole подпрограммами тоже:

SQL::Translator::Parser::Storable->normalize_name 
is really SQL::Translator::Utils::normalize_name 

l l ovely comes_from метод не довольно встроен, хотя он не требует ничего за пределами Стандартный Perl. Для того, чтобы сделать его доступным для вас и всех ваших классов и объектов и многое другое, просто добавьте этот кусок кода где-то - в любом месте, пожалуйста, на самом деле :)

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; 
} 

Объявив, что в UNIVERSAL подразделам, теперь все, кто-нибудь получает играйте с ним, как и в случае с can и isa. Наслаждайтесь!

+1

Спасибо, это Совершенно так просто, именно то, что я искал. –

2

Вы уверены, что не хотите IDE? Кажется, это то, о чем вы просите. Padre, Eclipse EPIC, Emacs и vim и многие другие редакторы предлагают некоторые варианты функций, которые вы упоминаете, - вероятно, проще, чем вам кажется. Если у вас есть большой проект для навигации ctags, это может помочь - его обычно легко интегрировать в редактор, и вы можете взломать свой файл конфигурации (с regexes BTW), чтобы получить его для распознавания бит сложного набора исходных файлов.

Существует связанный PERL FAQ entry about IDEs и вопрос: What's a good development environment for Perl?. Есть также множество модулей CPAN вы хотите использовать при разработке, что позволит вам заглянуть в ваш код программно:

Вы можете увидеть пример скрипта, который ищет методы в классах в узле SO: Get all methods and/or properties in a given Perl class or module.

Возможно, у вас есть инструменты, подобные этим, чтобы помочь вам прыгать в вашем источнике так, как вы считаете полезным из оболочки или изнутри отладчика. Trepan имеет хорошее краткое описание инструментов отладки в рамках своей документации. Вообще, хотя вы можете быть очень продуктивным комбинируя Data::DumperB:: modules (B::Xref, B::Deparse, и т.д., etc.) С отладчиком и ack.

+0

Благодарим вас за все перечисленные вами ресурсы. Это выглядит великолепно, я собираюсь попробовать это. –

+0

@ 2rare2die, вы можете проверить ['MooseX :: amine' и mex] (https://metacpan.org/pod/MooseX::amine). Я добавлю их в свой ответ. –

+0

Как только структура класса программы становится слишком сложной для простого понимания людьми без помощи среды IDE, она прошла точку без возврата, и вы могли бы также использовать Java, а не Perl. :(По какой-то причине такая непостижимая призрачная магия на расстоянии не беспокоит пользователей Moose. Для остальных из нас, к счастью, стандартного Perl хватает, и нас не принуждают в Джаваленд против нашего согласия. – tchrist

 Смежные вопросы

  • Нет связанных вопросов^_^