在实时网站上重构Perl代码。相互模块依赖关系是否正常?

在实时网站上重构Perl代码。相互模块依赖关系是否正常?,perl,recursion,refactoring,Perl,Recursion,Refactoring,我们有一个基于Perl的大型网站 我被指派重构许多脚本和包的代码。有时更改很容易,我只是修改现有的函数。但有时我需要重写整个函数。坏消息是我重写的函数调用了其他函数。因此,如果我在新模块中移动重构代码,我还需要复制所有补充函数。但是,如果我不将重构代码移动到我的特殊模块,一个微小的语法错误可能会使整个站点崩溃:-( 是的,我知道我们应该使用版本控制等等。但我们不这样做,这是我不能改变的事实。怎么办 所以我需要在测试模块中保留一些代码(以避免语法错误导致整个站点崩溃)。从其他模块到测试(对于我的新

我们有一个基于Perl的大型网站

我被指派重构许多脚本和包的代码。有时更改很容易,我只是修改现有的函数。但有时我需要重写整个函数。坏消息是我重写的函数调用了其他函数。因此,如果我在新模块中移动重构代码,我还需要复制所有补充函数。但是,如果我不将重构代码移动到我的特殊模块,一个微小的语法错误可能会使整个站点崩溃:-(

是的,我知道我们应该使用版本控制等等。但我们不这样做,这是我不能改变的事实。怎么办

所以我需要在测试模块中保留一些代码(以避免语法错误导致整个站点崩溃)。从其他模块到测试(对于我的新重构例程)以及从测试到其他模块(对于补充例程)进行循环引用可以吗

请注意,我们有一些
AutoRequire
模块,这是大多数脚本和模块所需要的。
AutoRequire
进行::X()调用以自动加载模块(如果尚未加载)


我的主要问题是,在此设置中是否可以使用相互模块依赖项。还有其他建议吗?

Require首先检查模块是否已加载,如果未加载,然后将其标记为已加载。因此,如果您有一个依赖项,即Foo需要Bar,Bar需要Foo,那么它将首先尝试在Fo中加载Fooo尝试加载Bar。但由于Bar需要Foo,并且Bar尚未最终加载,因此可能会出现问题

从@ysth输入后编辑:它不会失败,但可能只加载部分内容,这可能会在以后引起有趣的问题


因此,它可能只是工作,但以后也可能会出现问题(例如无法使用导出的函数等等)。

Perl允许相互依赖,但有时会导致不直观的行为。我举的一个例子是:

foo.pm

package foo;
use bar;
sub import { printf("%s loaded foo\n", scalar caller) }
1;
package bar;
use foo;
sub import { printf("%s loaded bar\n", scalar caller) }
1;
bar.pm

package foo;
use bar;
sub import { printf("%s loaded foo\n", scalar caller) }
1;
package bar;
use foo;
sub import { printf("%s loaded bar\n", scalar caller) }
1;
script.pl

#!/usr/bin/env perl
package main;
use foo;
输出:

foo loaded bar
main loaded foo
难道你不希望在输出中的某个地方看到
条形加载的foo

仔细考虑编译时和运行时等等,你会发现为什么那一行没有输出,这是正确的和有文档记录的行为,只是不一定非常直观

也就是说,对于在导入时不做任何事情的纯面向对象模块(例如,将任何东西导出到其调用者,或充当pragma,或如本例中的打印输出),通常应该是非常安全的


也就是说,对于纯面向对象的模块,通常没有理由预先使用
use
加载它们,相反,您可以使用
require
加载它们,或者在需要时加载它们。

即使您的公司不使用版本控制,您也可以在本地使用它来跟踪您所做的更改,以便它们易于恢复。Also,考虑为你的应用程序写一些,这样你就可以知道什么时候改变会引入回归或其他的东西。那么,为测试目的建立一个站点的另一个实例会很困难吗?对一个现场生产现场进行未经测试的更改仅仅是自找麻烦。e使用来自另一个的常量,或者一个使用原型。OO模块在这方面做得比较少,因此您不太可能遇到问题。不,它不会失败(您尝试过吗?)。但在运行另一个模块的顶级代码时,其中一个模块将仅部分加载,这可能会导致有趣的错误。请避免使用B.pm作为示例模块名称,因为存在该名称的核心模块。