重构perl子例程的参数列表

时间:2013-07-26 07:09:08

标签: perl refactoring

我正在重构一些应用程序代码,我希望能够从子例程中删除一些参数。例如,假设我有以下[1]:

sub do_something {
    my ( $param1, $param2, $param3, $param4 ) = ( @_ );
    ....
}

然而,作为重构的一部分,我使参数2和3变得多余。更新此方法签名是一个简单的部分,但有一种直接更新所有调用的方法吗?

我一直在做一些定制的grep / sed / perl来做这件事,但是对sub的一些调用是多行的,这使得它很痛苦,每次我在一个项目上这样做这是定制的。是否有适合进行此特定重构的工具?

[1] - 不是实际的参数或子程序名称,我向你保证!

2 个答案:

答案 0 :(得分:3)

Padre有一些重构功能,但我不知道它是否能达到你想要的效果。

将您的界面更改为接受哈希而不是位置列表,这将使未来的更改比现在更少。

sub do_something {
    my (%param) = (@_);
    ...
}

do_something(foo => 23, bar => 42);

答案 1 :(得分:0)

如果您的测试套件具有接近100%的代码覆盖率,您可以使用它来查找所有呼叫站点。

给出callstack中位置的参数,caller内置函数返回

  1. 来电者的包裹名称
  2. 文件名
  3. 行号
  4. 完全限定的子名称
  5. ......还有一些
  6. 我们现在可以添加一些记录调用位置的代码。我们可以将结果放入某些数据结构中进行自动处理,也可以将报告写入日志文件。 E.g。

    sub this_logs {
      {
        # seperate scope to not pollute your sub
        state $log_fh //= do {
          open my $fh, ">", "record_callsites.log"; # assuming autodie;
          $fh;
        };
        state $seen = {};
        my (undef,    undef, undef, $sub) = caller(1);
        my ($package, $file, $line,     ) = caller(0);
        my $site = $sub ? "$sub()" : "pkg $package";
        unless ($seen->{$file}{$line}++) {
          say {$log_fh} "CALL from $site at $file line $line";
        }
      }
      my ($param1, $param2) = @_;
      # etc
    }
    

    假设您的所有代码都是

    this_logs(1, 2, 3);         # direct call
    foo();                      # call from same package
    my $sub = "this_" . "logs"; 
    baz($sub);                  # call by name
    Foo::bar();                 # call from different package
    foo();                      # duplicate call
    
    sub foo {
      return this_logs(5, 6, 7);
    }
    sub baz {
      shift()->(1, 2, 3);  # no strict refs for this, please
    };
    
    package Foo;
    sub bar {
      main::this_logs();
    }
    

    这将生成日志文件

    CALL from pkg main at - line 20
    CALL from main::foo() at - line 28
    CALL from main::baz() at - line 31
    CALL from Foo::bar() at - line 3
    

    (文件名-表示STDIN)

    因此,给定一个合适的测试套件,可以找到无法获取的呼叫站点。

    如果您有非moronic编辑器,您还可以发出一个脚本,依次打开每个文件并将光标定位在正确的行上:

    say "kate -l $line $file";
    say "vim +$line $file";