找到未使用的"use'd"Perl模块

Per*_*nti 13 perl module

我正在研究一个非常大的,非常古老的"历史悠久的"代码库.在过去,经常有人在想"哦,我可能需要这个和那个模块,所以我只是把它包括......",后来,人们经常"缓存"模块内的数据("使用ThisAndThat"需要一些几秒钟加载从DB到RAM的几百MB,是的,它真的是一个愚蠢的想法,我们也在努力)因此,通常,我们有一个小模块使用20或30个模块,其中90%是在源本身中完全未使用,并且,由于在几个使用的子模块中"缓存",模块往往需要花费一分钟来加载甚至更多,这当然是不可接受的.

所以,我试图让它做得更好.现在,我的方式是查看所有模块,尽可能地了解它们,然后查看包括它们在内的所有模块,看看它们是否需要.

有没有更简单的方法?我的意思是:有一些函数返回模块所具有的所有子函数

...
return grep { defined &{"$module\::$_"} } keys %{"$module\::"}
Run Code Online (Sandbox Code Playgroud)

那么,有没有简单的方法可以看到哪些是默认导出的,哪些来自哪里,并在其他模块中使用?

一个简单的例子是Data :: Dumper,它几乎包含在每个文件中,甚至,当所有调试警告和打印等等都不在脚本中时.但是模块仍然需要加载Data :: Dumper.

有没有简单的方法来检查?

谢谢!

Eri*_*ikR 7

以下代码可能是您的解决方案的一部分 - 它将显示为每个实例导入的符号use:

package traceuse;
use strict;
use warnings;
use Devel::Symdump;

sub import {
  my $class = shift;
  my $module = shift;

  my $caller = caller();

  my $before = Devel::Symdump->new($caller);

  my $args = \@_;
  # more robust way of emulating use?
  eval "package $caller; require $module; $module\->import(\@\$args)";

  my $after = Devel::Symdump->new($caller);

  my @added;
  my @after_subs = $after->functions;
  my %before_subs = map { ($_,1) } $before->functions;
  for my $k (@after_subs) {
    push(@added, $k) unless $before_subs{$k};
  }

  if (@added) {
    warn "using module $module added: ".join(' ', @added)."\n";
  } else {
    warn "no new symbols from using module $module\n";
  }
}
1;
Run Code Online (Sandbox Code Playgroud)

然后将"use module ..."替换为"use traceuse module ...",您将获得导入的函数列表.

用法示例:

package main;

sub foo { print "debug: foo called with: ".Dumper(\@_)."\n"; }

use traceuse Data::Dumper;
Run Code Online (Sandbox Code Playgroud)

这将输出:

using module Data::Dumper added: main::Dumper
Run Code Online (Sandbox Code Playgroud)

即,您可以确定哪些功能以强大的方式导入.您可以轻松地扩展它以报告导入的标量,数组和哈希变量 - 检查文档Devel::Symdump.

确定实际使用哪些函数是等式的另一半.为此,您可以使用简单的源代码grep - 即Dumper出现在模块的源代码中,而不是use在线上.这取决于您对源代码的了解.

笔记:

  • 可能有一个模块可以执行traceuse所做的事情 - 我没有检查过

  • 可能有更好的方法来模仿另一个包中的"使用"