我正在使用的外部Perl库有一个依赖项(DBD::mysql),我不会在我的应用程序(DBD:::SQLite)中使用它,所以我希望系统只是假装存在依赖项,即使它是"假的"。
我可以创建一个空的DBD::mysql.pm模块来编译吗?或者有更简单的方法吗?
所以我认为这里有一些问题。
当你说依赖性时,你的意思是外部模块只是尝试require
还是use
DBD::mysql
?如果是这种情况,那么您应该建议开发人员,他不应该明确地这样做,因为这违背了使用DBI
的目的。应该根据DSN动态选择数据库驱动程序。
假设作者只是因为认为这是一件有用或有意义的事情而use
修改了包名,那么是,你可以覆盖该包,有几种方法可以做到这一点。
正如您所建议的,您只需创建自己的模块DBD/mysql.pm
即可定义DBD::mysql
包。
如果你感兴趣的话,你还可以做一些其他的事情。您只需要让Perl相信模块已经加载,而不必在源代码树中到处都是伪造的目录和文件。我们可以通过直接操纵%INC
来做到这一点。
package main; # or whereever
BEGIN {
$INC{'DBD/mysql.pm'} = "nothing to see here";
}
只需添加这个散列密钥,我们就可以排除在文件系统中搜索有问题的模块。注意这是在BEGIN
块中。如果外部作者执行了use
,那么我们必须在评估use
语句之前填充此值。use
语句等价于封装在BEGIN
中的require
和import
。
现在让我们从一般意义上进一步推测外部作者试图调用包的方法。如果这些符号不存在,则会出现运行时错误。您可以利用Perl的AUTOLOAD
来拦截这样的调用并做正确的事情。正确的做法可以有很多不同,从简单地记录消息到更详细的内容。例如,您可以使用这个工具来检查作者通过监视所有调用引入的耦合的深度。
package DBD::mysql;
sub AUTOLOAD {
printf(
"I don't wanna '%s' called from '%s'n", $AUTOLOAD, caller(0)
);
}
package main; # or whereever
BEGIN {
$INC{'DBD/mysql.pm'} = "nothing to see here";
}
DBD::mysql::blah()
现在,让我们讨论一下这样的情况:违规的作者还创建了类的一些面向对象的实例,而他的代码没有正确地解释为您的存根代码。我们将存根构造函数,我们假设它是new
,只是用我们的包名称来祝福匿名散列。那样你就不会在实例上调用方法时出错。
package DBD::mysql;
sub AUTOLOAD {
printf(
"I don't wanna '%s' called from '%s'n", $AUTOLOAD, caller(0)
);
}
sub new {
bless({}, __PACKAGE__)
}
package main; # or whereever
BEGIN {
$INC{'DBD/mysql.pm'} = "nothing to see here";
}
my $thing = new DBD::mysql;
$thing->blah()