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는 Importer.pm, base.pm, mixin.pm 및 SUPER.pm의 가장 뛰어난 부분을 하나의 매직 파운데이션 클래스로 결합합니다. 이는 기존 Perl OO의 모든 문제점을 깨끗하고 간단하며 (아마도 언젠가는) 표준 방식으로 수정하려고 시도합니다.
Spiffy는 Python, Ruby, Java 및 Perl 6과 같은 다른 OO 언어에서 아이디어를 차용했습니다. 또한 자체적인 몇 가지 트릭을 추가합니다.
CPAN을 살펴보면 OO 관련 모듈이 엄청나게 많습니다. 새 프로젝트를 시작할 때 가장 적합한 모듈 세트를 선택한 다음 각 수업에서 해당 모듈을 사용해야 합니다. 반면에 Spiffy는 하나의 모듈에 필요한 모든 것을 갖추고 있으며 수업 중 하나에서 한 번만 사용하면 됩니다. Spiffy.pm을 프로젝트에서 가장 기본 클래스의 기본 클래스로 만들면 Spiffy는 자동으로 모든 하위 클래스에 모든 마법을 전달합니다. 결국에는 그것을 사용하고 있다는 사실조차 잊어버릴 수도 있습니다!
Spiffy와 다른 Perl 객체 지향 기본 클래스의 가장 눈에 띄는 차이점은 항목을 내보낼 수 있다는 것입니다. Spiffy의 하위 클래스를 생성하면 Spiffy가 내보내는 모든 항목과 추가로 내보내려는 항목이 자동으로 하위 클래스에서 내보내집니다. 그리고 누군가가 귀하의 하위 클래스의 하위 클래스를 생성하면 해당 모든 항목이 자동으로 내보내집니다. "상속된 내보내기"라고 생각하면 친숙한 Importer.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;
두 번째 버전은 혼합되는 클래스가 Spiffy의 하위 클래스인 경우에만 작동합니다. 첫 번째 버전은 Spiffy가 이미 로드되어 있는 한 모든 경우에 작동합니다.
혼합되는 방법을 제한하려면 역할을 사용하십시오. (힌트: 내보내기 목록처럼 작동합니다):
use MySpiffyBaseModule -mixin => qw(:basics x y !foo);
객체 지향 Perl에서는 거의 모든 서브루틴이 메소드입니다. 각 메소드는 첫 번째 인수로 전달된 객체를 가져옵니다. 이는 거의 모든 서브루틴이 다음 줄로 시작한다는 의미입니다.
my $self = shift;
Spiffy는 해당 행을 삽입할 수 있는 간단한 선택적 필터 메커니즘을 제공하므로 코드가 더 깔끔해집니다. 평균 메소드에 10줄의 코드가 있다고 생각한다면 이는 코드의 10%입니다! 이 옵션을 켜려면 -base
옵션 대신 - Base
옵션을 사용하거나 -selfless
옵션을 추가하면 됩니다. 소스 필터링 때문에 짜증이 난다면 이 기능을 사용하지 마세요. 나는 개인적으로 깨끗하고 유지 관리가 가능한 코드를 작성하는 데 중독성이 있다고 생각합니다.
Spiffy의 유용한 기능은 클래스의 속성을 선언하는 데 사용할 수 있는 field
와 const
두 가지 함수를 내보내고 이에 대한 접근자 메서드를 자동으로 생성한다는 것입니다. 두 함수의 유일한 차이점은 const
속성을 수정할 수 없다는 것입니다. 따라서 접근자는 훨씬 빠릅니다.
OO 프로그래밍의 흥미로운 측면 중 하나는 메서드가 부모 클래스에서 동일한 메서드를 호출하는 경우입니다. 이는 일반적으로 슈퍼 메소드 호출로 알려져 있습니다. 이를 수행하기 위한 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
라는 두 가지 특수 메서드를 사용하여 어떤 인수가 부울(싱글톤)이고 어떤 인수가 쌍인지 선언합니다. 구문 분석 인수는 부울과 쌍을 꺼내서 이를 익명 해시로 반환하고 그 뒤에 일치하지 않는 인수 목록을 반환합니다.
마지막으로 Spiffy는 몇 가지 디버깅 기능인 WWW
, XXX
, YYY
및 ZZZ
내보낼 수 있습니다. 각각은 해당 인수의 YAML 덤프를 생성합니다. WWW는 출력을 경고하고, XXX는 출력과 함께 죽고, YYY는 출력을 인쇄하고, ZZZ는 출력을 고백합니다. YAML이 요구 사항에 적합하지 않은 경우 -dumper
옵션을 사용하여 모든 덤프를 Data::Dumper 형식으로 전환할 수 있습니다.
그거 스파이피야!
Spiffy는 Perl에서 완전히 새로운 아이디어를 구현합니다. 객체 지향 클래스 역할을 하고 함수를 내보내는 모듈입니다. 그러나 이는 Importer.pm의 개념을 한 단계 더 발전시킨 것입니다. 이는 클래스의 전체 @ISA
경로를 탐색하고 각 모듈의 내보내기 사양을 따릅니다. Spiffy는 이를 수행하기 위해 내보내기 모듈을 호출하므로 태그 및 부정을 포함하여 내보내기가 가지고 있는 모든 멋진 인터페이스 기능을 사용할 수 있습니다.
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 마법을 추가한 후). Spiffy는 @EXPORT
와 유사한 @EXPORT_BASE
변수를 제공하지만 -base
사용하는 용도에만 해당됩니다.
Perl에서 OO 프로그래밍을 많이 했다면 아마도 다중 상속(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에서 더 느슨하게 사용됩니다. 이는 내보내기 모듈이 사용하는 가져오기 목록과 매우 유사하며 그룹(태그) 및 부정을 사용할 수 있습니다. 목록의 첫 번째 요소가 부정을 사용하는 경우 Spiffy는 믹스인 클래스가 수행할 수 있는 모든 메소드로 시작합니다.
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 pragma를 켜고 짜증나는 '1;'을 추가합니다. 모듈에 줄을 연결하십시오.
Spiffy는 이제 '-Base' 필터 메커니즘을 사용할 때 비공개 메소드를 지원합니다. my
키워드를 사용하여 하위 항목을 선언하고 앞에 '$'
를 붙여 호출하면 됩니다. 이와 같이:
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가지 함수를 모두 내보내려면 내보내기 태그를 사용하세요.
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
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');
구문 분석 인수
이 방법은 인수 목록을 가져와서 쌍으로 그룹화합니다. 값이 있을 수도 있고 없을 수도 있는 부울 인수를 허용합니다(기본값은 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
에는 '빨간색', '흰색', '검은색'이 포함됩니다.
부울_인수
부울로 인식되는 인수 목록을 반환합니다. 자신만의 목록을 정의하려면 이 메서드를 재정의하세요.
paired_arguments
쌍을 이루는 것으로 인식되는 인수 목록을 반환합니다. 자신만의 목록을 정의하려면 이 메서드를 재정의하세요.
Spiffy 모듈이나 그 하위 클래스를 use
때 인수 목록을 전달할 수 있습니다. 이러한 인수는 위에서 설명한 parse_arguments
메서드를 사용하여 구문 분석됩니다. 특수 인수 -base
현재 패키지를 사용 중인 Spiffy 모듈의 하위 클래스로 만드는 데 사용됩니다.
페어링되지 않은 매개변수는 일반 가져오기 목록처럼 작동합니다. 내보내기 모듈과 함께 사용되는 것과 같습니다.
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
클래스가 모듈인지 아닌지에 관계없이 작동하지만, -base
구문은 그런 식으로 작동할 수 없습니다. 왜냐하면 use
항상 모듈을 로드하려고 시도하기 때문입니다.
Spiffy가 base.pm과 작동하도록 하기 위해 더러운 트릭이 사용되었습니다. Spiffy는 base::import
자체 버전으로 바꿉니다. 기본 모듈이 Spiffy가 아닌 경우 Spiffy는 원래 base::import를 호출합니다. 기본 모듈이 Spiffy인 경우 Spiffy는 자체 작업을 수행합니다.
두 가지 주의 사항이 있습니다.
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. Ingy döt Net.
이 프로그램은 무료 소프트웨어입니다. Perl 자체와 동일한 조건으로 재배포하거나 수정할 수 있습니다.
http://www.perl.com/perl/misc/Artistic.html을 참조하세요.