2 Location: YAPC::Asia::2008
3 Presenter: Yuval Kogman
12 * 実験やプロトタイプ (experimental)
14 * もう一つのアクセサビルダー (accessor builder)
15 * ソースフィルタ (source filter)
19 ✂------✂------✂------✂------✂------✂------✂------✂------✂------✂------
26 * Perlのための完全にモダンなオブジェクトフレームワーク
28 * A complete modern object framework for Perl
30 ✂------✂------✂------✂------✂------✂------✂------✂------✂------✂------
37 * Class::MOPのためのシンタックスシュガー (Syntactic sugar)
39 * CLOS (Common Lisp Object System)
44 * 安定していて、お仕事にもつかえます (Stable & Production ready)
47 ✂------✂------✂------✂------✂------✂------✂------✂------✂------✂------
70 my ($self, $name) = @_;
71 $self->{'name'} = $name if $name;
72 return $self->{'name'};
76 my ($self, $age) = @_;
77 $self->{'age'} = $age if $age;
78 return $self->{'age'};
84 ✂------✂------✂------✂------✂------✂------✂------✂------✂------✂------
88 A Simple Moose Example
89 ----------------------
95 has name => (is => 'rw');
96 has age => (is => 'rw');
101 ✂------✂------✂------✂------✂------✂------✂------✂------✂------✂------
104 ===========================
105 A Simple Moose Example (cont.)
106 ------------------------------
109 * キーワードをインポート (imports keywords)
110 * `use strict; use warnings;`
111 * `@ISA = qw(Moose::Object) unless @ISA`
113 ✂------✂------✂------✂------✂------✂------✂------✂------✂------✂------
116 ===========================
117 A Simple Moose Example (cont.)
118 ------------------------------
120 * `has` はアトリビュートを定義する (declares attibutes)
121 * アクセサを生成 (generates accessors)
122 * `is => 'rw'` → 読み書き両用アクセサ
123 * `is => 'ro'` → 読み込み専用アクセサ
126 * `new` は `Moose::Object` から継承する
131 今度はアトリビュートの機能を説明していくよ
132 Now we're going to discuss more features of the attributes
134 ✂------✂------✂------✂------✂------✂------✂------✂------✂------✂------
137 =========================
138 Variations on a Moose Example
139 -----------------------------
155 default => sub { [qw(Bob Alice Tim)] },
161 default と isa が追加されてます
164 ✂------✂------✂------✂------✂------✂------✂------✂------✂------✂------
167 =================================
168 Variations on a Moose Example (cont.)
169 -------------------------------------
172 * コードリファレンス (coderef)
173 * またはリファレンス以外 (数値, 文字列) (nonref)
174 * `new` にパラメータがわたされなかったときに使われる
176 * `lazy` は `default` を遅延させる
177 * 最初に `$object->staff` が使われたときに呼ばれる (generates)
178 * `new` の中ではなく (no param)
184 リファレンスでないと想定外の共有がむずかしくなる
185 non refs make accidental sharing hard
187 ✂------✂------✂------✂------✂------✂------✂------✂------✂------✂------
190 =================================
191 Variations on a Moose Example (cont.)
192 -------------------------------------
194 * `isa` は型を規定する (specifies type)
195 * `Moose::Util::TypeConstraints`
196 * `Any, Item, Bool, Undef, Defined, Value, Num, Int, Str, Ref, ScalarRef, ArrayRef, HashRef, CodeRef, RegexpRef, GlobRef, FileHandle, Object, and Role`
197 * 型は存在する必要はありません (don't need to exist)
199 has 'date' => (isa => 'DateTime'); # DWIM
204 isa, type constraints
206 ✂------✂------✂------✂------✂------✂------✂------✂------✂------✂------
213 * 型は階層構造をもっている (types have a hierarchy)
214 * `Item` ⊃ `Defined` ⊃ `Ref` ⊃ `Object`
219 => where { ref($_) };
223 => where { blessed($_) }
230 ✂------✂------✂------✂------✂------✂------✂------✂------✂------✂------
234 Some Type of Coercion
235 ---------------------
240 use Moose::Util::TypeConstraints;
243 class_type 'Manager';
247 => via { Manager->new( name => $_) };
257 ✂------✂------✂------✂------✂------✂------✂------✂------✂------✂------
261 Some Type of Coercion (cont.)
262 -----------------------------
265 # 型制約のキーワードをインポート(import type constraint keywords)
266 use Moose::Util::TypeConstraints;
269 # オブジェクトのサブタイプであるマネージャーを定義(define Manager, a subtype of Object)
270 class_type "Manager";
273 # 変換を定義する(define the conversion)
276 => via { Manager->new( name => $_) };
279 # アトリビュートごとに有効にする(enable it per attribute)
289 breakdown of the example
291 クラスの型はMooseのクラスすべてに自動的に用意されます
292 class types are automatically created for all Moose classes
294 ✂------✂------✂------✂------✂------✂------✂------✂------✂------✂------
298 Conventional Delegates
299 ----------------------
310 manager_name => 'name',
311 coworkers => 'staff',
316 * マネージャーは `Employee` のいくつかのメソッドを処理します
317 * manager `handles` certain methods for `Employee`
318 * `$emp->coworkers` == `$emp->manager->staff `
320 ✂------✂------✂------✂------✂------✂------✂------✂------✂------✂------
324 Conventional Delegates (cont.)
325 ------------------------------
330 handles => [qw(number extension)],
334 ✂------✂------✂------✂------✂------✂------✂------✂------✂------✂------
338 Conventional Delegates (cont.)
339 ------------------------------
344 handles => qr/$method_regex/,
348 * `Phone->meta->compute_all_applicable_methods`にフィルターをかける
349 * Filters `Phone->meta->compute_all_applicable_methods`
351 ✂------✂------✂------✂------✂------✂------✂------✂------✂------✂------
355 Conventional Delegates (cont.)
356 ------------------------------
361 handles => "Dialing", # a role
365 ✂------✂------✂------✂------✂------✂------✂------✂------✂------✂------
369 UnConventional Delegates
370 ------------------------
375 use MooseX::AttributeHelpers;
378 metaclass => 'Collection::Array',
379 isa => 'ArrayRef[Employees]',
382 push => 'add_employee',
383 pop => 'remove_employee',
384 count => 'number_of_employees',
385 empty => 'any_employees',
389 ✂------✂------✂------✂------✂------✂------✂------✂------✂------✂------
397 before 'employees' => sub { warn 'calling employees' };
399 after 'employees' => sub { warn 'finished calling employees' };
402 * 現在のメソッドが実行される前/された後に実行されます
404 * `@_`のコピーを得ます(Get a copy of `@_`)
405 * 返り値は無視されます(Return value is ignored)
407 ✂------✂------✂------✂------✂------✂------✂------✂------✂------✂------
410 ============================
411 Modified Methods (cont.)
412 ------------------------
415 around 'employees' => sub {
416 my ($next, $self, @args) = @_;
418 my @return = $self->$next(@args);
424 ✂------✂------✂------✂------✂------✂------✂------✂------✂------✂------
427 ============================
428 Modified Methods (cont.)
429 ------------------------
440 inner(); # call subclass here
446 ✂------✂------✂------✂------✂------✂------✂------✂------✂------✂------
449 ============================
450 Modified Methods (cont.)
451 ------------------------
454 package Employee::Chef;
457 extends qw(Employee);
459 augment do_work => sub {
463 $self->flip_burger(shift @burgers);
467 $chef->do_work; # punch in, flip burgers, punch out
469 ✂------✂------✂------✂------✂------✂------✂------✂------✂------✂------
473 Some Type of Digression
474 -----------------------
479 isa => 'ArrayRef[Employee]',
482 has shopping_carts => (
484 isa => 'ArrayRef[ArrayRef[ShinyBead]]'
490 型システムの機能についてちょっと説明していくよ
491 Going to go into features of the type system for a bit
496 ✂------✂------✂------✂------✂------✂------✂------✂------✂------✂------
499 ========================
500 Some Type of Digression (cont.)
501 -------------------------------
506 isa => 'English | Welsh | Scots | Gaelic',
511 isa => 'Employee | ArrayRef[Employee|Group]',
520 ✂------✂------✂------✂------✂------✂------✂------✂------✂------✂------
523 ========================
524 Some Type of Digression (cont.)
525 -------------------------------
530 use Moose::Util::TypeConstraints;
531 use Test::Deep qw(eq_deeply ...);
533 type 'SomethingTricky'
535 eq_deeply( $_, ... );
540 isa => 'SomethingTricky',
547 Test::Deep custom validator
549 CPANからどんなバリデータでも持ってこられる
550 Can use any validation from the CPAN
552 ✂------✂------✂------✂------✂------✂------✂------✂------✂------✂------
555 ============================
556 Some Parametrized Type of Coercion
557 ----------------------------------
560 use Moose::Util::TypeConstraints;
561 subtype 'ArrayRef[Employee]' => as 'ArrayRef';
563 coerce 'ArrayRef[Employee]'
564 => from 'ArrayRef[Str]'
565 => via { [ map { Employee->new( name => $_ ) } @$_ ] };
569 isa => 'ArrayRef[Employee]',
571 default => sub { [qw(Bob Alice Tim)] },
578 ArrayRef[Str] から ArrayRef[Employee] に強制変換
579 coerce parametrized ArrayRef[Employee] from ArrayRef[Str]
581 強制変換は 'default' の返り値にも適用されます
582 coercions can be applied to 'default' return values
584 ✂------✂------✂------✂------✂------✂------✂------✂------✂------✂------
591 * Role は…(A role is like a)
594 * …それでいて安全でパワフル(safe, powerful)
595 * Role は小さくて再利用可能な動作向け(A role is for small reusable behaviors)
596 * 多重継承よりよい(better than using a multiple inheritence)
598 ✂------✂------✂------✂------✂------✂------✂------✂------✂------✂------
602 Role of the Moose (cont.)
603 -------------------------
605 * CPAN にある Role たち(Roles on the CPAN):
606 * `MooseX::Storage` - 柔軟なシリアライズ(Flexible serialization)
607 * `MooseX::LogDispatch` - `$self->logger->info("something happenned")`
608 * `MooseX::Getopt` - コマンドライン引数の処理(`@ARGV` aware constructor)
609 * `MooseX::Param` - `CGI.pm` の `param()` メソッドみたいなの(`param` method like `CGI.pm`'s)
610 * `MooseX::Clone` - 柔軟な`clone`メソッド(Flexible `clone` method)
615 Some examples of small reusable behaviors
618 Param is good for interacting with e.g. CGI::Expand or similar modules
620 ✂------✂------✂------✂------✂------✂------✂------✂------✂------✂------
624 Role of the Moose (cont.)
625 -------------------------
631 extends qw(Employee);
633 with qw(Salaried::Hourly);
638 extends qw(Employee);
640 with qw(Salaried::Monthly);
644 * `with` はクラスに Role を追加します
645 * `with` adds roles into your class
646 * `Salaried::Hourly`が`Minion`に追加される
647 * `Salaried::Hourly` was added to `Minion`
649 ✂------✂------✂------✂------✂------✂------✂------✂------✂------✂------
653 Role of the Moose (cont.)
654 -------------------------
660 requires qw('paycheck_amount');
666 ✂------✂------✂------✂------✂------✂------✂------✂------✂------✂------
670 Role of the Moose (cont.)
671 -------------------------
674 package Salaried::Hourly;
685 has logged_hours => (
691 sub paycheck_amount {
694 $self->logged_hours * $self->hourly_rate;
700 * More than an interface
702 ✂------✂------✂------✂------✂------✂------✂------✂------✂------✂------
706 Role of the Moose (cont.)
707 -------------------------
709 * Javaのインターフェースよりイイネ!
710 * More than Java Interfaces
711 * インターフェースは挙動の'規定'を提供する
712 * Interfaces are behavior "contracts"
713 * Role は挙動の'実装'も提供できる
714 * Roles can also have code
717 Roleはアトリビュートとメソッドを持てる
718 roles can have attributes and methods
719 Roleはインターフェースだけでなく動作を提供するもの
720 roles provide behavior, not just interface
722 ✂------✂------✂------✂------✂------✂------✂------✂------✂------✂------
726 Role of the Moose (cont.)
727 -------------------------
729 * Roleの組み込み(Role Composition)
730 * 継承ではない(Not inheritence)
734 ✂------✂------✂------✂------✂------✂------✂------✂------✂------✂------
738 Role of the Moose (cont.)
739 -------------------------
741 * Roleの組み込み(Role Composition)
742 * あいまいさが少ない(Less ambiguity)
743 * コンパイル時エラー(Compile time errors)
744 * …修正する方法もある(And ways to fix them)
747 喧嘩両成敗というのは優先順位がないということ。ふたつのRoleが同じものを定義しようとした場合はコンパイル時にエラーになる(直さないといけない)
748 symmetric composition means no precedence - if two roles try to define the same thing you get a compile time error that needs to be resolved
749 多重継承の場合はだまって最初のクラスを使うもんだと想定してしまう
750 multiple inheritence silently assumes you want the first class
752 Roleは多重継承と違ってコンパイル時にエラーを吐く
753 roles cause errors at compile time, unlike multiple inheritence
755 Roleは簡単にエラーを修正する方法も用意している
756 roles also provide easy ways to fix the errors
758 ✂------✂------✂------✂------✂------✂------✂------✂------✂------✂------
762 Role of the Moose (cont.)
763 -------------------------
791 ✂------✂------✂------✂------✂------✂------✂------✂------✂------✂------
795 Role of the Moose (cont.)
796 -------------------------
810 bark => "bark_sound",
829 Composition parameters
831 Easier conflict resolution
832 よりきめ細かいコントロールができるようになる
833 Finer grained control
835 ✂------✂------✂------✂------✂------✂------✂------✂------✂------✂------
839 MOPs Mean Cleanliness
840 ---------------------
842 * Moose は Class::MOP でつくられてる
843 * Moose is based on `Class::MOP`
844 * Perl5のためのメタオブジェクトプロトコル(Metaobject Protocol for Perl 5)
845 * すべてにオブジェクトがつくられる("makes an object for everything")
848 my $class = $obj->meta; # $objのメタクラス($obj's metaclass)
849 my $meta = MyApp->meta; # MyAppのメタクラス(MyApp's metaclass)
850 my $emo = $obj->meta->meta # メタメタ(even more meta)!
852 warn $obj->meta->name;
855 ✂------✂------✂------✂------✂------✂------✂------✂------✂------✂------
859 Looking in From the Inside
860 --------------------------
863 my $metaclass = $self->meta;
865 $metaclass->superclasses;
867 $metaclass->linearized_isa; # すべての先祖クラスを得ます(returns all ancestors)
869 $metaclass->has_method("foo");
871 $metaclass->compute_all_applicable_methods; # すべてのメソッド(継承されたものもふくめて)(returns all methods (inherited too))
873 $metaclass->has_attribute("bar");
881 ✂------✂------✂------✂------✂------✂------✂------✂------✂------✂------
884 ========================
885 Looking in From the Inside (cont.)
886 ----------------------------------
889 Moose::Meta::Class->create( Bar =>
891 superclasses => [ 'Foo' ],
893 Moose::Meta::Attribute->new( bar => ... ),
894 Moose::Meta::Attribute->new( baz => ... ),
897 calculate_bar => sub { ... },
898 construct_baz => sub { ... }
906 Classes can be created programmatically
909 Anonymous classes also possible
910 ✂------✂------✂------✂------✂------✂------✂------✂------✂------✂------
913 ========================
914 Looking in From the Inside (cont.)
915 ----------------------------------
918 has foo => ( is => "rw" );
920 __PACKAGE__->meta->add_attribute( foo => is => "rw" );
923 * Mooseは単なるシュガー(Moose is just sugar)
924 * 大変な部分はMOPがしてくれる(The MOP does the hard work)
926 ✂------✂------✂------✂------✂------✂------✂------✂------✂------✂------
933 * メタクラスはクラスの挙動をコントロールする
934 * Metaclassses control class behavior
938 metaclass => 'Collection::Array',
944 * custom attribute metaclasses
945 * アトリビュートがどういう風に動くかを変える
946 * change how attributes work
948 * Many customizable parts
949 * `Moose::Meta::Class`, `Moose::Meta::Attribute, ``Moose::Meta::Method`, `Moose::Meta::Method::Accessor` `Moose::Meta::Instance`, `Moose::Meta::Role`, `Moose::Meta::TypeConstraint`, …,
951 ✂------✂------✂------✂------✂------✂------✂------✂------✂------✂------
955 Working in the Meta Frame
956 -------------------------
958 * 仕事であったおもろい話(An interesting `$work` story)
959 * flashを使ったサイト用のCMS(CMS for a flash website)
960 * コンテンツはXML(Content is in XML)
962 ✂------✂------✂------✂------✂------✂------✂------✂------✂------✂------
965 ==========================
966 Working in the Meta Frame (cont.)
967 ---------------------------------
973 ✂------✂------✂------✂------✂------✂------✂------✂------✂------✂------
976 ==========================
977 Working in the Meta Frame (cont.)
978 ---------------------------------
980 * Step 2.1. XMLスキーマ(schemas) → クラス(classes)
981 * 自動変換(Automatic conversion)
982 * MOPのおかげで楽勝(MOP makes it easy)
983 * 実行時には高レベルオブジェクト(High level objects in runtime)
985 * クライアントのスキーマ(With client's schemas)
989 ✂------✂------✂------✂------✂------✂------✂------✂------✂------✂------
992 ==========================
993 Working in the Meta Frame (cont.)
994 ---------------------------------
996 * Step 2.2. メタ記述(Meta descriptions)
997 * メタクラスを拡張(Extend the metaclasses)
998 * 追加の情報を埋め込む(Embed additional information)
999 * フィールド型(field types)
1000 * アクセスコントロール(access control)
1002 ✂------✂------✂------✂------✂------✂------✂------✂------✂------✂------
1005 ==========================
1006 Working in the Meta Frame (cont.)
1007 ---------------------------------
1009 * Step 2.3 イントロスペクションかわゆす(Introspection goodness)
1010 * 汎用Webフロントエンド(Generic web frontend)
1011 * オブジェクトイントロスペクションベース(Object introspection based)
1013 * 編集用のウィジェット(Editing widgets)
1014 * クリーンで拡張性も高い(Clean, extensible)
1016 ✂------✂------✂------✂------✂------✂------✂------✂------✂------✂------
1024 * `MooseX::Compile` がアルでよ(`MooseX::Compile` is in the works)
1025 * いくつかの機能が遅い(Some features are slow)
1026 * でも、あなたがつかったぶんだけだから(but you only pay for what you use)
1027 * hashref じゃないクラスの拡張はトリッキー(Extending non-Hash based classes is tricky).
1028 * でも可能(but possible): `MooseX::GlobRef::Object`
1030 ✂------✂------✂------✂------✂------✂------✂------✂------✂------✂------
1037 * 退屈なことを減らせる(Less tedious)
1038 * 決まり文句を書かなくていい(ditch that boilerplate):
1039 * アトリビュートのストレージ/アクセサ(attribute storage/access)
1040 * コンストラクタ(construction)
1041 * デストラクタ(destruction)
1042 * 引数検査(verification)
1044 * 繰り返しを減らせる(less repetition)
1045 * typo を減らせる(fewer typos)
1047 ✂------✂------✂------✂------✂------✂------✂------✂------✂------✂------
1050 ========================
1051 Benefits of Moose (cont.)
1052 -------------------------
1055 * declarative == 情報がおおく、タイプ数がすくない(more info, less typing)
1057 * コードがすくなきゃバグもすくなかろう(less code means fewer bugs)
1059 ✂------✂------✂------✂------✂------✂------✂------✂------✂------✂------
1062 ========================
1063 Benefits of Moose (cont.)
1064 -------------------------
1066 * テストがすくなくていい(Less testing)
1068 * Moose is well tested
1069 * アクセサやら挙動やらをチェックせんでもよろし
1070 * no need to check accessor behavior, etc
1071 * あなたのコードの目的にフォーカスできます!
1072 * focus on your code's purpose
1073 * きちんと「まとめて」おかなくてもいいよ
1074 * not that it is "assembled" correctly
1075 * http://c2.com/cgi/wiki?IntentionNotAlgorithm
1077 ✂------✂------✂------✂------✂------✂------✂------✂------✂------✂------
1080 ========================
1081 Benefits of Moose (cont.)
1082 -------------------------
1084 * 読みやすい(More readable)
1085 * 宣言的なスタイルだからそのまま文書になっている
1086 * declarative style is self documenting
1087 * やりたいことを書け。関係ないOOのしかけとかはあまり書かなくてもいい
1088 * Code your intentions, not and OO mechanics less
1090 ✂------✂------✂------✂------✂------✂------✂------✂------✂------✂------
1093 ========================
1094 Benefits of Moose (cont.)
1095 -------------------------
1097 * Meta object protocol
1098 * Perl の OO を綺麗にあつかえます
1099 * Cleans up all levels of Perl's OO
1101 * Provides introspection
1103 * Enables powerful abstractions
1105 ✂------✂------✂------✂------✂------✂------✂------✂------✂------✂------
1108 ========================
1109 Benefits of Moose (cont.)
1110 -------------------------
1113 * It's the new black
1114 * イカした連中はみんな#mooseにきている
1115 * All the cool kids hang out on #moose
1117 * Smart sounding buzzwords
1118 * 2007年にはRubyがそうだったね
1121 ✂------✂------✂------✂------✂------✂------✂------✂------✂------✂------
1128 ✂------✂------✂------✂------✂------✂------✂------✂------✂------✂------
1134 package Units::Bytes;
1139 sub kilobytes { $_[0] * 1024 }
1140 sub megabytes { $_[0] * 1024->kilobytes }
1141 sub gigabytes { $_[0] * 1024->megabytes }
1142 sub terabytes { $_[0] * 1024->gigabytes }
1144 Moose::Autobox->mixin_additional_role(SCALAR => 'Units::Bytes');
1147 ✂------✂------✂------✂------✂------✂------✂------✂------✂------✂------
1158 is(5->bytes, 5, '... got 5 bytes');
1159 is(5->kilobytes, 5120, '... got 5 kilobytes');
1160 is(2->megabytes, 2097152, '... got 2 megabytes');
1161 is(1->gigabytes, 1073741824, '... got 1 gigabyte');
1162 is(2->terabytes, 2199023255552, '... got 2 terabyte');
1165 ✂------✂------✂------✂------✂------✂------✂------✂------✂------✂------
1170 * Moose なワンライナーには `oose.pm` があるでよ
1171 * Moose One Liners with `oose.pm`
1174 perl -Moose -e'has foo => (is=>q[rw]); Class->new(foo=>1)'
1178 * Useful for testing if something works
1179 * IRC での会話には欠かせませんな!
1182 ✂------✂------✂------✂------✂------✂------✂------✂------✂------✂------
1198 $self->yield('increment');
1201 event increment => sub {
1203 warn "Count is now " . $self->count;
1204 $self->count( $self->count + 1 );
1205 $self->yield('increment') unless $self->count > 3;
1208 Counter->new( count => 0 );
1212 * POE のコンポーネントを簡単にかけます
1213 * POE components made easy
1214 * それぞれのオブジェクトが POE::Session をもってます
1215 * Every object has a POE::Session
1216 * `event` がオブジェクトのステートを宣言します
1217 * `event` declares object states
1219 ✂------✂------✂------✂------✂------✂------✂------✂------✂------✂------
1224 * Slides written by:
1229 * Slides deleted by:
1232 * Slides translated by: