ReflexHow does it work?   Rocco Caputo – @rcaputo          YAPC::NA     Tuesday, 28 June 2011        Around Teatime
Feedback, plx.
This talkdescribes theGithub Version
Who Does He Think He Is?• Rocco Caputo or “rcaputo” most places. • http://search.cpan.org/~rcaputo/ • https://github.com/r...
“The POE Guy”
⃠“The POE Guy”
Curtis “Ovid”    Poe
EdgarAllan Poe
Anne DecaturDanielewski
The Other Committers•   Adam Kennedy            •   Jonathan Steinert•   Benjamin Smith          •   Larwan Berke•   Casey...
The CPAN AuthorsAlejandro Imass • Alessandro Ranellucci • Anatoly Sharifulin • Andrew A.Chen • Andrew Hoying • Andrew Ster...
The UsersEOVERFLOW
Okay, me too.
Digression:See Digression
ReflexWhat Is It?Rocco Caputo – @rcaputo       YAPC::NA  Tuesday, 28 June 2011     Around Teatime
ReflexWhat Isn’t It?Rocco Caputo – @rcaputo       YAPC::NA  Tuesday, 28 June 2011     Around Teatime
What can’t you do with  a drunken sailor?
Reflex is an only child waiting in    the park.
⃠Reflex is an only child waiting in    the park.
Reflex isn’t an event loop.
CPANalready has too many    event   loops.
Event loopsare the means, not the ends.
Reflex iseventy withoutso much loopy.
Nor is Reflex an object system.
CPANalready has too many   object  systems.
Reflex uses  Moose
But Why?!“I am disappointed that after all thistime we have no consensus on howto say in Perl ‘Class X has attributeY’ whe...
But Why?!• Moose lets me solve higher-level problems.• Moose has sufficient adoption to survive.• The Meta-Object Protocol ...
ReflexWhat Is It?Rocco Caputo – @rcaputo       YAPC::NA  Tuesday, 28 June 2011     Around Teatime
The ORM ofEvent Loops!!
Marketingbullshit aside...
ReactiveProgram Building     Blocks
Building BlocksProvidedby Moose
Plus a Reactorprovided by Your Favorite Event      Loop
Invisible Event Loop
Like ORMs hide SQL     ORM  behind objects...   DB
Reflexhides event   loops      Reflex  behind       The              Events objects...    Can
Reflex isModern POE
Reflex is Modern POE• POE = Perl Object Environment• Modern Perl objects are very different than  1998 Perl objects.• POE h...
Reflex   unifies   eventyinteraction.
Rule 34 for PerlIf you can thinkof it, CPAN hasa module for it.
TIMTOWTDIIf you can thinkof it, CPAN has2+ incompatiblemodules for it...
TIMTOWTDI ... and someday  you’ll need touse both at once.
TIMTOWTDI• There’s more than one way to pass  events around.• The “best” way... depends.• Choosing poorly limits later opt...
3 ½ RulesMake it Work
⁓1⁓Objects must not dictate callback  mechanisms.
⁓ 1.5 ⁓  Users define    how theyreceive callbacks.
⁓2⁓The base systemmust support alldesired callback     types.
⁓3⁓ Reflex must dojust enough work   to be correct.
Reflex unifieseventy program composition.
“How EventyPrograms arePut Together”
Static Composition• Code is bolted together before running. • Subclassing. • Role composition.• All pieces built and destr...
Dynamic Composition• Event watchers are created, • related (has-a),   • communicated (with),     • and destructicated     ...
Dynamic Lifetimes• Object provides service to one owner. • Object life is briefer than its owner. • Object’s lifespan matc...
Reflex  Embraces, Extends andConsumes Both
Examples are   next.
ReflexHow to Use It! Rocco Caputo – @rcaputo        YAPC::NA   Tuesday, 28 June 2011      Around Teatime
Anonymous Callbacks
Ye Olde Coderef    use Reflex::Interval;•   my $i_one = Reflex::Interval->new(•      interval => 1,       on_tick => sub {...
Ye Olde Coderef    use Reflex::Interval;    my $i_one = Reflex::Interval->new(       interval => 1,•      on_tick => sub {...
Ye Olde Coderef    use Reflex::Interval;    my $i_one = Reflex::Interval->new(       interval => 1,       on_tick => sub {...
Ye Olde Coderef    use Reflex::Interval;    my $i_one = Reflex::Interval->new(       interval => 1,       on_tick => sub {...
Ye Olde Codereftick   one...TICK   TWO!!!TICK   TWO!!!tick   one...TICK   TWO!!!TICK   TWO!!!tick   one...TICK   TWO!!!TIC...
Ye Olde Coderef - The Good• Quick and dead simple to use.• Convenient and fast for small things.• Parsimonious use of memo...
Ye Olde Coderef - The Bad• Circular references and memory leaks—  unless you explicitly manage memory.• Anti-pattern if do...
Ye Olde Coderef - The Ugly # A twisty maze of coderefs, all alike. Watcher( sub {   Watcher( sub {     Watcher( sub {     ...
MethodCallbacks
Method Callbacks    {•       package TickingThing;•       use Moose; extends "Reflex::Base";        use Reflex::Interval; ...
Method Callbacks    {        package TickingThing;        use Moose; extends "Reflex::Base";        use Reflex::Interval;•...
Method Callbacks    {        package TickingThing;        use Moose; extends "Reflex::Base";        use Reflex::Interval; ...
Method Callbacks    {        package TickingThing;        use Moose; extends "Reflex::Base";        use Reflex::Interval; ...
Method Callbacksmethod   got   tick...method   got   tick...method   got   tick...method   got   tick...method   got   tic...
Methods – The Costs• Verbose syntax.• Perl OO is slower than code references  and closures.• Perl OO requires memory.• Moo...
Methods – The Benefits• Syntax gets sweeter.• Object oriented design is cleaner and more  extensible.  • No twisty maze of ...
Methods – The Future• Avoiding flexibility by design is a dead end.• Speed and size improve over time.• Perl may get its ow...
“But callbackssuck!” you say?
Promises
What’s a Promise?“an object that acts as a proxyfor a result that is initially notknown, usually because thecomputation of...
What’s a Promise?Blah, blah, blah.
Promises• Asynchronous event generator. • Create it. • Do other stuff while it’s working. • Pick up the next result later....
Timer Promise (1 of 2)  use Reflex::Interval;• my $one = Reflex::Interval->new(•    interval => 1• );  my $two = Reflex::I...
Timer Promise (1 of 2)  use Reflex::Interval;  my $one = Reflex::Interval->new(     interval => 1  );• my $two = Reflex::I...
Timer Promise (2 of 2)  print "Before   : ", time(), "n";• my $event = $two->next();• print "After two: ", time(), "n";  $...
Timer Promise (2 of 2)  print "Before   : ", time(), "n";  my $event = $two->next();  print "After two: ", time(), "n";• $...
Eventy Timer Promise    % perl promises.pl•   Before   : 1295045065                            Blocked 2 seconds.•   After...
Eventy Timer Promise    % perl promises.pl    Before   : 1295045065•   After two: 1295045067                            In...
When to Avoid! Shun!• Only use Reflex’s promises for  asynchronous tasks that may need to wait.• Synchronous generators and...
“We were somewherearound Asheville in the   heart of the BlueRidge Mountains when the Moose began to      take hold.”
Subclassing
Simpler Method   Callbacks
Method Callbacks    {        package TickingThing;        use Moose; extends "Reflex::Base";        use Reflex::Interval;•...
Method Callbacks    {        package TickingThing;        use Moose; extends "Reflex::Base";        use Reflex::Interval; ...
Method Callbacks   {       package TickingThing;       use Moose; extends "Reflex::Base";       use Reflex::Interval;     ...
Subclassed Interval    {•       package TickingThing;        use Moose;•       extends "Reflex::Interval";        before o...
Subclassed Interval    {        package TickingThing;        use Moose;        extends "Reflex::Interval";•       before o...
Subclassed Interval  {      package TickingThing;      use Moose;      extends "Reflex::Interval";      before on_tick => ...
Roles
Roles• They’re sticky.• They’re delicious.• They’re high in carbohydrate calories.• They may contain bacon.
Reflex Roles• Eventy features are implemented as roles. • Consume them when appropriate.• Each role has a corresponding cla...
Reflex::Interval (1 of 3)  package Reflex::Interval;  use Moose; extends "Reflex::Base";• has interval => (       isa => "N...
Reflex::Interval (2 of 3)    with "Reflex::Role::Interval" => {•      att_interval    => "interval",•      att_auto_start =...
Reflex::Interval (2 of 3)    with "Reflex::Role::Interval" => {       att_interval    => "interval",       att_auto_start =...
Reflex::Interval (2 of 3)    with "Reflex::Role::Interval" => {       att_interval    => "interval",       att_auto_start =...
Reflex::Interval (3 of 3)      1;
Parameterized Roles• Reflex uses role  parameters to wire  together code.• MooseX::Role::  Parameterized rocks  for this.
Three Kinds ofRole Parameters
Attribute Parameters• Name attributes in the consumer that  control role behavior.• Begin with “att_”.
Attribute Parameters  package Reflex::Interval;  use Moose;• has interval => ( isa => "Num", ... );• has auto_start => ( i...
Attribute Parameters    package Reflex::Interval;    use Moose;    has interval   => ( isa => "Num", ... );    has auto_st...
Callback Parameters• Name consumer methods to call back  when things happen.• Begin with “cb_”.• These callbacks are simpl...
Callback Parameters    package Reflex::Interval;    use Moose;    ...;    with "Reflex::Role::Interval" => {•      cb_tick...
Method Parameters• Roles may implement public API methods.• Classes get to decide what they’re called.• Begin with “method...
Method Parameters    {        package Reflex::Interval;        use Moose; extends "Reflex::Base";        with "Reflex::Rol...
Lots of   RoleParameters
Awesome   buttedious toconfigure.
Dynamic Defaults• Each role designates a primary attribute  parameter.• Other parameter default values are based  on the p...
Primary Attribute    with "Reflex::Role::Interval" => {•     att_interval => "watchdog",      ...,    }Role Parameter     ...
Primary Attribute    with "Reflex::Role::Interval" => {•     att_interval => "log_rotation",      ...,    }Role Parameter ...
Primary Attribute    with "Reflex::Role::Interval" => {•      att_interval    => "interval",•      att_auto_start => "auto...
Primary Attribute    with "Reflex::Role::Interval" => {•      att_interval    => "interval",       att_auto_start => "auto...
Primary Attribute    with "Reflex::Role::Interval" => {•      att_interval    => "interval",       att_auto_start => "auto...
Primary Attribute    with "Reflex::Role::Interval" => {•      att_interval    => "interval",       att_auto_start => "auto...
Primary Attribute    with "Reflex::Role::Interval" => {•      att_interval    => "interval",       att_auto_start => "auto...
OtherMooseMagic
Expose Inner Workings
Expose Inner Workings    {•       package AnotherTickingThing;•       use Moose; extends "TickingThing";        has "+tick...
Expose Inner Workings    {        package AnotherTickingThing;        use Moose; extends "TickingThing";•       has "+tick...
Expose Inner Workings    {        package AnotherTickingThing;        use Moose; extends "TickingThing";        has "+tick...
Replace Inner Workings
Replace Inner Workings  my $thing = TickingThing->new();• $thing->ticker(•   Reflex::Interval->new(•     interval => 0.125...
Replace Inner Workings• my $thing = TickingThing->new(         ticker => Reflex::Interval->new(           interval => 0.12...
Replace Inner Workings• my $thing;• $thing = TickingThing->new(         ticker => Reflex::Interval->new(           interva...
Replace Inner Workings• my $thing = TickingThing->new();• $thing->ticker(         Reflex::Interval->new(           interva...
Replace Inner Workings    my $thing = TickingThing->new();    $thing->ticker(       Reflex::Interval->new(         interva...
OverrideAttributes
Override Attributes    {•       package FasterInterval;•       use Moose; extends "Reflex::Interval";        has "+interva...
Override Attributes    {        package FasterInterval;        use Moose; extends "Reflex::Interval";•       has "+interva...
Override Attributes  {      package FasterInterval;      use Moose; extends "Reflex::Interval";      has "+interval" => ( ...
WhateverObjectsCan Do
What Can’tObjects Do?    ☺
ReflexHow does it work?   Rocco Caputo – @rcaputo          YAPC::NA     Tuesday, 28 June 2011        Around Teatime
Static Reflex      =   Moose
Dynamic Reflex   = Emit & Watch
Crossing theBarrier BetweenStatic & Dynamic   Interaction
Static to Dynamic• Classes are built using static roles.• Classes implement additional features.• Callbacks within a class...
Default Callback    with "Reflex::Role::Interval" => {       att_interval    => "interval",       att_auto_start => "auto_...
Dynamic back to Static?  Just CallStuff, Okay?
Trade Offs• Dynamic object interaction is richer, more  fun, and often necessary.• Beware of using dynamic messages solely...
Emitting an Event•   package Moosian; use Moose;•   extends "Reflex::Base";    has name => ( is => "ro", isa => "Str" );  ...
Emitting an Event    package Moosian; use Moose;    extends "Reflex::Base";    has name => ( is => "ro", isa => "Str" );• ...
Emitting an Event    package Moosian; use Moose;    extends "Reflex::Base";    has name => ( is => "ro", isa => "Str" );  ...
Emitting Events• Objects emit() events as part of their  public interfaces.• Events have no explicit destination.• It’s up...
Watching Events• my $bob = Moosian->new( name => "Bob" );  my $joe = Moosian->new( name => "Joe" );• $bob->watch( $joe, "y...
Watching Events    my $bob = Moosian->new( name => "Bob" );•   my $joe = Moosian->new( name => "Joe" );    $bob->watch( $j...
Watching Events  my $bob = Moosian->new( name => "Bob" );  my $joe = Moosian->new( name => "Joe" );  $bob->watch( $joe, "y...
Moosian DialogBob   says:   Yip-yip-yip-yip...   uh-huh   uh-huh..Joe   says:   Yip-yip-yip-yip...   uh-huh   uh-huh..Bob ...
Infinite Recursion OK        TIME     RSS COMMAND•    1:16.60   17940 perl moosians.pl        TIME     RSS COMMAND     2:37...
Infinite Recursion OK        TIME     RSS COMMAND     1:16.60   17940 perl moosians.pl        TIME     RSS COMMAND•    2:37...
Infinite Recursion OK        TIME     RSS COMMAND     1:16.60   17940 perl moosians.pl        TIME     RSS COMMAND     2:37...
Infinite Recursion OK        TIME     RSS COMMAND     1:16.60   17940 perl moosians.pl        TIME     RSS COMMAND     2:37...
SimplifiedHierarchical Watching
Hierarchical Watching?• Most program  structure is  hierarchical.• Trees of objects  that use other  objects.• Parent obje...
Moose Traits  Rock
WatchedAttributes
CallbacksDiscovered by    Name
Watched Attributes• use Reflex::Trait::Watched qw(watches);• watches clock => (       isa    => "Reflex::Interval",       ...
Watched Attributes  use Reflex::Trait::Watched qw(watches);  watches clock => (     isa    => "Reflex::Interval",     setu...
Watched Attributes  use Reflex::Trait::Watched qw(watches);  watches clock => (     isa    => "Reflex::Interval",     setu...
Watched Attributes  use Reflex::Trait::Watched qw(watches);• watches clock => (       isa    => "Reflex::Interval",       ...
Watched Attributes    use Reflex::Trait::Watched qw(watches);    watches clock => (•      isa    => "Reflex::Interval",   ...
Watched Attributes  use Reflex::Trait::Watched qw(watches);• watches penguin => (•   isa   => "Reflex::Bomb",       setup ...
Watched Attributes  use Reflex::Trait::Watched qw(watches);  watches penguin => (     isa   => "Reflex::Bomb",     setup =...
Watched Attributes  use Reflex::Trait::Watched qw(watches);• watches watchdog => ( ... Interval ... );• watches log_mark =...
Reflex RoleComposition
Two-Way Pipe Driver• Bidirectionally stream data between two  file handles.• Useful for proxies.
Two File Handles•   package Proxy;    use Moose;    extends "Reflex::Base";•   has client => (•     isa => "FileHandle",  ...
Reduced for Example• use Reflex::Callbacks "make_null_handler";• make_null_handler("on_client_closed");• make_null_handler...
From Client to Server• with "Reflex::Role::Streaming" => {         att_active => "active",•        att_handle => "client",...
From Client to Server    with "Reflex::Role::Streaming" => {       att_active => "active",       att_handle => "client",  ...
From Server to Client• with "Reflex::Role::Streaming" => {         att_active => "active",•        att_handle => "server",...
From Server to Client    with "Reflex::Role::Streaming" => {       att_active => "active",       att_handle => "server",  ...
We’re “Done”  1;
Quote-Done-Unquote• Not handling EOF (cb_closed).• Not handling errors (cb_error).• We’ll probably need separate “active” ...
Usage  # Assume we already have the sockets.• my $p = Proxy->new(•   client => $client_socket,•   server => $server_socket...
Simple?
I Wrote What?                         Reflex::Role::Writable                         att_handle                            ...
Reflex::Role::StreamingReflex                       The ability to.... RoleReading     ... read data from a non-blocking file...
Relax–It’s Just the Class• That’s the Proxy class.• All instances will share the same code.
Overkill? Dial it Back!   Roles letprograms pickand mix what  they need.
Reflex::Role::InStreaming            Reflex::Role::InStreaming            att_handle            att_active            cb_dat...
Reflex::Role::OutStreaming             Reflex::Role::OutStreaming             att_handle             att_active             ...
Dynamic  Fun
SmallTalk-Like Messaging
Auto-EmitMessages When  Attributes   Change
SmallTalk Messaging• package EmittingCounter;• use Reflex::Trait::EmitsOnChange qw(emits);  emits count => (     isa => "I...
SmallTalk Messaging    package EmittingCounter;    use Reflex::Trait::EmitsOnChange qw(emits);• emits count => (         i...
Now Watch It• use EmittingCounter;  use Reflex::Trait::Watched qw(watches);• watches counter => (•   isa   => "EmittingCou...
Now Watch It    use EmittingCounter;    use Reflex::Trait::Watched qw(watches);    watches counter => (       isa   => "Em...
Self- ManagedCollections
Reflex::Collection• Manages objects that do  Reflex::Role::Collectible.• Collectible objects are automatically  cleaned up w...
Echo Server (1 of 1)    {•       package TcpEchoServer; use Moose;•       extends "Reflex::Acceptor"; use EchoStream;     ...
Echo Server (1 of 1)    {        package TcpEchoServer; use Moose;•       extends "Reflex::Acceptor"; use EchoStream;     ...
Echo Server (1 of 1)    {        package TcpEchoServer; use Moose;        extends "Reflex::Acceptor"; use EchoStream;•    ...
Echo Server (1 of 1)    {        package TcpEchoServer; use Moose;        extends "Reflex::Acceptor"; use EchoStream;     ...
Echo Server (1 of 1)    {        package TcpEchoServer; use Moose;        extends "Reflex::Acceptor"; use EchoStream;     ...
EchoStream (1 of 1)• package EchoStream;    use Moose;•   extends "Reflex::Stream";    sub on_data {      my ($self, $args...
EchoStream (1 of 1)    package EchoStream;    use Moose;    extends "Reflex::Stream";• sub on_data {         my ($self, $a...
POECompatibility
Benefits of POE• Mature and stable.• Use any event loop you want.• Hundreds of existing modules.• Thousands of users.• And ...
POE Compatibility• Migrate incrementally. • Reflex can talk to POE modules. • POE modules can talk to Reflex objects. • “Sep...
“But is Reflex   Ready?”
40% Complete!• Large swathes of design are stable.• Documentation! • ... which I broke preparing for this talk.• Bugs! • ....
Help Make It Better• http://github.com/rcaputo/reflex • See the roadmap.• #reflex on irc.perl.org• poe-subscribe@perl.org• H...
Contribute to a Project• Nick Perez’s Reflex-based psgi server.• Reflexive::Role::Collective       Interact with a collectio...
Thank you!
WebliographyDrawing of Edgar Allan    Self-Herding CatPoe.                          ORM Diagram“A Softer World” comic.    ...
Upcoming SlideShare
Loading in...5
×

Reflex - How Does It Work? (extended dance remix)

3,334

Published on

Most asynchronous Perl programming is unnecessarily dynamic. It conflicts with object orientation, and it reintroduces memory management issues that some of us learned Perl to escape.

Reflex is a flexible, contemporary asynchronous library that embraces the latest developments in Perl object orientation. Asynchronous classes can be snapped together at coding time, reducing the amount of anonymous code that's often slung around at runtime. Methods are first-class callbacks in Reflex; they can be augmented and overridden using normal Perl OO. Mixing in Moose make things even better.

This presentation is an expanded, more code-intensive version of my Perl Oasis talk. It will cover the 6.5 ways Reflex-based modules can be used, including anonymous callback and closure juggling, and mind-bogglingly powerful Moose-fueled OO crack. Imperative promises are included for people who just want to do one simple thing without mucking about with callbacks at all.

Published in: Technology, Education
0 Comments
2 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total Views
3,334
On Slideshare
0
From Embeds
0
Number of Embeds
1
Actions
Shares
0
Downloads
24
Comments
0
Likes
2
Embeds 0
No embeds

No notes for slide

Reflex - How Does It Work? (extended dance remix)

  1. 1. ReflexHow does it work? Rocco Caputo – @rcaputo YAPC::NA Tuesday, 28 June 2011 Around Teatime
  2. 2. Feedback, plx.
  3. 3. This talkdescribes theGithub Version
  4. 4. Who Does He Think He Is?• Rocco Caputo or “rcaputo” most places. • http://search.cpan.org/~rcaputo/ • https://github.com/rcaputo • http://twitter.com/rcaputo
  5. 5. “The POE Guy”
  6. 6. ⃠“The POE Guy”
  7. 7. Curtis “Ovid” Poe
  8. 8. EdgarAllan Poe
  9. 9. Anne DecaturDanielewski
  10. 10. The Other Committers• Adam Kennedy • Jonathan Steinert• Benjamin Smith • Larwan Berke• Casey West • Martijn van Beers• Chris Fedde • Matt Cashner• Chris Williams • Matt Sickler• David Davis • Perl Whore• David Webb • Philip Gwyn• Hinrik Örn Sigurðsson • Tom Feist• jmadler • Yuval Kogman
  11. 11. The CPAN AuthorsAlejandro Imass • Alessandro Ranellucci • Anatoly Sharifulin • Andrew A.Chen • Andrew Hoying • Andrew Sterling Hanenkamp • Andrew V. Purshottam •Andy Grundman • Artur Bergman • Benjamin Trott • Brendan Beveridge •Chris Cobb • Chris Prather • Christian-Rolf Gruen • Curtis Hawthorne •Daisuke Maki • Daisuke Murase • Damien Krotkine • Dan McCormick • DavidGolden • David Snopek • Denis Pokataev • Dmitry Karasik • dmitry kim •Eriam Schaffter • Eric Waters • Erick Calder • George Nistorica • GregFast • Guillermo Roditi • Hans Dieter Pearcey • Ivan B. Serezhkin • J. J.Merelo Guervos • Jan Henning Thorsen • Jason McManus • Jeff Bisbee • JeffGoff • Jerome Quelin • Johannes Plunien • Jonathan Ringstad • Jozef Kutej• Justin Hunter • Kazuhiro Osawa • Kevin L. Esteb • Kirill Miazine •Larry Shatzer Jr • Loic TROCHET • Marc Lehmann • Marc Mims • Mark A.Hershberger • Mark McConnell • Mark Morgan • Markus Mueller • MatthewO’Connor • Michael Ching • Michael R. Davis • Michael Schilli • MikeFletcher • Mike Schroeder • Mischa Spiegelmock • MOCK • MSERGEANT •Nicholas Perez • Olivier ‘dolmen’ Mengue • Paul David Tinsley • PaulDriver • Paul Evans • Paul G Webster • Paul Visscher • Pavel Boldin •Pedro Melo • Peter Guzis • Przemyslaw Iskra • Rafael Kitover • RichardClamp • Rob Bloodgood • Rob Partington • Robert ‘phaylon’ Sedlacek •Sawyer X • Scott Beck • Scott McCoy • Sean Egan • Sebastien Aperghis-Tramoni • Sergey Kotenko • Sergey Skvortsov • Sjors Gielen • StephenAdkins • Steve James • Steve McNabb • Takeshi Miki • Tatsuhiko Miyagawa •Thiago Berlitz Rondon • Tony Cook • Torsten Raudssus • wb@95700.net •William Travis Holton • Yuji Suzuki • Yves Blusseau • Zoffix Znet
  12. 12. The UsersEOVERFLOW
  13. 13. Okay, me too.
  14. 14. Digression:See Digression
  15. 15. ReflexWhat Is It?Rocco Caputo – @rcaputo YAPC::NA Tuesday, 28 June 2011 Around Teatime
  16. 16. ReflexWhat Isn’t It?Rocco Caputo – @rcaputo YAPC::NA Tuesday, 28 June 2011 Around Teatime
  17. 17. What can’t you do with a drunken sailor?
  18. 18. Reflex is an only child waiting in the park.
  19. 19. ⃠Reflex is an only child waiting in the park.
  20. 20. Reflex isn’t an event loop.
  21. 21. CPANalready has too many event loops.
  22. 22. Event loopsare the means, not the ends.
  23. 23. Reflex iseventy withoutso much loopy.
  24. 24. Nor is Reflex an object system.
  25. 25. CPANalready has too many object systems.
  26. 26. Reflex uses Moose
  27. 27. But Why?!“I am disappointed that after all thistime we have no consensus on howto say in Perl ‘Class X has attributeY’ when so many other languageshave solutions that have freed theirusers’ minds up to move on tohigher-level problems.”— Peter Scott, on the Perl 5 Porters Mailing List
  28. 28. But Why?!• Moose lets me solve higher-level problems.• Moose has sufficient adoption to survive.• The Meta-Object Protocol is insanely useful.• Moose will get better as native Perl OO improves.
  29. 29. ReflexWhat Is It?Rocco Caputo – @rcaputo YAPC::NA Tuesday, 28 June 2011 Around Teatime
  30. 30. The ORM ofEvent Loops!!
  31. 31. Marketingbullshit aside...
  32. 32. ReactiveProgram Building Blocks
  33. 33. Building BlocksProvidedby Moose
  34. 34. Plus a Reactorprovided by Your Favorite Event Loop
  35. 35. Invisible Event Loop
  36. 36. Like ORMs hide SQL ORM behind objects... DB
  37. 37. Reflexhides event loops Reflex behind The Events objects... Can
  38. 38. Reflex isModern POE
  39. 39. Reflex is Modern POE• POE = Perl Object Environment• Modern Perl objects are very different than 1998 Perl objects.• POE has a lot of users.• Start over with Reflex so POE remains compatible.
  40. 40. Reflex unifies eventyinteraction.
  41. 41. Rule 34 for PerlIf you can thinkof it, CPAN hasa module for it.
  42. 42. TIMTOWTDIIf you can thinkof it, CPAN has2+ incompatiblemodules for it...
  43. 43. TIMTOWTDI ... and someday you’ll need touse both at once.
  44. 44. TIMTOWTDI• There’s more than one way to pass events around.• The “best” way... depends.• Choosing poorly limits later options.• Reflex supports any or all at once.
  45. 45. 3 ½ RulesMake it Work
  46. 46. ⁓1⁓Objects must not dictate callback mechanisms.
  47. 47. ⁓ 1.5 ⁓ Users define how theyreceive callbacks.
  48. 48. ⁓2⁓The base systemmust support alldesired callback types.
  49. 49. ⁓3⁓ Reflex must dojust enough work to be correct.
  50. 50. Reflex unifieseventy program composition.
  51. 51. “How EventyPrograms arePut Together”
  52. 52. Static Composition• Code is bolted together before running. • Subclassing. • Role composition.• All pieces built and destroyed together.• Most eventy abstractions ignore this.
  53. 53. Dynamic Composition• Event watchers are created, • related (has-a), • communicated (with), • and destructicated • at run time.• Lather, rinse, repeat until the owner ends.
  54. 54. Dynamic Lifetimes• Object provides service to one owner. • Object life is briefer than its owner. • Object’s lifespan matches its owner. • Good candidate for static composition.• Object provides service to 2+ subscribers. • Good candidate for breadboarding or publish/subscribe.
  55. 55. Reflex Embraces, Extends andConsumes Both
  56. 56. Examples are next.
  57. 57. ReflexHow to Use It! Rocco Caputo – @rcaputo YAPC::NA Tuesday, 28 June 2011 Around Teatime
  58. 58. Anonymous Callbacks
  59. 59. Ye Olde Coderef use Reflex::Interval;• my $i_one = Reflex::Interval->new(• interval => 1, on_tick => sub { print "tick one...n" }, ); my $i_two = Reflex::Interval->new( interval => 0.5, on_tick => sub { print "tick two...n" }, ); Reflex->run_all();
  60. 60. Ye Olde Coderef use Reflex::Interval; my $i_one = Reflex::Interval->new( interval => 1,• on_tick => sub { print "tick one...n" }, ); my $i_two = Reflex::Interval->new( interval => 0.5, on_tick => sub { print "tick two...n" }, ); Reflex->run_all();
  61. 61. Ye Olde Coderef use Reflex::Interval; my $i_one = Reflex::Interval->new( interval => 1, on_tick => sub { print "tick one...n" }, );• my $i_two = Reflex::Interval->new(• interval => 0.5, on_tick => sub { print "tick two...n" }, ); Reflex->run_all();
  62. 62. Ye Olde Coderef use Reflex::Interval; my $i_one = Reflex::Interval->new( interval => 1, on_tick => sub { print "tick one...n" }, ); my $i_two = Reflex::Interval->new( interval => 0.5,• on_tick => sub { print "TICK TWO!!!n" }, ); Reflex->run_all();
  63. 63. Ye Olde Codereftick one...TICK TWO!!!TICK TWO!!!tick one...TICK TWO!!!TICK TWO!!!tick one...TICK TWO!!!TICK TWO!!!^C
  64. 64. Ye Olde Coderef - The Good• Quick and dead simple to use.• Convenient and fast for small things.• Parsimonious use of memory.
  65. 65. Ye Olde Coderef - The Bad• Circular references and memory leaks— unless you explicitly manage memory.• Anti-pattern if done solely for speed... • Implementation detail wags the dog. • Giving up OO benefits for speed.
  66. 66. Ye Olde Coderef - The Ugly # A twisty maze of coderefs, all alike. Watcher( sub { Watcher( sub { Watcher( sub { Watcher( sub { Watcher( sub { Watcher( sub { Watcher( sub { Watcher( sub { Watcher( sub { Watcher( sub { Watcher( sub { Watcher( sub {
  67. 67. MethodCallbacks
  68. 68. Method Callbacks {• package TickingThing;• use Moose; extends "Reflex::Base"; use Reflex::Interval; has ticker => ( isa => "Reflex::Interval", is => "rw", default => sub { my $self = shift(); Reflex::Interval->new( interval => 1, on_tick => [ $self, "callback" ], ) }, ); sub callback { print "method got tick...n" } } Thing->new()->run_all();
  69. 69. Method Callbacks { package TickingThing; use Moose; extends "Reflex::Base"; use Reflex::Interval;• has ticker => (• isa => "Reflex::Interval", is => "rw", default => sub { my $self = shift(); Reflex::Interval->new( interval => 1, on_tick => [ $self, "callback" ], ) }, ); sub callback { print "method got tick...n" } } Thing->new()->run_all();
  70. 70. Method Callbacks { package TickingThing; use Moose; extends "Reflex::Base"; use Reflex::Interval; has ticker => ( isa => "Reflex::Interval", is => "rw", default => sub { my $self = shift(); Reflex::Interval->new(• interval => 1, on_tick => [ $self, "callback" ], ) }, ); sub callback { print "method got tick...n" } } Thing->new()->run_all();
  71. 71. Method Callbacks { package TickingThing; use Moose; extends "Reflex::Base"; use Reflex::Interval; has ticker => ( isa => "Reflex::Interval", is => "rw", default => sub { my $self = shift(); Reflex::Interval->new(• interval => 1, on_tick => [ $self, "callback" ], ) }, );• sub callback { print "method got tick...n" } } Thing->new()->run_all();
  72. 72. Method Callbacksmethod got tick...method got tick...method got tick...method got tick...method got tick...method got tick...method got tick...method got tick...method got tick...method got tick...^C
  73. 73. Methods – The Costs• Verbose syntax.• Perl OO is slower than code references and closures.• Perl OO requires memory.• Moose uses memory, too.
  74. 74. Methods – The Benefits• Syntax gets sweeter.• Object oriented design is cleaner and more extensible. • No twisty maze of nested code references, all different.• It’s all “standard” Perl and/or Moose.
  75. 75. Methods – The Future• Avoiding flexibility by design is a dead end.• Speed and size improve over time.• Perl may get its own MOP. • Moose and Moose-alikes may converge as Perl standardizes common features.
  76. 76. “But callbackssuck!” you say?
  77. 77. Promises
  78. 78. What’s a Promise?“an object that acts as a proxyfor a result that is initially notknown, usually because thecomputation of its value has notyet completed.” — Wikipedia
  79. 79. What’s a Promise?Blah, blah, blah.
  80. 80. Promises• Asynchronous event generator. • Create it. • Do other stuff while it’s working. • Pick up the next result later.• Blocks or returns “incomplete” if not done. • Implementation decides which. • Future release may let the caller decide.
  81. 81. Timer Promise (1 of 2) use Reflex::Interval;• my $one = Reflex::Interval->new(• interval => 1• ); my $two = Reflex::Interval->new( interval => 2 );
  82. 82. Timer Promise (1 of 2) use Reflex::Interval; my $one = Reflex::Interval->new( interval => 1 );• my $two = Reflex::Interval->new(• interval => 2• );
  83. 83. Timer Promise (2 of 2) print "Before : ", time(), "n";• my $event = $two->next();• print "After two: ", time(), "n"; $event = $one->next(); print "After one: ", time(), "n";
  84. 84. Timer Promise (2 of 2) print "Before : ", time(), "n"; my $event = $two->next(); print "After two: ", time(), "n";• $event = $one->next();• print "After one: ", time(), "n";
  85. 85. Eventy Timer Promise % perl promises.pl• Before : 1295045065 Blocked 2 seconds.• After two: 1295045067 After one: 1295045067
  86. 86. Eventy Timer Promise % perl promises.pl Before : 1295045065• After two: 1295045067 Instant result.• After one: 1295045067
  87. 87. When to Avoid! Shun!• Only use Reflex’s promises for asynchronous tasks that may need to wait.• Synchronous generators and iterators are more efficient for computation.
  88. 88. “We were somewherearound Asheville in the heart of the BlueRidge Mountains when the Moose began to take hold.”
  89. 89. Subclassing
  90. 90. Simpler Method Callbacks
  91. 91. Method Callbacks { package TickingThing; use Moose; extends "Reflex::Base"; use Reflex::Interval;• has ticker => (• isa => "Reflex::Interval", is => "rw", default => sub { my $self = shift(); Reflex::Interval->new( interval => 1, on_tick => [ $self, "callback" ], ) }, ); sub callback { print "method got tick...n" } } Thing->new()->run_all();
  92. 92. Method Callbacks { package TickingThing; use Moose; extends "Reflex::Base"; use Reflex::Interval; has ticker => ( isa => "Reflex::Interval", is => "rw", default => sub { my $self = shift(); Reflex::Interval->new(• interval => 1, on_tick => [ $self, "callback" ], ) }, );• sub callback { print "method got tick...n" } } Thing->new()->run_all();
  93. 93. Method Callbacks { package TickingThing; use Moose; extends "Reflex::Base"; use Reflex::Interval; has ticker => ( isa => "Reflex::Interval", is => "rw", default => sub { my $self = shift(); Reflex::Interval->new( interval => 1, on_tick => [ $self, "callback" ], ) }, ); sub callback { print "method got tick...n" } }• Thing->new()->run_all();
  94. 94. Subclassed Interval {• package TickingThing; use Moose;• extends "Reflex::Interval"; before on_tick => sub { print "customized tick...n" }; } TickingThing->new( interval => 1 )->run_all();
  95. 95. Subclassed Interval { package TickingThing; use Moose; extends "Reflex::Interval";• before on_tick => sub {• print "customized tick...n" }; } TickingThing->new( interval => 1 )->run_all();
  96. 96. Subclassed Interval { package TickingThing; use Moose; extends "Reflex::Interval"; before on_tick => sub { print "customized tick...n" }; }• TickingThing->new( interval => 1 )->run_all();
  97. 97. Roles
  98. 98. Roles• They’re sticky.• They’re delicious.• They’re high in carbohydrate calories.• They may contain bacon.
  99. 99. Reflex Roles• Eventy features are implemented as roles. • Consume them when appropriate.• Each role has a corresponding class. • Reflex::Interval is Reflex::Role::Interval.
  100. 100. Reflex::Interval (1 of 3) package Reflex::Interval; use Moose; extends "Reflex::Base";• has interval => ( isa => "Num", is => "rw" );• has auto_repeat => ( isa => "Bool", is => "ro", default => 1 );• has auto_start => ( isa => "Bool", is => "ro", default => 1 );
  101. 101. Reflex::Interval (2 of 3) with "Reflex::Role::Interval" => {• att_interval => "interval",• att_auto_start => "auto_start",• att_auto_repeat => "auto_repeat", cb_tick => "on_tick", method_start => "start", method_stop => "stop", method_repeat => "repeat", }; sub on_tick { my ($self, $args) = @_; $self->emit( event => "tick", args => $args ); }
  102. 102. Reflex::Interval (2 of 3) with "Reflex::Role::Interval" => { att_interval => "interval", att_auto_start => "auto_start", att_auto_repeat => "auto_repeat",• cb_tick => "on_tick", method_start => "start", method_stop => "stop", method_repeat => "repeat", };• sub on_tick { my ($self, $args) = @_;• $self->emit(• event => "tick", args => $args ); }
  103. 103. Reflex::Interval (2 of 3) with "Reflex::Role::Interval" => { att_interval => "interval", att_auto_start => "auto_start", att_auto_repeat => "auto_repeat", cb_tick => "on_tick",• method_start => "start",• method_stop => "stop",• method_repeat => "repeat", }; sub on_tick { my ($self, $args) = @_; $self->emit( event => "tick", args => $args ); }
  104. 104. Reflex::Interval (3 of 3) 1;
  105. 105. Parameterized Roles• Reflex uses role parameters to wire together code.• MooseX::Role:: Parameterized rocks for this.
  106. 106. Three Kinds ofRole Parameters
  107. 107. Attribute Parameters• Name attributes in the consumer that control role behavior.• Begin with “att_”.
  108. 108. Attribute Parameters package Reflex::Interval; use Moose;• has interval => ( isa => "Num", ... );• has auto_start => ( isa => "Bool", ... ); ...; with "Reflex::Role::Interval" => { att_interval => "interval", att_auto_start => "auto_start", ..., };
  109. 109. Attribute Parameters package Reflex::Interval; use Moose; has interval => ( isa => "Num", ... ); has auto_start => ( isa => "Bool", ... ); ...; with "Reflex::Role::Interval" => {• att_interval => "interval",• att_auto_start => "auto_start", ..., };
  110. 110. Callback Parameters• Name consumer methods to call back when things happen.• Begin with “cb_”.• These callbacks are simple, synchronous method calls.
  111. 111. Callback Parameters package Reflex::Interval; use Moose; ...; with "Reflex::Role::Interval" => {• cb_tick => "on_tick", ..., };• sub on_tick { my ($self, $args_hash) = @_; ...; }
  112. 112. Method Parameters• Roles may implement public API methods.• Classes get to decide what they’re called.• Begin with “method_”.
  113. 113. Method Parameters { package Reflex::Interval; use Moose; extends "Reflex::Base"; with "Reflex::Role::Interval" => { ...,• method_start => "start",• method_stop => "stop", }; } my $interval = Reflex::Interval->new();• $interval->stop();• $interval->start();
  114. 114. Lots of RoleParameters
  115. 115. Awesome buttedious toconfigure.
  116. 116. Dynamic Defaults• Each role designates a primary attribute parameter.• Other parameter default values are based on the primary parameter’s value.• Avoids namespace clashes as an extension of basic OO.
  117. 117. Primary Attribute with "Reflex::Role::Interval" => {• att_interval => "watchdog", ..., }Role Parameter Default Name method_start start_watchdog() method_stop stop_watchdog() cb_tick on_watchdog_tick()
  118. 118. Primary Attribute with "Reflex::Role::Interval" => {• att_interval => "log_rotation", ..., }Role Parameter Default Name method_start start_log_rotation() method_stop stop_log_rotation() cb_tick on_log_rotation_tick()
  119. 119. Primary Attribute with "Reflex::Role::Interval" => {• att_interval => "interval",• att_auto_start => "auto_start",• att_auto_repeat => "auto_repeat",• cb_tick => "on_tick",• method_start => "start",• method_stop => "stop",• method_repeat => "repeat", }; Redundancy is a special case. It overrides generally useful defaults.
  120. 120. Primary Attribute with "Reflex::Role::Interval" => {• att_interval => "interval", att_auto_start => "auto_start", att_auto_repeat => "auto_repeat",• cb_tick => "on_tick", method_start => "start", method_stop => "stop", method_repeat => "repeat", };Calls $self->on_tick() ... not $self->on_interval_tick()
  121. 121. Primary Attribute with "Reflex::Role::Interval" => {• att_interval => "interval", att_auto_start => "auto_start", att_auto_repeat => "auto_repeat", cb_tick => "on_tick",• method_start => "start", method_stop => "stop", method_repeat => "repeat", };Creates $interval->start() ... not $interval->start_interval()
  122. 122. Primary Attribute with "Reflex::Role::Interval" => {• att_interval => "interval", att_auto_start => "auto_start", att_auto_repeat => "auto_repeat", cb_tick => "on_tick", method_start => "start",• method_stop => "stop", method_repeat => "repeat", };Creates $interval->stop() ... not $interval->stop_interval()
  123. 123. Primary Attribute with "Reflex::Role::Interval" => {• att_interval => "interval", att_auto_start => "auto_start", att_auto_repeat => "auto_repeat", cb_tick => "on_tick", method_start => "start", method_stop => "stop",• method_repeat => "repeat", }; Etc.
  124. 124. OtherMooseMagic
  125. 125. Expose Inner Workings
  126. 126. Expose Inner Workings {• package AnotherTickingThing;• use Moose; extends "TickingThing"; has "+ticker" => ( handles => [ "interval" ], ); } my $thing = AnotherTickingThing->new(); $thing->interval(0.1); $thing->run_all();
  127. 127. Expose Inner Workings { package AnotherTickingThing; use Moose; extends "TickingThing";• has "+ticker" => (• handles => [ "interval" ],• ); } my $thing = AnotherTickingThing->new(); $thing->interval(0.1); $thing->run_all();
  128. 128. Expose Inner Workings { package AnotherTickingThing; use Moose; extends "TickingThing"; has "+ticker" => ( handles => [ "interval" ], ); } my $thing = AnotherTickingThing->new();• $thing->interval(0.1); $thing->run_all();
  129. 129. Replace Inner Workings
  130. 130. Replace Inner Workings my $thing = TickingThing->new();• $thing->ticker(• Reflex::Interval->new(• interval => 0.125, on_tick => [ $thing, "callback" ], ) ); $thing->run_all();
  131. 131. Replace Inner Workings• my $thing = TickingThing->new( ticker => Reflex::Interval->new( interval => 0.125,• on_tick => [ $thing, "callback" ], ) ); Can’t use $thing like this. It must be declared before it can be used.
  132. 132. Replace Inner Workings• my $thing;• $thing = TickingThing->new( ticker => Reflex::Interval->new( interval => 0.125,• on_tick => [ $thing, "callback" ], ) ); Two statements. Reference to $thing held inside $thing.
  133. 133. Replace Inner Workings• my $thing = TickingThing->new();• $thing->ticker( Reflex::Interval->new( interval => 0.125,• on_tick => [ $thing, "callback" ], ) ); Dynamically replace it later. Reference to $thing held inside $thing.
  134. 134. Replace Inner Workings my $thing = TickingThing->new(); $thing->ticker( Reflex::Interval->new( interval => 0.125,• on_tick => [ $thing, "callback" ], ) ); Either way, Reflex automatically weakens the inner reference for you.
  135. 135. OverrideAttributes
  136. 136. Override Attributes {• package FasterInterval;• use Moose; extends "Reflex::Interval"; has "+interval" => ( default => 0.5, ); } FasterInterval->new()->run_all();
  137. 137. Override Attributes { package FasterInterval; use Moose; extends "Reflex::Interval";• has "+interval" => (• default => 0.5, ); } FasterInterval->new()->run_all();
  138. 138. Override Attributes { package FasterInterval; use Moose; extends "Reflex::Interval"; has "+interval" => ( default => 0.5, ); }• FasterInterval->new()->run_all();
  139. 139. WhateverObjectsCan Do
  140. 140. What Can’tObjects Do? ☺
  141. 141. ReflexHow does it work? Rocco Caputo – @rcaputo YAPC::NA Tuesday, 28 June 2011 Around Teatime
  142. 142. Static Reflex = Moose
  143. 143. Dynamic Reflex = Emit & Watch
  144. 144. Crossing theBarrier BetweenStatic & Dynamic Interaction
  145. 145. Static to Dynamic• Classes are built using static roles.• Classes implement additional features.• Callbacks within a class are synchronous.• Classes emit dynamic messages.• Dynamic object interaction is based on watching for those messages.
  146. 146. Default Callback with "Reflex::Role::Interval" => { att_interval => "interval", att_auto_start => "auto_start", att_auto_repeat => "auto_repeat",• cb_tick => "on_tick", method_start => "start", method_stop => "stop", method_repeat => "repeat", };• sub on_tick { my ($self, $args) = @_;• $self->emit(• event => "tick", args => $args ); }
  147. 147. Dynamic back to Static? Just CallStuff, Okay?
  148. 148. Trade Offs• Dynamic object interaction is richer, more fun, and often necessary.• Beware of using dynamic messages solely “for fun’s sake”.• Static callbacks are more efficient.
  149. 149. Emitting an Event• package Moosian; use Moose;• extends "Reflex::Base"; has name => ( is => "ro", isa => "Str" ); sub yip { my ($self, $args) = @_; print( $self->name(), " says: Yip-yip-yip-yip..", " uh-huh uh-huh..n" ); $self->emit( event => "yipped" ); } 1;
  150. 150. Emitting an Event package Moosian; use Moose; extends "Reflex::Base"; has name => ( is => "ro", isa => "Str" );• sub yip { my ($self, $args) = @_;• print(• $self->name(),• " says: Yip-yip-yip-yip..",• " uh-huh uh-huh..n"• ); $self->emit( event => "yipped" ); } 1;
  151. 151. Emitting an Event package Moosian; use Moose; extends "Reflex::Base"; has name => ( is => "ro", isa => "Str" ); sub yip { my ($self, $args) = @_; print( $self->name(), " says: Yip-yip-yip-yip..", " uh-huh uh-huh..n" );• $self->emit( event => "yipped" ); } 1;
  152. 152. Emitting Events• Objects emit() events as part of their public interfaces.• Events have no explicit destination.• It’s up to users to watch() for events.
  153. 153. Watching Events• my $bob = Moosian->new( name => "Bob" ); my $joe = Moosian->new( name => "Joe" );• $bob->watch( $joe, "yipped", "yip" ); $joe->watch( $bob, "yipped", "yip" ); $bob->yip(); Reflex->run_all();
  154. 154. Watching Events my $bob = Moosian->new( name => "Bob" );• my $joe = Moosian->new( name => "Joe" ); $bob->watch( $joe, "yipped", "yip" );• $joe->watch( $bob, "yipped", "yip" ); $bob->yip(); Reflex->run_all();
  155. 155. Watching Events my $bob = Moosian->new( name => "Bob" ); my $joe = Moosian->new( name => "Joe" ); $bob->watch( $joe, "yipped", "yip" ); $joe->watch( $bob, "yipped", "yip" );• $bob->yip();• Reflex->run_all();
  156. 156. Moosian DialogBob says: Yip-yip-yip-yip... uh-huh uh-huh..Joe says: Yip-yip-yip-yip... uh-huh uh-huh..Bob says: Yip-yip-yip-yip... uh-huh uh-huh..Joe says: Yip-yip-yip-yip... uh-huh uh-huh..Bob says: Yip-yip-yip-yip... uh-huh uh-huh..Joe says: Yip-yip-yip-yip... uh-huh uh-huh..Bob says: Yip-yip-yip-yip... uh-huh uh-huh..Joe says: Yip-yip-yip-yip... uh-huh uh-huh..Bob says: Yip-yip-yip-yip... uh-huh uh-huh..Joe says: Yip-yip-yip-yip... uh-huh uh-huh..^C
  157. 157. Infinite Recursion OK TIME RSS COMMAND• 1:16.60 17940 perl moosians.pl TIME RSS COMMAND 2:37.94 17940 perl moosians.pl TIME RSS COMMAND 3:05.86 17940 perl moosians.pl TIME RSS COMMAND 3:30.69 17940 perl moosians.pl
  158. 158. Infinite Recursion OK TIME RSS COMMAND 1:16.60 17940 perl moosians.pl TIME RSS COMMAND• 2:37.94 17940 perl moosians.pl TIME RSS COMMAND 3:05.86 17940 perl moosians.pl TIME RSS COMMAND 3:30.69 17940 perl moosians.pl
  159. 159. Infinite Recursion OK TIME RSS COMMAND 1:16.60 17940 perl moosians.pl TIME RSS COMMAND 2:37.94 17940 perl moosians.pl TIME RSS COMMAND• 3:05.86 17940 perl moosians.pl TIME RSS COMMAND 3:30.69 17940 perl moosians.pl
  160. 160. Infinite Recursion OK TIME RSS COMMAND 1:16.60 17940 perl moosians.pl TIME RSS COMMAND 2:37.94 17940 perl moosians.pl TIME RSS COMMAND 3:05.86 17940 perl moosians.pl TIME RSS COMMAND• 3:30.69 17940 perl moosians.pl
  161. 161. SimplifiedHierarchical Watching
  162. 162. Hierarchical Watching?• Most program structure is hierarchical.• Trees of objects that use other objects.• Parent objects often need results from children.
  163. 163. Moose Traits Rock
  164. 164. WatchedAttributes
  165. 165. CallbacksDiscovered by Name
  166. 166. Watched Attributes• use Reflex::Trait::Watched qw(watches);• watches clock => ( isa => "Reflex::Interval", setup => sub { Reflex::Interval->new(interval => 1) }, ); sub on_clock_tick { print "tick...n" }
  167. 167. Watched Attributes use Reflex::Trait::Watched qw(watches); watches clock => ( isa => "Reflex::Interval", setup => sub { Reflex::Interval->new(interval => 1) }, );• sub on_clock_tick { print "tick...n" }
  168. 168. Watched Attributes use Reflex::Trait::Watched qw(watches); watches clock => ( isa => "Reflex::Interval", setup => sub { Reflex::Interval->new(interval => 1) }, );• sub on_clock_tick { print "tick...n" }
  169. 169. Watched Attributes use Reflex::Trait::Watched qw(watches);• watches clock => ( isa => "Reflex::Interval", setup => sub { Reflex::Interval->new(interval => 1) }, );• sub on_clock_tick { print "tick...n" }
  170. 170. Watched Attributes use Reflex::Trait::Watched qw(watches); watches clock => (• isa => "Reflex::Interval", setup => sub { Reflex::Interval->new(interval => 1) }, );• sub on_clock_tick { print "tick...n" }
  171. 171. Watched Attributes use Reflex::Trait::Watched qw(watches);• watches penguin => (• isa => "Reflex::Bomb", setup => sub { ... }, ); sub on_penguin_tick { ... } sub on_penguin_stop { ... } sub on_penguin_explode { ... }
  172. 172. Watched Attributes use Reflex::Trait::Watched qw(watches); watches penguin => ( isa => "Reflex::Bomb", setup => sub { ... }, );• sub on_penguin_tick { ... }• sub on_penguin_stop { ... }• sub on_penguin_explode { ... }
  173. 173. Watched Attributes use Reflex::Trait::Watched qw(watches);• watches watchdog => ( ... Interval ... );• watches log_mark => ( ... Interval ... );• sub on_watchdog_tick { ... }• sub on_log_mark_tick { ... }
  174. 174. Reflex RoleComposition
  175. 175. Two-Way Pipe Driver• Bidirectionally stream data between two file handles.• Useful for proxies.
  176. 176. Two File Handles• package Proxy; use Moose; extends "Reflex::Base";• has client => (• isa => "FileHandle", is => "rw", required => 1 );• has server => (• isa => "FileHandle", is => "rw", required => 1 );• has active => (• isa => "Bool", is => "ro", default => 1 );
  177. 177. Reduced for Example• use Reflex::Callbacks "make_null_handler";• make_null_handler("on_client_closed");• make_null_handler("on_client_error");• make_null_handler("on_server_closed");• make_null_handler("on_server_error");
  178. 178. From Client to Server• with "Reflex::Role::Streaming" => { att_active => "active",• att_handle => "client", }; sub on_client_data { my ($self, $arg) = @_; $self->put_server($arg->{data}); }
  179. 179. From Client to Server with "Reflex::Role::Streaming" => { att_active => "active", att_handle => "client", };• sub on_client_data { my ($self, $arg) = @_;• $self->put_server($arg->{data}); }
  180. 180. From Server to Client• with "Reflex::Role::Streaming" => { att_active => "active",• att_handle => "server", }; sub on_server_data { my ($self, $arg) = @_; $self->put_client($arg->{data}); }
  181. 181. From Server to Client with "Reflex::Role::Streaming" => { att_active => "active", att_handle => "server", };• sub on_server_data { my ($self, $arg) = @_;• $self->put_client($arg->{data}); }
  182. 182. We’re “Done” 1;
  183. 183. Quote-Done-Unquote• Not handling EOF (cb_closed).• Not handling errors (cb_error).• We’ll probably need separate “active” flags for client and server later.• Flow-control for data rate mismatches?• Etc.
  184. 184. Usage # Assume we already have the sockets.• my $p = Proxy->new(• client => $client_socket,• server => $server_socket, ); # Do something else while it runs.
  185. 185. Simple?
  186. 186. I Wrote What? Reflex::Role::Writable att_handle Reflex::Role::Reading att_active att_handle cb_ready cb_closed method_pause cb_data method_resume cb_error method_start method_read Reflex::Role::ReadableReflex::Role::Writing method_stop att_handleatt_handle att_activecb_error cb_readymethod_put method_pausemethod_flush Proxy method_resume client method_stop server Reflex::Role::Streaming active Reflex::Role::Streaming att_handle on_client_data att_handle att_active on_client_closed att_active cb_data on_client_error cb_data cb_closed put_client cb_closed cb_error stop_client cb_error method_put on_server_data method_put method_stop on_server_closed method_stop on_server_errorReflex::Role::Readable put_serveratt_handle stop_server Reflex::Role::Writingatt_active att_handlecb_ready cb_errormethod_pause method_put Reflex::Role::Writablemethod_resume method_flush Reflex::Role::Reading att_handlemethod_stop att_handle att_active cb_closed cb_ready cb_data method_pause cb_error method_resume method_read method_start method_stop
  187. 187. Reflex::Role::StreamingReflex The ability to.... RoleReading ... read data from a non-blocking file handle.Readable ... watch for data arriving on a file handle.Writing ... buffer and/or write data to a NB file handle.Writable ... watch a file handle for ability to write data.
  188. 188. Relax–It’s Just the Class• That’s the Proxy class.• All instances will share the same code.
  189. 189. Overkill? Dial it Back! Roles letprograms pickand mix what they need.
  190. 190. Reflex::Role::InStreaming Reflex::Role::InStreaming att_handle att_active cb_data cb_closed cb_error method_stop Reflex::Role::Readable Reflex::Role::Reading att_handle att_handle att_active cb_closed cb_ready cb_data method_pause cb_error method_resume method_read method_stop
  191. 191. Reflex::Role::OutStreaming Reflex::Role::OutStreaming att_handle att_active cb_data cb_closed cb_error method_put method_stop Reflex::Role::Writable att_handle Reflex::Role::Writing att_active att_handle cb_ready cb_error method_pause method_put method_resume method_flush method_start method_stop
  192. 192. Dynamic Fun
  193. 193. SmallTalk-Like Messaging
  194. 194. Auto-EmitMessages When Attributes Change
  195. 195. SmallTalk Messaging• package EmittingCounter;• use Reflex::Trait::EmitsOnChange qw(emits); emits count => ( isa => "Int", default => 0 ); sub something_happens { my $self = shift; $self->count($self->count() + 1); }
  196. 196. SmallTalk Messaging package EmittingCounter; use Reflex::Trait::EmitsOnChange qw(emits);• emits count => ( isa => "Int", default => 0 ); sub something_happens { my $self = shift;• $self->count($self->count() + 1); }
  197. 197. Now Watch It• use EmittingCounter; use Reflex::Trait::Watched qw(watches);• watches counter => (• isa => "EmittingCounter", setup => sub { EmittingCounter-> new() }, ); sub on_counter_count { my ($self, $args) = @_; print "counter reached $args->{value}n"; }
  198. 198. Now Watch It use EmittingCounter; use Reflex::Trait::Watched qw(watches); watches counter => ( isa => "EmittingCounter", setup => sub { EmittingCounter-> new() }, );• sub on_counter_count { my ($self, $args) = @_;• print "counter reached $args->{value}n"; }
  199. 199. Self- ManagedCollections
  200. 200. Reflex::Collection• Manages objects that do Reflex::Role::Collectible.• Collectible objects are automatically cleaned up when they stop.• Great for create-and-forget things.
  201. 201. Echo Server (1 of 1) {• package TcpEchoServer; use Moose;• extends "Reflex::Acceptor"; use EchoStream; use Reflex::Collection qw(has_many); has_many clients => ( handles => { remember_client => "remember" } ); sub on_accept { my ($self, $args) = @_; $self->remember_client( EchoStream->new( handle => $args->{socket} ) ); } }
  202. 202. Echo Server (1 of 1) { package TcpEchoServer; use Moose;• extends "Reflex::Acceptor"; use EchoStream; use Reflex::Collection qw(has_many); has_many clients => ( handles => { remember_client => "remember" } ); sub on_accept { my ($self, $args) = @_; $self->remember_client( EchoStream->new( handle => $args->{socket} ) ); } }
  203. 203. Echo Server (1 of 1) { package TcpEchoServer; use Moose; extends "Reflex::Acceptor"; use EchoStream;• use Reflex::Collection qw(has_many); has_many clients => ( handles => { remember_client => "remember" } ); sub on_accept { my ($self, $args) = @_; $self->remember_client( EchoStream->new( handle => $args->{socket} ) ); } }
  204. 204. Echo Server (1 of 1) { package TcpEchoServer; use Moose; extends "Reflex::Acceptor"; use EchoStream; use Reflex::Collection qw(has_many);• has_many clients => (• handles => {• remember_client => "remember" } ); sub on_accept { my ($self, $args) = @_; $self->remember_client( EchoStream->new( handle => $args->{socket} ) ); } }
  205. 205. Echo Server (1 of 1) { package TcpEchoServer; use Moose; extends "Reflex::Acceptor"; use EchoStream; use Reflex::Collection qw(has_many); has_many clients => ( handles => { remember_client => "remember" } );• sub on_accept { my ($self, $args) = @_;• $self->remember_client(• EchoStream->new( handle => $args->{socket} ) ); } }
  206. 206. EchoStream (1 of 1)• package EchoStream; use Moose;• extends "Reflex::Stream"; sub on_data { my ($self, $args) = @_; $self->put($args->{data}); } 1;
  207. 207. EchoStream (1 of 1) package EchoStream; use Moose; extends "Reflex::Stream";• sub on_data { my ($self, $args) = @_;• $self->put($args->{data}); } 1;
  208. 208. POECompatibility
  209. 209. Benefits of POE• Mature and stable.• Use any event loop you want.• Hundreds of existing modules.• Thousands of users.• And you. • Don’t rewrite everything at once.
  210. 210. POE Compatibility• Migrate incrementally. • Reflex can talk to POE modules. • POE modules can talk to Reflex objects. • “Separate but equal” is not enough.• Static Reflex is faster than POE message passing.• Reflex eg directory contains examples.
  211. 211. “But is Reflex Ready?”
  212. 212. 40% Complete!• Large swathes of design are stable.• Documentation! • ... which I broke preparing for this talk.• Bugs! • ... which I added preparing for this talk.• Roadmap documented in the repository.
  213. 213. Help Make It Better• http://github.com/rcaputo/reflex • See the roadmap.• #reflex on irc.perl.org• poe-subscribe@perl.org• Hackathon, BOF or hallway track.• Use it, and complain... to me.• Influence the project while it’s still plastic.
  214. 214. Contribute to a Project• Nick Perez’s Reflex-based psgi server.• Reflexive::Role::Collective Interact with a collection of reflexive objects.• Reflexive::Role::DataMover Move data between two streams.• Reflexive::Role::TCPServer Become a fully featured TCP server.• Reflexive::Stream::Filtering Apply POE filters to Reflex streams.• (Your Project Here)
  215. 215. Thank you!
  216. 216. WebliographyDrawing of Edgar Allan Self-Herding CatPoe. ORM Diagram“A Softer World” comic. POEs users areWizard Moose outstanding in their fields.Edgar Allan Bro Moose AntlersUniversum Promise RingTiled Angry Moose The WatchersAccidental Goatse A Fighter Jet Made of(Unused) Biceps
  1. A particular slide catching your eye?

    Clipping is a handy way to collect important slides you want to go back to later.

×