Spiffy - あなたのための Spiffy Perl インターフェイス フレームワーク
package Keen; use Spiffy -Base; field 'mirth'; const mood => ':-)'; sub happy { if ($self->mood eq ':-(') { $self->mirth(-1); print "Cheer up!"; } super; }
「Spiffy」は、Perl でオブジェクト指向 (OO) プログラミングを行うためのフレームワークおよび方法論です。 Spiffy は、Exporter.pm、base.pm、mixin.pm、SUPER.pm の最良の部分を 1 つの魔法の基礎クラスに結合します。これは、従来の Perl OO のすべての欠点を、クリーンで簡単な、そして (おそらくいつかは) 標準的な方法で修正しようとします。
Spiffy は、Python、Ruby、Java、Perl 6 などの他の OO 言語からアイデアを借用しています。また、独自のトリックもいくつか追加しています。
CPAN を見ると、OO 関連のモジュールが大量にあります。新しいプロジェクトを開始するときは、最も意味のあるモジュールのセットを選択し、それらのモジュールを各クラスで使用する必要があります。一方、Spiffy には、おそらく必要なものがすべて 1 つのモジュールに含まれており、クラスの 1 つで 1 回使用するだけで済みます。 Spiffy.pm をプロジェクトの最も基底クラスの基底クラスにすると、Spiffy はそのすべてのマジックをすべてのサブクラスに自動的に渡します。そのうち、使っていることさえ忘れてしまうかもしれません。
Spiffy と他の Perl オブジェクト指向基本クラスの最も顕著な違いは、Spiffy にはエクスポート機能があることです。 Spiffy のサブクラスを作成すると、エクスポートしたいものに加えて、Spiffy がエクスポートするすべてのものがサブクラスによって自動的にエクスポートされます。そして、誰かがあなたのサブクラスのサブクラスを作成すると、それらのものはすべて自動的にエクスポートされます。これを「継承されたエクスポート」と考えると、よく知られた Exporter.pm 仕様構文が使用されます。
Spiffy または Spiffy のサブクラスをクラスの基本クラスとして使用するには、 use
コマンドに-base
引数を指定します。
use MySpiffyBaseModule -base;
従来のuse base 'MySpiffyBaseModule';
構文もすべてまったく同じように機能します。唯一の注意点は、Spiffy.pm がすでにロードされている必要があることです。それは、Spiffy がすべての Spiffy マジックを実行するために、その場でbase.pm を再配線するためです。
Spiffy は、Perl6 のような役割を持つ Ruby のようなミックスインをサポートしています。 base
と同様に、次のいずれかの呼び出しを使用できます。
use mixin 'MySpiffyBaseModule'; use MySpiffyBaseModule -mixin;
2 番目のバージョンは、混合されているクラスが Spiffy のサブクラスである場合にのみ機能します。最初のバージョンは、Spiffy がすでにロードされている限り、どのような場合でも機能します。
混在するメソッドを制限するには、ロールを使用します。 (ヒント: これらはエクスポーター リストと同じように機能します):
use MySpiffyBaseModule -mixin => qw(:basics x y !foo);
オブジェクト指向 Perl では、ほぼすべてのサブルーチンがメソッドです。各メソッドは、最初の引数として渡されたオブジェクトを取得します。つまり、実質的にすべてのサブルーチンは次の行で始まることになります。
my $self = shift;
Spiffy は、その行を挿入するためのシンプルなオプションのフィルター メカニズムを提供し、よりクリーンなコードを実現します。平均的なメソッドのコード行が 10 行であると考えると、それはコードの 10% に相当します。このオプションをオンにするには、 -base
オプションの代わりに- Base
オプションを使用するか、 -selfless
オプションを追加します。ソース フィルタリングに気分が悪くなる場合は、この機能を使用しないでください。私は個人的に、非常にクリーンで保守しやすいコードを書くという探求に中毒性を感じています。
Spiffy の便利な機能は、クラスの属性を宣言するために使用できるfield
とconst
という 2 つの関数をエクスポートし、それらのアクセサー メソッドを自動的に生成することです。 2 つの関数の唯一の違いは、 const
属性は変更できないことです。したがって、アクセサーははるかに高速になります。
OO プログラミングの興味深い点の 1 つは、メソッドが親クラスから同じメソッドを呼び出す場合です。これは一般にスーパー メソッドの呼び出しとして知られています。これを行うための Perl の機能は非常に醜いです。
sub cleanup { my $self = shift; $self->scrub; $self->SUPER::cleanup(@_); }
Spiffy を使用すると、スーパー メソッドを非常に簡単に呼び出すことができます。 super
関数を使うだけです。引数は自動的に渡されるため、引数を渡す必要はありません。 Spiffy での同じ機能を次に示します。
sub cleanup { $self->scrub; super; }
Spiffy には、 parse_arguments
と呼ばれる引数を解析するための特別なメソッドがあり、それは独自の引数の解析にも使用されます。どの引数がブール (シングルトン) で、どの引数がペアであるかを宣言するには、 boolean_arguments
とpaired_arguments
という 2 つの特別なメソッドを使用します。引数を解析すると、ブール値とペアが抽出され、匿名ハッシュで返され、その後に一致しない引数のリストが続きます。
最後に、Spiffy はいくつかのデバッグ関数WWW
、 XXX
、 YYY
、 ZZZ
をエクスポートできます。それぞれの引数の YAML ダンプが生成されます。 WWW は出力を警告し、XXX は出力とともに終了し、YYY は出力を印刷し、ZZZ は出力を告白します。 YAML がニーズに合わない場合は、 -dumper
オプションを使用してすべてのダンプを Data::Dumper 形式に切り替えることができます。
それがスピーフィーです!
Spiffy は、まったく新しいアイデアを Perl で実装します。オブジェクト指向クラスとして機能し、関数もエクスポートするモジュール。しかし、これは Exporter.pm の概念をさらに一歩進めたものです。クラスの@ISA
パス全体をたどり、各モジュールのエクスポート仕様を尊重します。 Spiffy はこれを行うために Exporter モジュールを呼び出すため、タグや否定など、Exporter が持つすべての高度なインターフェイス機能を使用できます。
Spiffy は、ダッシュで始まらないすべての引数がエクスポート仕様を構成するとみなします。
package Vehicle; use Spiffy -base; our $SERIAL_NUMBER = 0; our @EXPORT = qw($SERIAL_NUMBER); our @EXPORT_BASE = qw(tire horn); package Bicycle; use Vehicle -base, '!field'; $self->inflate(tire);
この場合、 Bicycle->isa('Vehicle')
と、 Vehicle
とSpiffy
エクスポートするすべてのものは、 field
除いて、 Bicycle
に入ります。
エクスポートは、数百のクラスを含むシステムを設計し、すべてのクラスが一部の関数または定数にアクセスできるようにしたい場合に非常に役立ちます。
or variables. Just export them in your main base class and every subclass
必要な機能が得られます。
Spiffy は (Spiffy マジックを追加した後) ジョブを Exporter に委任するため、Exporter が行うことのほとんどすべてを行うことができます。 Spiffy は@EXPORT
に似た@EXPORT_BASE
変数を提供しますが、 -base
使用する用途にのみ使用できます。
Perl でオブジェクト指向プログラミングを多く行ったことがある場合は、おそらく多重継承 (MI) を使用したことがあるでしょう。MI を頻繁に行った場合は、おそらく奇妙な問題や頭痛に遭遇したことがあるでしょう。 Ruby などの一部の言語は、ミックスインと呼ばれる手法を使用して MI の問題を解決しようとします。基本的に、すべての Ruby クラスは単一継承 (SI) のみを使用し、必要に応じて他のモジュールの機能をミックスインします。
ミックスインは、単純化したレベルで、別のクラスのメソッドをサブクラスにインポートするものと考えることができます。しかし、実装の観点から見ると、それは最善の方法ではありません。 Spiffy は Ruby と同じことを行います。空の匿名クラスを作成し、すべてをそのクラスにインポートして、新しいクラスを SI ISA パスにチェーンします。言い換えれば、次のように言うとします。
package AAA; use BBB -base; use CCC -mixin; use DDD -mixin;
最終的には、次のようなクラスの単一の継承チェーンが作成されます。
AAA << AAA-DDD << AAA-CCC << BBB;
AAA-DDD
およびAAA-CCC
生成されたクラスの実際のパッケージ名です。このスタイルの良い点は、CCC を混ぜても AAA のメソッドを壊さず、DDD も AAA や CCC と競合しないことです。 AAA にもあったメソッドを CCC に混ぜた場合でも、 super
使用してそのメソッドにアクセスできます。
Spiffy が CCC で混合すると、アンダースコアで始まらない CCC 内のすべてのメソッドが取り込まれます。実際にはそれよりもさらに遠くまで進みます。 CCC がサブクラスの場合、CCC が継承を通じて実行can
すべてのメソッドを取り込みます。これは非常に強力です。おそらく強力すぎるかもしれません。
ミックスインするものを制限するために、Spiffy は Perl6 からロールの概念を借用しています。ただし、Spiffy ではロールという用語がより大まかに使用されます。これは Exporter モジュールが使用するインポート リストによく似ており、グループ (タグ) と否定を使用できます。リストの最初の要素で否定が使用されている場合、Spiffy は mixin クラスが実行できるすべてのメソッドから開始します。
use EEE -mixin => qw(:tools walk !run !:sharp_tools);
この例では、 walk
とrun
EEE が実行できるメソッドであり、 tools
とsharp_tools
はクラス EEE の役割です。クラス EEE はこれらの役割をどのように定義しますか?これは、さらに多くのメソッドのリストを返す_role_tools
および_role_sharp_tools
というメソッドを非常に簡単に定義します。 (おそらく他のロールも!) ここで優れているのは、ロールは単なるメソッドであるため、それらも継承できるということです。 Perl6を取り上げてください。
-base
の代わりに-Base
フラグを使用すると、次の行を記述する必要がなくなります。
my $self = shift;
このステートメントは、ソース フィルターを使用してクラス内のすべてのサブルーチンに追加されます。この魔法はシンプルかつ高速なので、Ruby や Python と同等のクリーンなコードを作成する際のパフォーマンスの低下はほとんどありません。
package Example; use Spiffy -Base; sub crazy { $self->nuts; } sub wacky { } sub new() { bless [], shift; }
は次とまったく同じです:
package Example; use Spiffy -base; use strict;use warnings; sub crazy {my $self = shift; $self->nuts; } sub wacky {my $self = shift; } sub new { bless [], shift; } ;1;
サブルーチンnew
の後に空の括弧があると、$self が追加されないことに注意してください。また、行番号が変更されないように、追加のコードが既存の行に追加されることにも注意してください。
-Base
、strict プラグマと warnings プラグマもオンにし、迷惑な '1;' を追加します。モジュールにラインを追加します。
Spiffy は、「-Base」フィルター メカニズムを使用する場合のプライベート メソッドをサポートするようになりました。 my
キーワードを使用して sub を宣言し、先頭に'$'
を付けて呼び出すだけです。このような:
package Keen; use SomethingSpiffy -Base; # normal public method sub swell { $self->$stinky; } # private lexical method. uncallable from outside this file. my sub stinky { ... }
XXX 関数は、ほぼどこにでも挿入でき、データをきれいな YAML でダンプしてくれるため、デバッグに非常に便利です。次のステートメントを考えてみましょう。
my @stuff = grep { /keen/ } $self->find($a, $b);
このステートメントに問題がある場合は、次のいずれかの方法でデバッグできます。
XXX my @stuff = grep { /keen/ } $self->find($a, $b); my @stuff = XXX grep { /keen/ } $self->find($a, $b); my @stuff = grep { /keen/ } XXX $self->find($a, $b); my @stuff = grep { /keen/ } $self->find(XXX $a, $b);
XXX は挿入と取り外しが簡単です。コードの不確実な領域を XXX でマークすることも伝統です。これにより、デバッグ ダンパーを取り出し忘れた場合に見つけやすくなります。
WWW と YYY は、引数をダンプしてから引数を返すため、優れています。こうすることで、多くの場所にそれらを挿入しても、以前と同じようにコードを実行できます。 YAML ダンプとフルスタック トレースの両方を使用して終了する必要がある場合は、ZZZ を使用します。
-base
オプションを使用すると、デバッグ関数がデフォルトでエクスポートされますが、これは以前に-XXX
オプションを使用したことがある場合に限られます。 4 つの関数すべてをエクスポートするには、export タグを使用します。
use SomeSpiffyModule ':XXX';
デバッグ関数で YAML の代わりに Data::Dumper を使用するように強制するには:
use SomeSpiffyModule -dumper;
このセクションでは、Spiffy がエクスポートする関数について説明します。 field
、 const
、 stub
、およびsuper
関数は、 -base
または-Base
オプションを使用した場合にのみエクスポートされます。
分野
クラスのフィールドのアクセサー メソッドを定義します。
package Example; use Spiffy -Base; field 'foo'; field bar => []; sub lalala { $self->foo(42); push @{$self->{bar}}, $self->foo; }
field
に渡される最初のパラメータは、定義されている属性の名前です。アクセサーにはオプションのデフォルト値を与えることができます。オブジェクトにフィールドの値が設定されていない場合、この値が返されます。
定数
const bar => 42;
const
関数は、不変である点を除けば <field> に似ています。また、オブジェクトにデータは保存されません。おそらく、常にconst
デフォルト値を与えたいと思うでしょう。そうしないと、生成されたメソッドが役に立たなくなります。
スタブ
stub 'cigar';
stub
関数は、適切なメッセージとともに終了するメソッドを生成します。スタブ メソッドが呼び出されないように、サブクラスはこれらのメソッドを実装する必要があるという考えです。
素晴らしい
この関数が引数なしで呼び出された場合、ISA ツリーの上位にある同じメソッドが呼び出され、すべて同じ引数が渡されます。引数を指定して呼び出された場合は、先頭に$self
を付けてそれらの引数を使用します。言い換えれば、期待どおりに機能します。
sub foo { super; # Same as $self->SUPER::foo(@_); super('hello'); # Same as $self->SUPER::foo('hello'); $self->bar(42); } sub new() { my $self = super; $self->init; return $self; }
super メソッドがない場合、 super
は単に何も行いません。最後に、 super
AUTOLOAD サブルーチンで正しい動作を行います。
このセクションでは、Spiffy のサブクラスが自動的に継承するすべてのメソッドをリストします。
ミックスイン
実行時にクラスをミックスインするメソッド。 use mixin ...
と同じ引数を取ります。ターゲット クラスを呼び出し元のミックスインにします。
$self->mixin('SomeClass'); $object->mixin('SomeOtherClass' => 'some_method');
parse_arguments
このメソッドは引数のリストを取得し、それらをペアにグループ化します。値を持つ場合も持たない場合もあるブール引数を許可します (デフォルトは 1)。このメソッドは、すべてのペアのハッシュ参照をハッシュ内のキーと値として返します。ペアにできない引数はリストとして返されます。以下に例を示します。
sub boolean_arguments { qw(-has_spots -is_yummy) } sub paired_arguments { qw(-name -size) } my ($pairs, @others) = $self->parse_arguments( 'red', 'white', -name => 'Ingy', -has_spots => -size => 'large', 'black', -is_yummy => 0, );
この呼び出しの後、 $pairs
以下が含まれます。
{ -name => 'Ingy', -has_spots => 1, -size => 'large', -is_yummy => 0, }
@others
には「赤」、「白」、「黒」が含まれます。
ブール値_引数
ブール値として認識される引数のリストを返します。独自のリストを定義するには、このメソッドをオーバーライドします。
ペアの引数
ペアとして認識される引数のリストを返します。独自のリストを定義するには、このメソッドをオーバーライドします。
Spiffy モジュールまたはそのサブクラスをuse
場合、引数のリストを渡すことができます。これらの引数は、上で説明したparse_arguments
メソッドを使用して解析されます。特別な引数-base
、現在のパッケージを、使用されている Spiffy モジュールのサブクラスにするために使用されます。
ペアになっていないパラメータはすべて、通常のインポート リストのように機能します。 Exporter モジュールで使用されるものと同様です。
Spiffy モジュールを基本クラスとして使用する適切な方法は、 use
ステートメントに-base
パラメーターを使用することです。これは、 use base
一般的なモジュールとは異なります。
package Something; use Spiffy::Module -base; use base 'NonSpiffy::Module';
今では、何が Spiffy で何がそうでないのかを把握するのは難しいかもしれません。したがって、Spiffy は実際にbase.pm で動作するように作られています。次のように言うことができます。
package Something; use base 'Spiffy::Module'; use base 'NonSpiffy::Module';
use base
、クラスが実際のモジュール (別個のファイル) ではなく、既にロードされているファイル内の単なるパッケージである場合にも非常に便利です。 base
クラスがモジュールであるかどうかに関係なく機能しますが、 use
常にモジュールをロードしようとするため、 -base
構文はそのように機能しません。
Spiffy を Base.pm で動作させるために、汚いトリックが行われました。 Spiffy はbase::import
独自のバージョンと交換します。基本モジュールが Spiffy ではない場合、Spiffy は元の Base::import を呼び出します。基本モジュールが Spiffy の場合、Spiffy は独自の処理を行います。
注意点が2つあります。
Spiffy を最初にロードする必要があります。
Spiffy がロードされておらず、Spiffy モジュールでuse base
が呼び出された場合、Spiffy は終了し、作成者にこのドキュメントを読むように指示する有用なメッセージが表示されます。これは、Spiffy が事前にインポート スワップを行う必要があるためです。
このエラーが発生した場合は、コードの前に次のようなステートメントを追加してください。
use Spiffy ();
混合禁止
base.pm
複数の引数を取ることができます。そして、これは、すべての基本クラスが Spiffy であるか、すべて非 Spiffy である限り、Spiffy で機能します。混ぜるとSpiffyは死んでしまいます。この場合は、個別のuse base
ステートメントを使用するだけです。
Spiffy は Perl で OO プログラミングを行うための素晴らしい方法ですが、まだ開発中です。新しいものが追加されたり、うまく機能しないものは削除される可能性があります。
Ingy döt Net <[email protected]>
著作権は 2004 ~ 2014 年です。インギー・ドット・ネット。
このプログラムはフリーソフトウェアです。 Perl 自体と同じ条件の下で再配布したり変更したりすることができます。
http://www.perl.com/perl/misc/Artistic.html を参照してください。