Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/perl/10.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
什么';将monster Perl模块重构为子模块的好方法是什么?_Perl_Perl Module - Fatal编程技术网

什么';将monster Perl模块重构为子模块的好方法是什么?

什么';将monster Perl模块重构为子模块的好方法是什么?,perl,perl-module,Perl,Perl Module,我有一个项目的Perl模块。我可能有十几个程序挂在上面,很多都是垃圾。我以前没有与DBI有过太多亲密的私人关系,所以这部分是可以修复的,但重要的是它是大的。从字面上说是两个洛克斯 很容易将这个函数(我们称之为Dumb.pm)分解成单独的模块(Dumb::FormTools、Dumb::Database等),但正如我所说,有很多程序已经“使用Dumb;” 我想通过Dumb导出Dumb::Database的可导出函数,而不必反复修改: sub my_dumb_function { return Du

我有一个项目的Perl模块。我可能有十几个程序挂在上面,很多都是垃圾。我以前没有与DBI有过太多亲密的私人关系,所以这部分是可以修复的,但重要的是它是大的。从字面上说是两个洛克斯

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

我想通过Dumb导出Dumb::Database的可导出函数,而不必反复修改:

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

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

不确定您当前如何使用它(它当前是否导出方法?),但您可以设置新的子模块以允许您导入其功能(使用导出器),然后让原始模块显式导入现在分解的部分。比如:

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;

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

  • 把所有东西都放到源代码管理中。您需要保留原始版本和中间版本
  • 如果您还没有测试套件,请编写一个。获得尽可能高的测试覆盖率。这个测试套件是在将来的版本、错误和所有错误中保留相同行为的基线。您可能会遇到一个依赖于原始模块中的bug的程序
  • 开始黑客攻击。在每个步骤中,检查其余部分是否仍然通过原始测试,以及发布的接口是否仍然导致相同的行为

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

    我假设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
    标记。您必须手动定义它(在每个子模块中)


    另一方面,如果子模块没有
    @EXPORT\u OK
    功能,那么您可以跳过
    :all
    标记,只说
    使用Dumb::submodule

    您可能还想研究一下

    我没有时间写一个正确的答案,但是您可以在
    Dumb
    中使用自定义的
    import
    函数,将对
    import
    的调用路由到各个子模块。只有2k LOC?哇,一个很好的小模块!;)。。。然后是我在上一份工作中继承的14K怪物,有7K个提交日志…
    *我的dumb\u函数=\&dumb::Database::my\u dumb\u函数
    这几乎就是Exporter的功能。我只有使用“use Exporter qw(import);”才能让它工作,但这意味着我能够让它工作。非常感谢。您还可以从Exporter继承,这就是我的意思。对不起,我已经更正了。我不明白你为什么建议将
    导入到\u级别
    Dumb
    将成为向后兼容模块,直到
    使用Dumb可以由特定程序需要的单个模块替换。当库存
    import
    允许
    Dumb
    重新导出从新模块导入的功能时,您为什么要在每个新模块中编写自定义
    import
    ,以决定导出到哪个级别?如果
    Dumb
    需要拆分为单独的模块,并且顶级程序仍然希望获得只需使用
    Dumb
    就可以从这些单独的模块导出,这样您就不想在
    Dumb
    中导入了。但是,如果OP想做其他事情,我不推荐它作为解决方案。这里有很多方法。你的答案是正确的,但我认为你必须导入Dumb,这样你才能将相同的东西导出到更高的层次,这是不雅的。正如我理解OP的问题,他有一个巨大的模块,可以做很多不同的事情。他希望自己使用了单独的模块,这样脚本就可以只加载实际使用的模块。但他不想追踪每一个说
    使用Dumb
    的程序,并修复它以导入正确的模块。他需要一个Dumb.pm与现有的导出进行向后兼容,这样他就可以逐步修复那些
    使用Dumb
    的程序,使其只使用实际需要的模块。这是一种看待问题的方法,但我认为这是在添加一些不存在问题的假设。我没有做出和你一样的假设。这些可能是有道理的,但只有他才能澄清他想要做什么,以及哪个答案更适合他
    our %EXPORT_TAGS = ( all => [ @EXPORT, @EXPORT_OK ] );
    # or, for a module that doesn't export anything by default:
    our %EXPORT_TAGS = ( all => \@EXPORT_OK );