Perl 面向对象编程 : Is it a good idea to outsource methods in your own modules

标签 perl oop

我正在考虑将模块的各个方法移动到单独的模块中,以获得更易于管理的文件。我为此写了一个小测试:

a.pl:

#!/usr/bin/perl

use 5.028;
use warnings;
use utf8;
use open ':std', ':encoding(UTF-8)';
use Readonly;
use English qw(-no_match_vars);
use Benchmark qw(:all);
use A;


our $VERSION = 1;

Readonly::Scalar my $COUNT => 10_000_000;

warn $A::VERSION;
warn $A::Login2::VERSION;
my $a = A->new;
warn $a;
$a->login(1);
$a->login2(1);

cmpthese($COUNT, {
  login  => sub{$a->login},
  login2 => sub{$a->login2}
});

下午:

package A;
use 5.028;
use warnings;
use utf8;
use open ':std', ':encoding(UTF-8)';
use Readonly;
use English qw(-no_match_vars);
use A::Login2 'login2';


our $VERSION = 1;

sub new {
  my ($class, $p) = @_;
  my $this = {};
  bless $this, $class;
  return $this;
}

sub login {
  my ($this, $dump) = @_;

  if ($dump) {
    warn "$this: login";
    $this->test;
  }

  return;
}

sub test {
  my ($this) = @_;
  warn "$this: test";
  return;
}

1;

A/Login2.pm:

package A::Login2;
use 5.028;
use warnings;
use utf8;
use open ':std', ':encoding(UTF-8)';
use Readonly;
use English qw(-no_match_vars);
use base 'Exporter';
our @EXPORT_OK = qw(login2);


our $VERSION = 1.1;

sub login2 {
  my ($this, $dump) = @_;

  if ($dump) {
    warn "$this: login2";
    $this->test;
  }

  return;
}

1;

./a.pl 的输出是:

1 at ./a.pl line 18.
1.1 at ./a.pl line 19.
A=HASH(0x5581d48f3470) at ./a.pl line 21.
A=HASH(0x5581d48f3470): login at A.pm line 25.
A=HASH(0x5581d48f3470): test at A.pm line 34.
A=HASH(0x5581d48f3470): login2 at A/Login2.pm line 18.
A=HASH(0x5581d48f3470): test at A.pm line 34.
            Rate  login login2
login  5847953/s     --    -6%
login2 6250000/s     7%     --

我本以为登录比登录2更快。

  1. 为什么login2比login更快?
  2. 将每个方法放在自己的模块中是一个好主意吗?
    1. 有更好的方法吗?

我期待您的评论。

最佳答案

这是一个关于设计的开放式问题,但我会提供一些具体的评论。

首先,为了便于管理和提高可读性而分割笨重的文件是一个值得称赞的想法,这通常是一个好主意。我们在编写的任何大型代码中使用库——因此,整个代码被分割在不同的单元中。

但这种划分是基于功能的,行为(功能)自然地分组到包中。根据大小进行分割可能会导致代码库变得尴尬;组合起来可能很重要,更新可能会变得棘手(有错误?)等等。这实际上会阻碍整体的可管理性。

如果一个模块感觉太大,很可能是捆绑在一起的功能太多,并且代码库应该位于多个不同模块中。没有简单的规则来评估这一点;设计库并不容易。思考一下拆分一组函数以便它们拥有自己的功能是否有意义可能会有所帮助 namespace

但是,发布的示例有另一个问题:它是一个类,但面向对象的机制与基本包导入混合在一起。这是很复杂的(一个对象如何/为什么传递给一个不是类的文件中定义的函数?),我不建议这样做。

设计良好的类是否会太大而无法很好地放入文件中?大概是我猜的吧,虽然我没见过这样的案例。通常,当一个代码库最终在 Perl 中的多个编译单元中崩溃时,这是因为功能性——拥有多个类更合适。

但是,如果不知何故,仅仅是大小问题最终成为问题,那么合理的方法可能是让多个文件各自为同一个,并清楚地记录下来。

A.pm

package A;

use warnings;
use strict;
use feature 'say';

# =======================================================
# NOTE: Class definition is given in multiple parts/files
# =======================================================

use A_part1;
use A_part2;

sub new { ... } 

# perhaps more methods in this file
1;

A_part1.pm

package A;

# warnings, strict, pragmas, etc

sub func1 { my ($self, @args) = @_; ... };

...    

1;

对于A_part2.pm等也类似。然后照常使用

use A;

my $obj = A->new( ... );

$obj->func1(...); 

请注意,这打破了有关文件名和包名称之间关系的规则(约定)(A_part1.pm vs package A;);首先,PerlCritic 会提示。但是,这里是故意这样做的,我不会担心这一点。

但我认为实际上很少需要这样做。我宁愿期望,如果一个库看起来太大,它可能承担了太多的任务,应该重新设计为多个类。


但是,如果确实有太多属于同一个库的函数,一旦文件被分解,请考虑使用 require 将这些文件放在一起.

Perl::Critic::Policy::Modules::RequireFilenameMatchesPackage

关于Perl 面向对象编程 : Is it a good idea to outsource methods in your own modules,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/68297780/

相关文章:

regex - Perl 正则表达式匹配表情符号

java - 类(class)成员的计算

python - 使用 View 委托(delegate)的方法连接 QMainWindow 中的操作 (PySide/Qt/PyQt)

Perl:按值降序对哈希值进行排序

javascript - 运行脚本后如何返回成功

Perl:使用在嵌套子目录中组织的自定义嵌套模块

perl - 如何用null替换字符

java - Java 类中方法的静态最终常量的位置

java - Android数据库最佳实践

Python - 存在一个在对象未实现函数时调用的函数?