Commit | Line | Data |
720accfe |
1 | Title: Moose |
2 | Location: YAPC::Asia::2008 |
3 | Presenter: Yuval Kogman |
4 | Date: 2008 |
5 | Theme: moose |
6 | |
7 | Moose はなにではないか |
8 | ====================== |
9 | Moose Is Not |
10 | ------------ |
11 | |
12 | * 実験やプロトタイプ (experimental) |
13 | * おもちゃ (toy) |
14 | * もう一つのアクセサビルダー (accessor builder) |
15 | * ソースフィルタ (source filter) |
16 | * 黒魔術 (black magic) |
17 | * Perl 6 in Perl 5 |
18 | |
19 | ✂------✂------✂------✂------✂------✂------✂------✂------✂------✂------ |
20 | |
21 | Mooseとはなにか |
22 | =============== |
23 | Moose Is |
24 | -------- |
25 | |
26 | * Perlのための完全にモダンなオブジェクトフレームワーク |
27 | |
28 | * A complete modern object framework for Perl |
29 | |
30 | ✂------✂------✂------✂------✂------✂------✂------✂------✂------✂------ |
31 | |
32 | Mooseとはなにか |
33 | =============== |
34 | Moose Is |
35 | -------- |
36 | |
37 | * Class::MOPのためのシンタックスシュガー (Syntactic sugar) |
38 | * 祖先たち (ancestry) |
39 | * CLOS (Common Lisp Object System) |
40 | * Smalltalk |
41 | * Alces latifrons |
42 | * Perl 6 |
43 | * … |
44 | * 安定していて、お仕事にもつかえます (Stable & Production ready) |
45 | |
46 | |
47 | ✂------✂------✂------✂------✂------✂------✂------✂------✂------✂------ |
48 | |
49 | シンプルな例 |
50 | ============ |
51 | A Simple Example |
52 | ---------------- |
53 | |
54 | <pre><code> |
55 | package Person; |
56 | |
57 | use strict; |
58 | use warnings; |
59 | |
60 | sub new { |
61 | my ($class) = @_; |
62 | |
63 | return bless { |
64 | name => '', |
65 | age => undef, |
66 | }, $class; |
67 | } |
68 | |
69 | sub name { |
70 | my ($self, $name) = @_; |
71 | $self->{'name'} = $name if $name; |
72 | return $self->{'name'}; |
73 | } |
74 | |
75 | sub age { |
76 | my ($self, $age) = @_; |
77 | $self->{'age'} = $age if $age; |
78 | return $self->{'age'}; |
79 | } |
80 | |
81 | 1; |
82 | </code></pre> |
83 | |
84 | ✂------✂------✂------✂------✂------✂------✂------✂------✂------✂------ |
85 | |
86 | シンプルなMooseの例 |
87 | =================== |
88 | A Simple Moose Example |
89 | ---------------------- |
90 | |
91 | <pre><code> |
92 | package Person; |
93 | use Moose; |
94 | |
95 | has name => (is => 'rw'); |
96 | has age => (is => 'rw'); |
97 | |
98 | 1; |
99 | </code></pre> |
100 | |
101 | ✂------✂------✂------✂------✂------✂------✂------✂------✂------✂------ |
102 | |
103 | シンプルなMooseの例(つづき) |
104 | =========================== |
105 | A Simple Moose Example (cont.) |
106 | ------------------------------ |
107 | |
108 | * `use Moose;` |
109 | * キーワードをインポート (imports keywords) |
110 | * `use strict; use warnings;` |
111 | * `@ISA = qw(Moose::Object) unless @ISA` |
112 | |
113 | ✂------✂------✂------✂------✂------✂------✂------✂------✂------✂------ |
114 | |
115 | シンプルなMooseの例(つづき) |
116 | =========================== |
117 | A Simple Moose Example (cont.) |
118 | ------------------------------ |
119 | |
120 | * `has` はアトリビュートを定義する (declares attibutes) |
121 | * アクセサを生成 (generates accessors) |
122 | * `is => 'rw'` → 読み書き両用アクセサ |
123 | * `is => 'ro'` → 読み込み専用アクセサ |
124 | * `writer`, `reader` |
125 | |
126 | * `new` は `Moose::Object` から継承する |
127 | |
128 | |
129 | ########## |
130 | |
131 | 今度はアトリビュートの機能を説明していくよ |
132 | Now we're going to discuss more features of the attributes |
133 | |
134 | ✂------✂------✂------✂------✂------✂------✂------✂------✂------✂------ |
135 | |
136 | Mooseの例のバリエーション |
137 | ========================= |
138 | Variations on a Moose Example |
139 | ----------------------------- |
140 | |
141 | <pre><code> |
142 | package Person; |
143 | use Moose; |
144 | |
145 | has name => ( |
146 | is => 'rw', |
147 | isa => 'Str' |
148 | default => 'Bob' |
149 | ); |
150 | |
151 | has staff => ( |
152 | is => 'ro', |
153 | isa => 'ArrayRef', |
154 | lazy => 1, |
155 | default => sub { [qw(Bob Alice Tim)] }, |
156 | ); |
157 | </code></pre> |
158 | |
159 | ########## |
160 | |
161 | default と isa が追加されてます |
162 | Adds default, isa |
163 | |
164 | ✂------✂------✂------✂------✂------✂------✂------✂------✂------✂------ |
165 | |
166 | Mooseの例のバリエーション(つづき) |
167 | ================================= |
168 | Variations on a Moose Example (cont.) |
169 | ------------------------------------- |
170 | |
171 | * `default` は |
172 | * コードリファレンス (coderef) |
173 | * またはリファレンス以外 (数値, 文字列) (nonref) |
174 | * `new` にパラメータがわたされなかったときに使われる |
175 | |
176 | * `lazy` は `default` を遅延させる |
177 | * 最初に `$object->staff` が使われたときに呼ばれる (generates) |
178 | * `new` の中ではなく (no param) |
179 | |
180 | ########## |
181 | デフォルトの話 |
182 | discusses default |
183 | |
184 | リファレンスでないと想定外の共有がむずかしくなる |
185 | non refs make accidental sharing hard |
186 | |
187 | ✂------✂------✂------✂------✂------✂------✂------✂------✂------✂------ |
188 | |
189 | Mooseの例のバリエーション(つづき) |
190 | ================================= |
191 | Variations on a Moose Example (cont.) |
192 | ------------------------------------- |
193 | |
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) |
198 | <pre><code> |
199 | has 'date' => (isa => 'DateTime'); # DWIM |
200 | </code></pre> |
201 | ########## |
202 | |
203 | isa, 型の制約 |
204 | isa, type constraints |
205 | |
206 | ✂------✂------✂------✂------✂------✂------✂------✂------✂------✂------ |
207 | |
208 | 型 |
209 | == |
210 | Typical Family |
211 | -------------- |
212 | |
213 | * 型は階層構造をもっている (types have a hierarchy) |
214 | * `Item` ⊃ `Defined` ⊃ `Ref` ⊃ `Object` |
215 | |
216 | <pre><code> |
217 | subtype 'Ref' |
218 | => as 'Defined' |
219 | => where { ref($_) }; |
220 | |
221 | subtype 'Object' |
222 | => as 'Ref' |
223 | => where { blessed($_) } |
224 | </code></pre> |
225 | ########## |
226 | |
227 | 型の階層構造 |
228 | type hierarchy |
229 | |
230 | ✂------✂------✂------✂------✂------✂------✂------✂------✂------✂------ |
231 | |
232 | 型の強制変換 |
233 | ============ |
234 | Some Type of Coercion |
235 | --------------------- |
236 | |
237 | <pre><code> |
238 | package Employee; |
239 | use Moose; |
240 | use Moose::Util::TypeConstraints; |
241 | extends qw(Person); |
242 | |
243 | class_type 'Manager'; |
244 | |
245 | coerce 'Manager' |
246 | => from 'Str' |
247 | => via { Manager->new( name => $_) }; |
248 | |
249 | has manager => ( |
250 | is => 'ro', |
251 | isa => 'Manager', |
252 | required => 1, |
253 | coerce => 1, |
254 | ); |
255 | </code></pre> |
256 | |
257 | ✂------✂------✂------✂------✂------✂------✂------✂------✂------✂------ |
258 | |
259 | 型の強制変換(つづき) |
260 | ==================== |
261 | Some Type of Coercion (cont.) |
262 | ----------------------------- |
263 | |
264 | <pre><code> |
265 | # 型制約のキーワードをインポート(import type constraint keywords) |
266 | use Moose::Util::TypeConstraints; |
267 | |
268 | |
269 | # オブジェクトのサブタイプであるマネージャーを定義(define Manager, a subtype of Object) |
270 | class_type "Manager"; |
271 | |
272 | |
273 | # 変換を定義する(define the conversion) |
274 | coerce 'Manager' |
275 | => from 'Str' |
276 | => via { Manager->new( name => $_) }; |
277 | |
278 | |
279 | # アトリビュートごとに有効にする(enable it per attribute) |
280 | has manager => ( |
281 | … |
282 | coerce => 1, |
283 | ); |
284 | </code></pre> |
285 | |
286 | ########## |
287 | |
288 | 例を細かく見ていくよ |
289 | breakdown of the example |
290 | |
291 | クラスの型はMooseのクラスすべてに自動的に用意されます |
292 | class types are automatically created for all Moose classes |
293 | |
294 | ✂------✂------✂------✂------✂------✂------✂------✂------✂------✂------ |
295 | |
296 | 伝統的な委譲 |
297 | ============ |
298 | Conventional Delegates |
299 | ---------------------- |
300 | |
301 | <pre><code> |
302 | package Employee; |
303 | use Moose; |
304 | extends qw(Person); |
305 | |
306 | has manager => ( |
307 | is => 'ro', |
308 | isa => 'Manager', |
309 | handles => { |
310 | manager_name => 'name', |
311 | coworkers => 'staff', |
312 | } |
313 | ); |
314 | </code></pre> |
315 | |
316 | * マネージャーは `Employee` のいくつかのメソッドを処理します |
317 | * manager `handles` certain methods for `Employee` |
318 | * `$emp->coworkers` == `$emp->manager->staff ` |
319 | |
320 | ✂------✂------✂------✂------✂------✂------✂------✂------✂------✂------ |
321 | |
322 | 伝統的な委譲(つづき) |
323 | ==================== |
324 | Conventional Delegates (cont.) |
325 | ------------------------------ |
326 | |
327 | <pre><code> |
328 | has phone => ( |
329 | ... |
330 | handles => [qw(number extension)], |
331 | ); |
332 | </code></pre> |
333 | |
334 | ✂------✂------✂------✂------✂------✂------✂------✂------✂------✂------ |
335 | |
336 | 伝統的な委譲(つづき) |
337 | ==================== |
338 | Conventional Delegates (cont.) |
339 | ------------------------------ |
340 | |
341 | <pre><code> |
342 | has phone => ( |
343 | isa => "Phone" |
344 | handles => qr/$method_regex/, |
345 | ); |
346 | </code></pre> |
347 | |
348 | * `Phone->meta->compute_all_applicable_methods`にフィルターをかける |
349 | * Filters `Phone->meta->compute_all_applicable_methods` |
350 | |
351 | ✂------✂------✂------✂------✂------✂------✂------✂------✂------✂------ |
352 | |
353 | 伝統的な委譲(つづき) |
354 | ==================== |
355 | Conventional Delegates (cont.) |
356 | ------------------------------ |
357 | |
358 | <pre><code> |
359 | has phone => ( |
360 | ... |
361 | handles => "Dialing", # a role |
362 | ); |
363 | </code></pre> |
364 | |
365 | ✂------✂------✂------✂------✂------✂------✂------✂------✂------✂------ |
366 | |
367 | 伝統的じゃない委譲 |
368 | ================ |
369 | UnConventional Delegates |
370 | ------------------------ |
371 | |
372 | <pre><code> |
373 | package Company; |
374 | use Moose; |
375 | use MooseX::AttributeHelpers; |
376 | |
377 | has employees => ( |
378 | metaclass => 'Collection::Array', |
379 | isa => 'ArrayRef[Employees]', |
380 | is => 'rw', |
381 | provides => { |
382 | push => 'add_employee', |
383 | pop => 'remove_employee', |
384 | count => 'number_of_employees', |
385 | empty => 'any_employees', |
386 | } |
387 | ); |
388 | </code></pre> |
389 | ✂------✂------✂------✂------✂------✂------✂------✂------✂------✂------ |
390 | |
391 | メソッド変更のセカイ |
392 | ==================== |
393 | Modified Methods |
394 | ---------------- |
395 | |
396 | <pre><code> |
397 | before 'employees' => sub { warn 'calling employees' }; |
398 | |
399 | after 'employees' => sub { warn 'finished calling employees' }; |
400 | </code></pre> |
401 | |
402 | * 現在のメソッドが実行される前/された後に実行されます |
403 | * Pre/Post hooks |
404 | * `@_`のコピーを得ます(Get a copy of `@_`) |
405 | * 返り値は無視されます(Return value is ignored) |
406 | |
407 | ✂------✂------✂------✂------✂------✂------✂------✂------✂------✂------ |
408 | |
409 | メソッド変更のセカイ(つづき) |
410 | ============================ |
411 | Modified Methods (cont.) |
412 | ------------------------ |
413 | |
414 | <pre><code> |
415 | around 'employees' => sub { |
416 | my ($next, $self, @args) = @_; |
417 | ... |
418 | my @return = $self->$next(@args); |
419 | ... |
420 | return @return; |
421 | }; |
422 | </code></pre> |
423 | |
424 | ✂------✂------✂------✂------✂------✂------✂------✂------✂------✂------ |
425 | |
426 | メソッド変更のセカイ(つづき) |
427 | ============================ |
428 | Modified Methods (cont.) |
429 | ------------------------ |
430 | |
431 | <pre><code> |
432 | package Employee; |
433 | use Moose; |
434 | |
435 | sub do_work { |
436 | my $self = shift; |
437 | |
438 | $self->punch_in; |
439 | |
440 | inner(); # call subclass here |
441 | |
442 | $self->punch_out; |
443 | } |
444 | </code></pre> |
445 | |
446 | ✂------✂------✂------✂------✂------✂------✂------✂------✂------✂------ |
447 | |
448 | メソッド変更のセカイ(つづき) |
449 | ============================ |
450 | Modified Methods (cont.) |
451 | ------------------------ |
452 | |
453 | <pre><code> |
454 | package Employee::Chef; |
455 | use Moose; |
456 | |
457 | extends qw(Employee); |
458 | |
459 | augment do_work => sub { |
460 | my $self = shift; |
461 | |
462 | while ( @burgers ) { |
463 | $self->flip_burger(shift @burgers); |
464 | } |
465 | } |
466 | |
467 | $chef->do_work; # punch in, flip burgers, punch out |
468 | </code></pre> |
469 | ✂------✂------✂------✂------✂------✂------✂------✂------✂------✂------ |
470 | |
471 | 型についての余談 |
472 | ================ |
473 | Some Type of Digression |
474 | ----------------------- |
475 | |
476 | <pre><code> |
477 | has employees => ( |
478 | is => 'rw', |
479 | isa => 'ArrayRef[Employee]', |
480 | ); |
481 | |
482 | has shopping_carts => ( |
483 | is => 'rw', |
484 | isa => 'ArrayRef[ArrayRef[ShinyBead]]' |
485 | ); |
486 | </code></pre> |
487 | |
488 | ########## |
489 | |
490 | 型システムの機能についてちょっと説明していくよ |
491 | Going to go into features of the type system for a bit |
492 | |
493 | パラメータ付きの型 |
494 | Parametrized types |
495 | |
496 | ✂------✂------✂------✂------✂------✂------✂------✂------✂------✂------ |
497 | |
498 | 型についての余談(つづき) |
499 | ======================== |
500 | Some Type of Digression (cont.) |
501 | ------------------------------- |
502 | |
503 | <pre><code> |
504 | has language => ( |
505 | is => 'rw', |
506 | isa => 'English | Welsh | Scots | Gaelic', |
507 | ); |
508 | |
509 | has member => ( |
510 | is => 'rw', |
511 | isa => 'Employee | ArrayRef[Employee|Group]', |
512 | ); |
513 | </code></pre> |
514 | |
515 | ########## |
516 | |
517 | 型の結合 |
518 | Union types |
519 | |
520 | ✂------✂------✂------✂------✂------✂------✂------✂------✂------✂------ |
521 | |
522 | 型についての余談(つづき) |
523 | ======================== |
524 | Some Type of Digression (cont.) |
525 | ------------------------------- |
526 | |
527 | <pre><code> |
528 | package Foo; |
529 | use Moose; |
530 | use Moose::Util::TypeConstraints; |
531 | use Test::Deep qw(eq_deeply ...); |
532 | |
533 | type 'SomethingTricky' |
534 | => where { |
535 | eq_deeply( $_, ... ); |
536 | }; |
537 | |
538 | has 'bar' => ( |
539 | is => 'rw', |
540 | isa => 'SomethingTricky', |
541 | ); |
542 | </code></pre> |
543 | |
544 | ########## |
545 | |
546 | Test::Deppのカスタムバリデータ |
547 | Test::Deep custom validator |
548 | |
549 | CPANからどんなバリデータでも持ってこられる |
550 | Can use any validation from the CPAN |
551 | |
552 | ✂------✂------✂------✂------✂------✂------✂------✂------✂------✂------ |
553 | |
554 | パラメータ付きの型の強制変換 |
555 | ============================ |
556 | Some Parametrized Type of Coercion |
557 | ---------------------------------- |
558 | |
559 | <pre><code> |
560 | use Moose::Util::TypeConstraints; |
561 | subtype 'ArrayRef[Employee]' => as 'ArrayRef'; |
562 | |
563 | coerce 'ArrayRef[Employee]' |
564 | => from 'ArrayRef[Str]' |
565 | => via { [ map { Employee->new( name => $_ ) } @$_ ] }; |
566 | |
567 | has staff => ( |
568 | is => 'ro', |
569 | isa => 'ArrayRef[Employee]', |
570 | lazy => 1, |
571 | default => sub { [qw(Bob Alice Tim)] }, |
572 | coerce => 1, |
573 | ); |
574 | </code></pre> |
575 | |
576 | ########## |
577 | |
578 | ArrayRef[Str] から ArrayRef[Employee] に強制変換 |
579 | coerce parametrized ArrayRef[Employee] from ArrayRef[Str] |
580 | |
581 | 強制変換は 'default' の返り値にも適用されます |
582 | coercions can be applied to 'default' return values |
583 | |
584 | ✂------✂------✂------✂------✂------✂------✂------✂------✂------✂------ |
585 | |
586 | MooseのRole |
587 | =========== |
588 | Role of the Moose |
589 | ----------------- |
590 | |
591 | * Role は…(A role is like a) |
592 | * JavaのInterfaceみたい |
593 | * mixinみたい |
594 | * …それでいて安全でパワフル(safe, powerful) |
595 | * Role は小さくて再利用可能な動作向け(A role is for small reusable behaviors) |
596 | * 多重継承よりよい(better than using a multiple inheritence) |
597 | |
598 | ✂------✂------✂------✂------✂------✂------✂------✂------✂------✂------ |
599 | |
600 | MooseのRole(つづき) |
601 | =================== |
602 | Role of the Moose (cont.) |
603 | ------------------------- |
604 | |
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) |
611 | |
612 | ########## |
613 | |
614 | 再利用可能な小さな動作の例 |
615 | Some examples of small reusable behaviors |
616 | |
617 | Paramは連携に便利 |
618 | Param is good for interacting with e.g. CGI::Expand or similar modules |
619 | |
620 | ✂------✂------✂------✂------✂------✂------✂------✂------✂------✂------ |
621 | |
622 | MooseのRole(つづき) |
623 | =================== |
624 | Role of the Moose (cont.) |
625 | ------------------------- |
626 | |
627 | <pre><code> |
628 | package Minion; |
629 | use Moose; |
630 | |
631 | extends qw(Employee); |
632 | |
633 | with qw(Salaried::Hourly); |
634 | |
635 | package Boss; |
636 | use Moose; |
637 | |
638 | extends qw(Employee); |
639 | |
640 | with qw(Salaried::Monthly); |
641 | |
642 | </code></pre> |
643 | |
644 | * `with` はクラスに Role を追加します |
645 | * `with` adds roles into your class |
646 | * `Salaried::Hourly`が`Minion`に追加される |
647 | * `Salaried::Hourly` was added to `Minion` |
648 | |
649 | ✂------✂------✂------✂------✂------✂------✂------✂------✂------✂------ |
650 | |
651 | MooseのRole(つづき) |
652 | =================== |
653 | Role of the Moose (cont.) |
654 | ------------------------- |
655 | |
656 | <pre><code> |
657 | package Salaried; |
658 | use Moose::Role; |
659 | |
660 | requires qw('paycheck_amount'); |
661 | </code></pre> |
662 | |
663 | * 単なるインターフェース |
664 | * Just an interface |
665 | |
666 | ✂------✂------✂------✂------✂------✂------✂------✂------✂------✂------ |
667 | |
668 | MooseのRole(つづき) |
669 | =================== |
670 | Role of the Moose (cont.) |
671 | ------------------------- |
672 | |
673 | <pre><code> |
674 | package Salaried::Hourly; |
675 | use Moose::Role; |
676 | |
677 | with qw(Salaried); |
678 | |
679 | has hourly_rate => ( |
680 | isa => "Num", |
681 | is => "rw", |
682 | required => 1, |
683 | ); |
684 | |
685 | has logged_hours => ( |
686 | isa => "Num", |
687 | is => "rw", |
688 | default => 0, |
689 | ); |
690 | |
691 | sub paycheck_amount { |
692 | my $self = shift; |
693 | |
694 | $self->logged_hours * $self->hourly_rate; |
695 | } |
696 | |
697 | </code></pre> |
698 | |
699 | * インターフェースよりイイネ! |
700 | * More than an interface |
701 | |
702 | ✂------✂------✂------✂------✂------✂------✂------✂------✂------✂------ |
703 | |
704 | MooseのRole(つづき) |
705 | =================== |
706 | Role of the Moose (cont.) |
707 | ------------------------- |
708 | |
709 | * Javaのインターフェースよりイイネ! |
710 | * More than Java Interfaces |
711 | * インターフェースは挙動の'規定'を提供する |
712 | * Interfaces are behavior "contracts" |
713 | * Role は挙動の'実装'も提供できる |
714 | * Roles can also have code |
715 | |
716 | ########## |
717 | Roleはアトリビュートとメソッドを持てる |
718 | roles can have attributes and methods |
719 | Roleはインターフェースだけでなく動作を提供するもの |
720 | roles provide behavior, not just interface |
721 | |
722 | ✂------✂------✂------✂------✂------✂------✂------✂------✂------✂------ |
723 | |
724 | MooseのRole(つづき) |
725 | =================== |
726 | Role of the Moose (cont.) |
727 | ------------------------- |
728 | |
729 | * Roleの組み込み(Role Composition) |
730 | * 継承ではない(Not inheritence) |
731 | * 喧嘩両成敗(Symmetric) |
732 | * 順序は関係ない(Unordered) |
733 | |
734 | ✂------✂------✂------✂------✂------✂------✂------✂------✂------✂------ |
735 | |
736 | MooseのRole(つづき) |
737 | =================== |
738 | Role of the Moose (cont.) |
739 | ------------------------- |
740 | |
741 | * Roleの組み込み(Role Composition) |
742 | * あいまいさが少ない(Less ambiguity) |
743 | * コンパイル時エラー(Compile time errors) |
744 | * …修正する方法もある(And ways to fix them) |
745 | |
746 | ########## |
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 |
751 | |
752 | Roleは多重継承と違ってコンパイル時にエラーを吐く |
753 | roles cause errors at compile time, unlike multiple inheritence |
754 | |
755 | Roleは簡単にエラーを修正する方法も用意している |
756 | roles also provide easy ways to fix the errors |
757 | |
758 | ✂------✂------✂------✂------✂------✂------✂------✂------✂------✂------ |
759 | |
760 | MooseのRole(つづき) |
761 | =================== |
762 | Role of the Moose (cont.) |
763 | ------------------------- |
764 | |
765 | <pre><code> |
766 | package First; |
767 | use Moose::Role; |
768 | |
769 | sub dancing { ... } |
770 | |
771 | package Second; |
772 | use Moose::Role |
773 | |
774 | sub dancing { ... } |
775 | |
776 | package Foo; |
777 | use Moose; |
778 | |
779 | # KABOOM |
780 | with qw( |
781 | First |
782 | Second |
783 | ); |
784 | </code></pre> |
785 | |
786 | ########## |
787 | |
788 | 衝突 |
789 | conflicts |
790 | |
791 | ✂------✂------✂------✂------✂------✂------✂------✂------✂------✂------ |
792 | |
793 | MooseのRole(つづき) |
794 | =================== |
795 | Role of the Moose (cont.) |
796 | ------------------------- |
797 | |
798 | <pre><code> |
799 | package Ent::Puppy; |
800 | use Moose; |
801 | |
802 | with ( |
803 | Tree => { |
804 | alias => { |
805 | bark => "tree_bark", |
806 | }, |
807 | }, |
808 | Dog => { |
809 | alias => { |
810 | bark => "bark_sound", |
811 | } |
812 | }, |
813 | ); |
814 | |
815 | sub bark { |
816 | my $self = shift; |
817 | |
818 | if ( $condition ) { |
819 | $self->tree_bark; |
820 | } else { |
821 | $self->bark_sound; |
822 | } |
823 | } |
824 | </code></pre> |
825 | |
826 | ########## |
827 | |
828 | 組み込むときにパラメータをつける |
829 | Composition parameters |
830 | 衝突を解決するのも簡単だし |
831 | Easier conflict resolution |
832 | よりきめ細かいコントロールができるようになる |
833 | Finer grained control |
834 | |
835 | ✂------✂------✂------✂------✂------✂------✂------✂------✂------✂------ |
836 | |
837 | MOPはキレイ |
838 | =========== |
839 | MOPs Mean Cleanliness |
840 | --------------------- |
841 | |
842 | * Moose は Class::MOP でつくられてる |
843 | * Moose is based on `Class::MOP` |
844 | * Perl5のためのメタオブジェクトプロトコル(Metaobject Protocol for Perl 5) |
845 | * すべてにオブジェクトがつくられる("makes an object for everything") |
846 | |
847 | <pre><code> |
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)! |
851 | |
852 | warn $obj->meta->name; |
853 | </code></pre> |
854 | |
855 | ✂------✂------✂------✂------✂------✂------✂------✂------✂------✂------ |
856 | |
857 | 内側からみてみる |
858 | ================ |
859 | Looking in From the Inside |
860 | -------------------------- |
861 | |
862 | <pre><code> |
863 | my $metaclass = $self->meta; |
864 | |
865 | $metaclass->superclasses; |
866 | |
867 | $metaclass->linearized_isa; # すべての先祖クラスを得ます(returns all ancestors) |
868 | |
869 | $metaclass->has_method("foo"); |
870 | |
871 | $metaclass->compute_all_applicable_methods; # すべてのメソッド(継承されたものもふくめて)(returns all methods (inherited too)) |
872 | |
873 | $metaclass->has_attribute("bar"); |
874 | |
875 | # … lots more |
876 | </code></pre> |
877 | ########## |
878 | |
879 | simple introspection |
880 | |
881 | ✂------✂------✂------✂------✂------✂------✂------✂------✂------✂------ |
882 | |
883 | 内側からみてみる(つづき) |
884 | ======================== |
885 | Looking in From the Inside (cont.) |
886 | ---------------------------------- |
887 | |
888 | <pre><code> |
889 | Moose::Meta::Class->create( Bar => |
890 | version => '0.01', |
891 | superclasses => [ 'Foo' ], |
892 | attributes => [ |
893 | Moose::Meta::Attribute->new( bar => ... ), |
894 | Moose::Meta::Attribute->new( baz => ... ), |
895 | ], |
896 | methods => { |
897 | calculate_bar => sub { ... }, |
898 | construct_baz => sub { ... } |
899 | } |
900 | ); |
901 | </code></pre> |
902 | |
903 | ########## |
904 | |
905 | クラスはプログラム的につくることもできる |
906 | Classes can be created programmatically |
907 | |
908 | 無名クラスも可 |
909 | Anonymous classes also possible |
910 | ✂------✂------✂------✂------✂------✂------✂------✂------✂------✂------ |
911 | |
912 | 内側からみてみる(つづき) |
913 | ======================== |
914 | Looking in From the Inside (cont.) |
915 | ---------------------------------- |
916 | |
917 | <pre><code> |
918 | has foo => ( is => "rw" ); |
919 | |
920 | __PACKAGE__->meta->add_attribute( foo => is => "rw" ); |
921 | </code></pre> |
922 | |
923 | * Mooseは単なるシュガー(Moose is just sugar) |
924 | * 大変な部分はMOPがしてくれる(The MOP does the hard work) |
925 | |
926 | ✂------✂------✂------✂------✂------✂------✂------✂------✂------✂------ |
927 | |
928 | メタクラスのタンゴ |
929 | ================== |
930 | The Metaclass Tango |
931 | ------------------- |
932 | |
933 | * メタクラスはクラスの挙動をコントロールする |
934 | * Metaclassses control class behavior |
935 | |
936 | <pre><code> |
937 | has employees => ( |
938 | metaclass => 'Collection::Array', |
939 | ... |
940 | ); |
941 | </code></pre> |
942 | |
943 | * カスタムアトリビュートメタクラスは |
944 | * custom attribute metaclasses |
945 | * アトリビュートがどういう風に動くかを変える |
946 | * change how attributes work |
947 | * カスタマイズ可能なパーツたち |
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`, …, |
950 | |
951 | ✂------✂------✂------✂------✂------✂------✂------✂------✂------✂------ |
952 | |
953 | メタフレームを使う |
954 | ================== |
955 | Working in the Meta Frame |
956 | ------------------------- |
957 | |
958 | * 仕事であったおもろい話(An interesting `$work` story) |
959 | * flashを使ったサイト用のCMS(CMS for a flash website) |
960 | * コンテンツはXML(Content is in XML) |
961 | |
962 | ✂------✂------✂------✂------✂------✂------✂------✂------✂------✂------ |
963 | |
964 | メタフレームを使う(つづき) |
965 | ========================== |
966 | Working in the Meta Frame (cont.) |
967 | --------------------------------- |
968 | |
969 | * Step 1. use Moose |
970 | * Step 2. ??? |
971 | * Step 3. 金(Profit)! |
972 | |
973 | ✂------✂------✂------✂------✂------✂------✂------✂------✂------✂------ |
974 | |
975 | メタフレームを使う(つづき) |
976 | ========================== |
977 | Working in the Meta Frame (cont.) |
978 | --------------------------------- |
979 | |
980 | * Step 2.1. XMLスキーマ(schemas) → クラス(classes) |
981 | * 自動変換(Automatic conversion) |
982 | * MOPのおかげで楽勝(MOP makes it easy) |
983 | * 実行時には高レベルオブジェクト(High level objects in runtime) |
984 | * 裏ではXML(XML backed) |
985 | * クライアントのスキーマ(With client's schemas) |
986 | * SAX → Moose |
987 | * Moose → SAX |
988 | |
989 | ✂------✂------✂------✂------✂------✂------✂------✂------✂------✂------ |
990 | |
991 | メタフレームを使う(つづき) |
992 | ========================== |
993 | Working in the Meta Frame (cont.) |
994 | --------------------------------- |
995 | |
996 | * Step 2.2. メタ記述(Meta descriptions) |
997 | * メタクラスを拡張(Extend the metaclasses) |
998 | * 追加の情報を埋め込む(Embed additional information) |
999 | * フィールド型(field types) |
1000 | * アクセスコントロール(access control) |
1001 | |
1002 | ✂------✂------✂------✂------✂------✂------✂------✂------✂------✂------ |
1003 | |
1004 | メタフレームを使う(つづき) |
1005 | ========================== |
1006 | Working in the Meta Frame (cont.) |
1007 | --------------------------------- |
1008 | |
1009 | * Step 2.3 イントロスペクションかわゆす(Introspection goodness) |
1010 | * 汎用Webフロントエンド(Generic web frontend) |
1011 | * オブジェクトイントロスペクションベース(Object introspection based) |
1012 | * HTMLビュー(view) |
1013 | * 編集用のウィジェット(Editing widgets) |
1014 | * クリーンで拡張性も高い(Clean, extensible) |
1015 | |
1016 | ✂------✂------✂------✂------✂------✂------✂------✂------✂------✂------ |
1017 | |
1018 | Moose の欠点 |
1019 | ============ |
1020 | Drawbacks of Moose |
1021 | ------------------ |
1022 | |
1023 | * ロード時間(Load time) |
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` |
1029 | |
1030 | ✂------✂------✂------✂------✂------✂------✂------✂------✂------✂------ |
1031 | |
1032 | Mooseのイイ!とこ |
1033 | ================ |
1034 | Benefits of Moose |
1035 | ----------------- |
1036 | |
1037 | * 退屈なことを減らせる(Less tedious) |
1038 | * 決まり文句を書かなくていい(ditch that boilerplate): |
1039 | * アトリビュートのストレージ/アクセサ(attribute storage/access) |
1040 | * コンストラクタ(construction) |
1041 | * デストラクタ(destruction) |
1042 | * 引数検査(verification) |
1043 | * … |
1044 | * 繰り返しを減らせる(less repetition) |
1045 | * typo を減らせる(fewer typos) |
1046 | |
1047 | ✂------✂------✂------✂------✂------✂------✂------✂------✂------✂------ |
1048 | |
1049 | Mooseのイイ!とこ(つづき) |
1050 | ======================== |
1051 | Benefits of Moose (cont.) |
1052 | ------------------------- |
1053 | |
1054 | * みじかい(Shorter) |
1055 | * declarative == 情報がおおく、タイプ数がすくない(more info, less typing) |
1056 | * no RSI ;-) |
1057 | * コードがすくなきゃバグもすくなかろう(less code means fewer bugs) |
1058 | |
1059 | ✂------✂------✂------✂------✂------✂------✂------✂------✂------✂------ |
1060 | |
1061 | Mooseのイイ!とこ(つづき) |
1062 | ======================== |
1063 | Benefits of Moose (cont.) |
1064 | ------------------------- |
1065 | |
1066 | * テストがすくなくていい(Less testing) |
1067 | * Moose はよくテストされておる |
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 |
1076 | |
1077 | ✂------✂------✂------✂------✂------✂------✂------✂------✂------✂------ |
1078 | |
1079 | Mooseのイイ!とこ(つづき) |
1080 | ======================== |
1081 | Benefits of Moose (cont.) |
1082 | ------------------------- |
1083 | |
1084 | * 読みやすい(More readable) |
1085 | * 宣言的なスタイルだからそのまま文書になっている |
1086 | * declarative style is self documenting |
1087 | * やりたいことを書け。関係ないOOのしかけとかはあまり書かなくてもいい |
1088 | * Code your intentions, not and OO mechanics less |
1089 | |
1090 | ✂------✂------✂------✂------✂------✂------✂------✂------✂------✂------ |
1091 | |
1092 | Mooseのイイ!とこ(つづき) |
1093 | ======================== |
1094 | Benefits of Moose (cont.) |
1095 | ------------------------- |
1096 | |
1097 | * Meta object protocol |
1098 | * Perl の OO を綺麗にあつかえます |
1099 | * Cleans up all levels of Perl's OO |
1100 | * イントロスペクションできます |
1101 | * Provides introspection |
1102 | * パワフルな抽象化 |
1103 | * Enables powerful abstractions |
1104 | |
1105 | ✂------✂------✂------✂------✂------✂------✂------✂------✂------✂------ |
1106 | |
1107 | Mooseのイイ!とこ(つづき) |
1108 | ======================== |
1109 | Benefits of Moose (cont.) |
1110 | ------------------------- |
1111 | |
1112 | * 今年の流行だよ |
1113 | * It's the new black |
1114 | * イカした連中はみんな#mooseにきている |
1115 | * All the cool kids hang out on #moose |
1116 | * かっこよさげなバズワード |
1117 | * Smart sounding buzzwords |
1118 | * 2007年にはRubyがそうだったね |
1119 | * Ruby is so 2007 |
1120 | |
1121 | ✂------✂------✂------✂------✂------✂------✂------✂------✂------✂------ |
1122 | |
1123 | おまけ |
1124 | ====== |
1125 | Bonus Material |
1126 | -------------- |
1127 | |
1128 | ✂------✂------✂------✂------✂------✂------✂------✂------✂------✂------ |
1129 | |
1130 | Autobox |
1131 | ======= |
1132 | |
1133 | <pre><code> |
1134 | package Units::Bytes; |
1135 | use Moose::Role; |
1136 | use Moose::Autobox; |
1137 | |
1138 | sub bytes { $_[0] } |
1139 | sub kilobytes { $_[0] * 1024 } |
1140 | sub megabytes { $_[0] * 1024->kilobytes } |
1141 | sub gigabytes { $_[0] * 1024->megabytes } |
1142 | sub terabytes { $_[0] * 1024->gigabytes } |
1143 | |
1144 | Moose::Autobox->mixin_additional_role(SCALAR => 'Units::Bytes'); |
1145 | </code></pre> |
1146 | |
1147 | ✂------✂------✂------✂------✂------✂------✂------✂------✂------✂------ |
1148 | |
1149 | Autobox (つづき) |
1150 | ================ |
1151 | Autobox (cont.) |
1152 | --------------- |
1153 | |
1154 | <pre><code> |
1155 | use Units::Bytes; |
1156 | use Moose::Autobox; |
1157 | |
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'); |
1163 | </code></pre> |
1164 | |
1165 | ✂------✂------✂------✂------✂------✂------✂------✂------✂------✂------ |
1166 | |
1167 | perl -Moose |
1168 | =========== |
1169 | |
1170 | * Moose なワンライナーには `oose.pm` があるでよ |
1171 | * Moose One Liners with `oose.pm` |
1172 | |
1173 | <pre><code> |
1174 | perl -Moose -e'has foo => (is=>q[rw]); Class->new(foo=>1)' |
1175 | </code></pre> |
1176 | |
1177 | * なんかためしたいときなどに |
1178 | * Useful for testing if something works |
1179 | * IRC での会話には欠かせませんな! |
1180 | * Nice for IRC |
1181 | |
1182 | ✂------✂------✂------✂------✂------✂------✂------✂------✂------✂------ |
1183 | |
1184 | MooseX::POE |
1185 | =========== |
1186 | |
1187 | <pre><code> |
1188 | package Counter; |
1189 | use MooseX::POE; |
1190 | |
1191 | has count => ( |
1192 | isa => 'Int', |
1193 | is => 'rw', |
1194 | ); |
1195 | |
1196 | sub START { |
1197 | my ($self) = @_; |
1198 | $self->yield('increment'); |
1199 | } |
1200 | |
1201 | event increment => sub { |
1202 | my ($self) = @_; |
1203 | warn "Count is now " . $self->count; |
1204 | $self->count( $self->count + 1 ); |
1205 | $self->yield('increment') unless $self->count > 3; |
1206 | }; |
1207 | |
1208 | Counter->new( count => 0 ); |
1209 | POE::Kernel->run(); |
1210 | </code></pre> |
1211 | |
1212 | * POE のコンポーネントを簡単にかけます |
1213 | * POE components made easy |
1214 | * それぞれのオブジェクトが POE::Session をもってます |
1215 | * Every object has a POE::Session |
1216 | * `event` がオブジェクトのステートを宣言します |
1217 | * `event` declares object states |
1218 | |
1219 | ✂------✂------✂------✂------✂------✂------✂------✂------✂------✂------ |
1220 | |
1221 | Fin |
1222 | === |
1223 | |
1224 | * Slides written by: |
1225 | * Chris Prather |
1226 | * Stevan Little |
1227 | * Robert Boone |
1228 | |
1229 | * Slides deleted by: |
1230 | * Yuval Kogman |
1231 | |
1232 | * Slides translated by: |
1233 | * tokuhirom |