5

我有一个项目的 Perl 模块。我可能有十几个程序挂在上面,其中很多都是垃圾。我之前没有在 DBI 上花费太多私人时间,所以这部分是可以修复的,但重要的是它很大。字面意思是 2KLOC。

将这个函数(我们称之为 Dumb.pm)分解为单独的模块(Dumb::FormTools、Dumb::Database 等)很容易,但正如我所说,有很多程序已经“使用 Dumb”; '

我想通过 Dumb 导出 Dumb::Database 的可导出函数,而不必一遍又一遍地改变它:

sub my_dumb_function { return Dumb::Database::my_dumb_function( @_ ) ; }

不是我在上面。只是这似乎是处理问题的愚蠢和不雅的方式。我曾经用过一次“不知道没有更好”的借口,而且一次真的比你得到的要多。帮助?

4

4 回答 4

7

很难给你具体的建议,因为不同的代码库需要不同的策略。我重构一个包含 500 行子例程的模块,与重构一个包含小子例程和大量重复代码的模块不同。如果我也需要更改界面,则有不同的策略。

  1. 将所有内容都纳入源代码管理。您需要保留原始版本和中间版本。
  2. 如果您还没有测试套件,请编写一个。尽可能提高测试覆盖率。该测试套件是在未来版本、错误和所有内容中保留相同行为的基准。您可能会遇到依赖于原始模块中的错误的程序。
  3. 开始黑客攻击。在每个步骤中,检查其余部分是否仍通过原始测试,并且已发布的接口仍会产生相同的行为。

不过,我认为您的实际问题是“如何导出到加载 Dumb 的原始模块?”。您可以提供自己的import使用 Exporterimport_to_level方法的例程。您可以导入到比加载您的直接级别更高的级别。因此,即使它正在加载,Dumb::Database import也可以将其导出加载到加载的命名空间中。DumbDumbDumb::Database

于 2010-01-28T19:13:52.377 回答
3

不确定您当前如何使用它(它当前是否导出方法?),但您可以设置新的子模块以允许您导入它们的功能(使用 Exporter),然后让原始模块显式导入现在损坏的出件。就像是:

package Dumb;

use Dumb::Database qw(my_dumb_function);

1;

package Dumb::Database;

use base qw(Exporter);

our @EXPORT_OK = qw(my_dumb_function);

sub my_dumb_function { 1; }

1;
于 2010-01-28T18:48:23.827 回答
3

我假设 Dumb.pm 当前使用 Exporter。假设您不想重命名函数(只需将它们拆分为单独的模块),您应该能够保留现有@EXPORT定义,从子模块导入所有内容,并简单地重新导出函数。

package Dumb;
use Dumb::FormTools ':all';
use Dumb::Database  ':all';

use Exporter 'import';

our @EXPORT = ...;    # Unchanged from original version
our @EXPORT_OK = ...; # Unchanged from original version

1;

默认情况下:all未定义标签。您必须手动定义它(在每个子模块中)。

our %EXPORT_TAGS = ( all => [ @EXPORT, @EXPORT_OK ] );
# or, for a module that doesn't export anything by default:
our %EXPORT_TAGS = ( all => \@EXPORT_OK );

另一方面,如果子模块没有@EXPORT_OK功能,那么您可以跳过:all标签,直接说use Dumb::Submodule;.

于 2010-01-28T19:25:05.097 回答
1

您可能还想查看Sub::Exporter

于 2010-01-29T00:08:02.777 回答