�ޤ���DCONWAY�����Τ����դ��顣

Always use fully encapsulated objects.
���֥������ȤϾ�˥��ץ��벽�����Ѥ���

�����perl�ξQ�Ȥ�����ꡢOO�ξQ�Ǥ���Τ����ɡ����줬perl�μ����ȽŤʤ뤳�Ȥˤ�ꡢperl�ˤ����Ƥ�¾�θ�������ˡ���ˤꤿ���ʤ륤�󥻥�ƥ������礭���Τ��ݤ�ʤ���

���ץ��벽�Υ����Ȥ������ޤ���礭���Τ���

�ʲ��ϡ��ϥå��塢�ϥå����ե���󥹡������ƥϥå����ե���󥹤ˤ�륪�֥������Ȥ���ǽ��٥���ޡ���������Τ����ǽ餬����������� accessor �� mutator ����٤ŤĸƤ����硣(bench0.pl)�����������ϥå���פθ��ܡ��ϥå����ե���󥹤�����Ⱦ�ۤ��٤���

          Rate hobf href hash
hobf  346092/s   -- -70% -84%
href 1161878/s 236%   -- -47%
hash 2198826/s 535%  89%   --
          Rate hobf href hash
hobf  347181/s   -- -70% -84%
href 1159485/s 234%   -- -46%
hash 2134227/s 515%  84%   --

�����٤��ϲ���ͳ�褹��Τ�������?Perl���Τ�Τ�����ǽ?�᥽�å�õ���˼�ּ�äƤ���?

���¤ϡ��ճ�����Ǽ����������ΤǤ��롣accessor ���ؿ��Ǥ���Ȥ������¤��Τ�Τ�����ʤΤ����ʲ��ϥ��֥������Ȥ���Ȥˤɤ������������뤫��benchmark������Τ�����̵�������᥽�å�õ����ʤ����ƴؿ��ƤӽФ��˼�ǽ񤭴����Ƥ⡢9%������®�ˤʤ�ʤ��������С��إåɤΤۤȤ�ɤϡ����줬�ؿ��ƤӽФ��Ǥ���Ȥ������Ȥ��Τ�Τˤ����äƤ��롣

              Rate   method      sub method++    sub++   direct direct++
method    430719/s       --      -8%     -74%     -77%     -81%     -91%
sub       469747/s       9%       --     -72%     -75%     -79%     -90%
method++ 1678847/s     290%     257%       --     -12%     -25%     -64%
sub++    1901402/s     341%     305%      13%       --     -16%     -60%
direct   2253342/s     423%     380%      34%      19%       --     -52%
direct++ 4706723/s     993%     902%     180%     148%     109%       --

��ˡ = Best Practice �Ͻ��פ�����������ñ��� accessor �Ǥ�4�ܤ���5�ܤȤ���OO�ǤϤ����ˤ�⤤�����Ȥ��Ǥ��ʤ�����������

�����ǡ�JavaScript�򸫤Ƥߤ롣JavaScript�ˤ����ơ�obj.whatever�Ͼ��obj['whatever']�������ˤʤäƤ��롣�᥽�åɤȤ��ư����ˤ�obj.whatever()��ɬ��()���դ��ʤ���Фʤ�ʤ���

������Ф��ơ�Perl�ξ��ˤ����Ƥϵդ�obj->whatever�Ͼ��obj->whatever()�Ȳ�ᤵ�졢obj->{'whatever'}�Ȳ�ᤵ��뤳�ȤϤʤ���()������Ǥ���ΤϤ褤�Τ������դ�JavaScript�Τ��������ˡ�Ȥ���ǧ��Ƥ��ޤ��С����ץ��벽�������򤵤ۤ�»�ʤ鷺��OO�Ǥ�����Ǥ���ΤǤϤʤ���������Ū�ˤ�obj->whatever��obj->{'whatever'}���̣���뤳�Ȥˤ���obj->whatever()�ȤʤäƤ�����ˤϤ��ΤޤޤȤ����櫓�Ǥ��롣

�Ȥ����櫓�ǡ���äƤߤ����ʤ��ʤ���­���Ԥ���̤��Ф���

#!perl
use strict;
use warnings;
use Benchmark qw/timethese cmpthese/;
use Obj;

my $hobj = Obj->new( attr => 1 );

cmpthese(
    timethese(
        0,
        {
            explicit => sub {
                $hobj->{attr} == 1 or die;
            },
            no => sub {
                no accessor;
                $hobj->attr == 1 or die;
            }, # comment here
            use => sub {
                use accessor;
                $hobj->attr == 1 or die;
            },
        }
    )
);
              Rate      use       no explicit
use       954355/s       --     -79%     -80%
no       4617898/s     384%       --      -2%
explicit 4707064/s     393%       2%       --

�ǡ�accessor.pm����ȤϤ����ʤäƤ��롣

package accessor;
use strict;
use warnings;
use Filter::Simple;
our $DEBUG = 1;
FILTER_ONLY code => sub {
    my @lines = split /\n/, $_;
    for (@lines) {
        last if /use\s+accessor/;
        s{ ->                       # arrow operator
           ([A-Za-z_][0-9A-Za-z_]*) # method name
           (\(?)                    # explicitly invoked?
        }{
            $2 ?  "->$1$2" # leave it alone
               :  "->{$1}" # make it a simple hash deref
        }egx;
    }
    $_ = join "\n", @lines;
};
no warnings 'redefine';
(*import, *unimport) = (\&unimport, \&import);
1;

���ƤΤȤ���Source Filter������ʤ���no accessor;�Ȥ����Τ��ʤ����˿������no loan�Τ褦��˰���쵤̣�ʤΤ���������ʾ�����Ǹ��̤�˰����Ƥ��롣

use Foo;�������ϤȤˤ�����Foo.pm���$self->whatever�Ȥ�������accessor��Ȥ��ΤϺ�ˡ���̤�ۤ���overkill(��ˡ)�Ȥ������ȤʤΤ����������ºݡ֥��󥰥ơ����ܡפ���Ǥ⡢DCONWAY�������ȡ��⥸�塼�������Ǥ�accessor���Ѥ���$self->get_whatever�Ȥ���ΤǤϤʤ���$whatever_of{ident $self}�Ȥ��Ƥ��ơ�Inside-Out Object�ˤ�����ץ��ѥƥ���ľ�����Ƥ���ΤϤ��Τ���ʤΤǤϤʤ��������ʤߤ�my %whatever_of�ʤΤǡ��⥸�塼�볰����ϱ��ä���Ƥ��롣�ܤ�����Ʊ��򻲾ȤΤ��ȡ�

Dan the POO Monger

Source Codes

Obj.pm

package Obj;
use strict;
use warnings;
sub new { my $pkg = shift; bless {@_}, $pkg }
sub attr {
    my $self = shift;
    return $self->{attr} unless @_;
    $self->{attr} = shift;
    return $self;
}
1;

bench0.pl

#!perl
use strict;
use warnings;
use Benchmark qw/timethese cmpthese/;
use Obj;

my (%hash, $href, $hobj);

cmpthese(
    timethese(
        0,
        {
            hash => sub { %hash = ( attr => 0 ) },
            href => sub { $href = { attr => 0 } },
            hobf => sub { $hobj = Obj->new( attr => 0 ) },
        }
    )
);

cmpthese(
    timethese(
        0,
        {
            hash => sub { $hash{attr}   = $hash{attr} + 1 },
            href => sub { $href->{attr} = $href->{attr} + 1 },
            hobf => sub { $hobj->attr( $hobj->attr + 1 ) },
        }
    )
);

bench1.pl

#!perl
use strict;
use warnings;
use Benchmark qw/timethese cmpthese/;
use Obj;

my $hobj = Obj->new( attr => 0 );
my $hsub = $hobj->can('attr');

sub Obj::inc_attr { shift->{attr}++ }

cmpthese(
    timethese(
        0,
        {
            method     => sub { $hobj->attr( $hobj->attr + 1 ) },
            'method++' => sub { $hobj->inc_attr },
            sub        => sub { $hsub->( $hobj => $hsub->($hobj) + 1 ) },
            'sub++'    => sub { Obj::inc_attr($hobj) },
            'direct++' => sub { $hobj->{attr}++ },
            direct     => sub { $hobj->{attr} = $hobj->{attr} + 1 },
        }
    )
);