モジュールファイル作成で注意すること(package/use)


モジュールファイル作成で注意すること


Perlではモジュールファイルのファイル名とパッケージ名が一致していなくても、ルール違反ではないので正常に動作します。
これは、例えば'MyModule.pm'という名前のモジュールファイルで

package Group;

のようにモジュールファイル名とは違ったパッケージ名を定義することが可能ですが、このような方法を採ることは一般的にはありません。
その理由はプログラマが混乱し、エラーを生む原因になるためです。

仮に、前述のようにモジュールファイル'MyModule.pm'をロードする場合

use MyModule;

で行いますが、モジュールファイルのファイル名が'MyModule.pm'ではなく、'Group.pm'だった場合、上記のコードではロードすることができません。
モジュールファイルのロードはパッケージ名ではなくファイル名を指定するので、この場合は

use Group;

としなければなりません。

また、先述、モジュールファイル'MyModule.pm'のように、モジュールファイルの名前とパッケージ名が違うモジュールファイルに定義されている関数を呼び出す場合

use MyModule;                 # ← これは正しい
MyModule::function();         # ← パッケージ名が違うためエラー

のようにパッケージ名が違うためで呼び出すことができませんので、この場合は

use MyModule;                 # ← これは正しい
Group::function();            # ← これも正しい

とすることで呼び出すことができます。


モジュールファイルの作成は通常、モジュールファイル名とパッケージ名を同一に揃えるのが一般的で、先述のような方法はメンテナンスの観点からも非常に危険な方法ではあるのですが、実はメリットもあります。

関数の管理手法はさまざまあるので、合理的でないかもしれませんが、同一パッケージの関数を複数のモジュールファイルごとに分けて定義することを例に解説します。

ここでは、'Base.pm'と'Addon.pm'の2つのモジュールファイルがあり、'Base.pm'は基本となる関数、'Addon.pm'は拡張的に追加する関数が収録されるとします。
そしてこの2つのモジュールファイルは共に'MyModule'とします。

# Base.pm

Package Group;

sub func_a {
  ....
}

sub func_b {
  ....
}
# Addon.pm

Package Group;

sub func_c {
  ....
}

sub func_d {
  ....
}

これを

# main.pl

use Base;
use Addon;

としてロードすると、2つのモジュールファイルに定義された関数が全てパッケージ'Group'に属されるので、

Group::func_a();   # Base.pm
Group::func_b();   # Base.pm
Group::func_c();   # Addon.pm
Group::func_d();   # Addon.pm

のようにパッケージ'Group'の関数として呼び出すことができます。

ただしこの手法では、双方のファイルに同名の関数が定義されている場合(正しくはパッケージ内に同じ名前の関数が複数定義されている場合)、関数の重複定義エラー(Subroutine redefined)が発生する危険性があるので、注意する必要がありますが、実現することは可能です。

Task Runner