Reflex - How does it work?

1,975 views

Published on

This is an outdated 20-minute overview of Reflex, a modern Perl library for building asynchronous, eventy classes and programs. Please see the extended dance remix I presented at YAPC::NA 2011 instead.

Published in: Technology, Education
  • Be the first to comment

  • Be the first to like this

Reflex - How does it work?

  1. 1. ReflexHow does it work? Rocco Caputo – @rcaputo Orlando Perl Workshop Saturday, 15 January 2011 Around Noon
  2. 2. Reflex What Is It?Rocco Caputo – @rcaputo Orlando Perl Workshop Saturday, 15 January 2011 Around Noon
  3. 3. What’s Reflex?!• Library of roles that process eventy stuff— timers, I/O notifications, signals, etc.• Eventy class library built with those roles.
  4. 4. Reflex Roles–Brieflypackage AsyncConsole;use Moose; extends Reflex::Base;has stdin => ( is => rw, isa => FileHandle, required => 1,);with Reflex::Role::Readable => { handle => stdin, cb_ready => get_keystroke,};sub get_keystroke { ... }
  5. 5. Reflex Roles?package Console;use Moose; extends Reflex::Base;has stdout => ( is => rw, isa => FileHandle, required => 1,);with Reflex::Role::Readable => { handle => stdin, cb_ready => get_keystroke,};sub get_keystroke { ... }
  6. 6. Except Much Better
  7. 7. I’ll Explainat YAPC::NA
  8. 8. ReflexHow does it work? Rocco Caputo – @rcaputo Orlando Perl Workshop Saturday, 15 January 2011 Around Noon
  9. 9. Magic
  10. 10. Sufficiently AdvancedTechnology
  11. 11. “SufficientlyAdvanced” = We Don’t Know Yet
  12. 12. LearnMagic in 90 Minutes
  13. 13. Learn JustEnough Magic in 20 Minutes to Harm Yourself
  14. 14. Learn JustEnough Magic in 18 Minutes to Harm Yourself
  15. 15. ReflexHow does it work? Rocco Caputo – @rcaputo Orlando Perl Workshop Saturday, 15 January 2011 Around Noon
  16. 16. ProgramComposition
  17. 17. Dynamic Composition• Objects are created, • related, • communicated (with), • and destructicated • at run time.• Lather, rinse, repeat until the program ends.
  18. 18. Static Composition• Code is bolted together before running.• It stays that way “forever”.• Subclassing.• Moose roles.
  19. 19. Dynamic Reflex
  20. 20. Anonymous Callbacks
  21. 21. Ye Olde Coderefuse Reflex::Interval;my $i = Reflex::Interval->new( interval => 1, on_tick => sub { print "tick...n" },);$i->run_all();
  22. 22. Ye Olde Codereftick...tick...tick...^C
  23. 23. Ye Olde Coderef• Quick and dead simple to use.• Closure tricks for convenience and speed.• Closures can’t use OO to extend or override event handlers.• Uses circular references—memory leakage if you’re not careful.
  24. 24. MethodCallbacks
  25. 25. Methodshas ticker => ( isa => Reflex::Interval, is => rw );sub BUILD { my $self = shift; $self->ticker( Reflex::Interval->new( interval => 1, on_tick => cb_method($self, "callback"), ) );}sub callback { print "tick...n" }
  26. 26. Methodshas ticker => ( isa => Reflex::Interval, is => rw );sub BUILD { my $self = shift; $self->ticker( Reflex::Interval->new( interval => 1, on_tick => cb_method($self, "callback"), ) );}sub callback { print "tick...n" }
  27. 27. Methodshas ticker => ( isa => Reflex::Interval, is => rw );sub BUILD { my $self = shift; $self->ticker( Reflex::Interval->new( interval => 1, on_tick => cb_method($self, "callback"), ) );}sub callback { print "tick...n" }
  28. 28. Methods• Cleaner object oriented design.• Callbacks can use every Moose trick in the book.• Requires more forethought.• Perl & Moose OO less performant than anonymous subroutines & closures.
  29. 29. ObservedAttributes
  30. 30. Callbacks DiscoveredAutomatically
  31. 31. MooseTraits Rock
  32. 32. Observed Attributesuse Reflex::Trait::Observed qw(observes);observes clock => ( isa => Reflex::Interval, setup => sub { Reflex::Interval->new(interval => 1) },);sub on_clock_tick { print "tick...n" }
  33. 33. Observed Attributesuse Reflex::Trait::Observed qw(observes);observes clock => ( isa => Reflex::Interval, setup => sub { Reflex::Interval->new(interval => 1) },);sub on_clock_tick { print "tick...n" }
  34. 34. Observed Attributesuse Reflex::Trait::Observed qw(observes);observes clock => ( isa => Reflex::Interval, setup => sub { Reflex::Interval->new(interval => 1) },);sub on_clock_tick { print "tick...n" }
  35. 35. Observed Attributesuse Reflex::Trait::Observed qw(observes);observes clock => ( isa => Reflex::Interval, setup => sub { Reflex::Interval->new(interval => 1) },);sub on_clock_tick { print "tick...n" }
  36. 36. Observed Attributesuse Reflex::Trait::Observed qw(observes);observes clock => ( isa => Reflex::Interval, setup => sub { Reflex::Interval->new(interval => 1) },);sub on_clock_tick { print "tick...n" }
  37. 37. Observed Attributesuse Reflex::Trait::Observed qw(observes);observes penguin => ( isa => Reflex::Bomb, setup => sub { ... },);sub on_penguin_tick { ... }sub on_penguin_stop { ... }sub on_penguin_explode { ... }
  38. 38. Observed Attributesuse Reflex::Trait::Observed qw(observes);observes watchdog => ( ... Interval ... );observes log_mark => ( ... Interval ... );sub on_watchdog_tick { ... }sub on_log_mark_tick { ... }
  39. 39. One Class,Three Uses
  40. 40. “But callbacks suck!”
  41. 41. Promises
  42. 42. What’s a Promise?“an object that acts as a proxyfor a result that is initially not known, usually because the computation of its value has not yet completed.” — Wikipedia
  43. 43. What’s a Promise?Blah blah blah.
  44. 44. What’s a Promise?• Asynchronous object. • Create it. • Do other stuff while it runs. • Pick up the result later.• Blocks or returns “incomplete” if not done. • Other stuff runs while it blocks.
  45. 45. Timer Promise (1 of 2)use Reflex::Interval;my $one = Reflex::Interval->new( interval => 1);my $two = Reflex::Interval->new( interval => 2);
  46. 46. 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";
  47. 47. Eventy Timer Promise% perl this-time-for-sure.plBefore : 1295045065After two: 1295045067After one: 1295045067
  48. 48. Eventy Timer Promise% perl this-time-for-sure.plBefore : 1295045065After two: 1295045067After one: 1295045067
  49. 49. One Class,Three Four Uses
  50. 50. FourDynamic Uses
  51. 51. Static Reflex
  52. 52. Subclassing
  53. 53. Eventy Subclassing{ package MyTimer; use Moose; extends Reflex::Interval; before on_tick => sub { say "tick..." };}MyTimer->new( interval => 1 )->run_all();
  54. 54. Eventy Subclassingtick...tick...tick...^C
  55. 55. One ClassFour Five Uses
  56. 56. Must be abeast, right?
  57. 57. Reflex::Interval (1 of 3)package Reflex::Interval;use Moose; extends Reflex::Base;has interval => ( isa => Num, is => ro);has auto_repeat => ( isa => Bool, is => ro, default => 1);has auto_start => ( isa => Bool, is => ro, default => 1);
  58. 58. Reflex::Interval (2 of 3)with Reflex::Role::Interval => { interval => "interval", auto_start => "auto_start", auto_repeat => "auto_repeat", cb_tick => "on_tick", ev_tick => "tick", method_start => "start", method_stop => "stop", method_repeat => "repeat",};
  59. 59. Reflex::Interval (3 of 3) 1;
  60. 60. Roles
  61. 61. Reflex Roles• Reflex eventiness implemented with roles. • Timers, I/O, signals, etc.• Roles are reified by simple classes. • Reflex::Interval is Reflex::Role::Interval.• Larger roles comprise simpler ones.• It’s all Mooses, all the way down.
  62. 62. Parameterized Roles• MooseX::Role::Parameterized rocks. • Parameters customize roles—fill in the blanks like templates. • Reflex uses it like breadboarding with Moose.
  63. 63. Lots of RoleParameters
  64. 64. They’re Tedious to Configure
  65. 65. Smart Defaults• A primary attribute identifies the role.• Default parameters are named after that attribute.• Roles avoid conflicts by default.• Without tediously supplying all parameters.
  66. 66. Key Attributewith Reflex::Role::Interval => { interval => "watchdog",}Role Parameter Default Name method_start start_watchdog() method_stop stop_watchdog() cb_tick on_watchdog_tick() ev_tick watchdog_tick
  67. 67. Key Attributewith Reflex::Role::Interval => { interval => "logmark",}Role Parameter Default Name method_start start_logmark() method_stop stop_logmark() cb_tick on_logmark_tick() ev_tick logmark_tick
  68. 68. One ClassRole Five Six Uses
  69. 69. Dynamic Fun
  70. 70. Smalltalk Messaging• Reflex::Trait::EmitsOnChange• Emits an event when an attribute changes. use Reflex::Trait::EmitsOnChange qw(emits); emits count => ( isa => Int, default => 0 ); sub on_ticker_tick { my $self = shift; $self->count($self->count() + 1); }
  71. 71. Smalltalk Messaginguse Reflex::Trait::EmitsOnChange qw(emits);emits count => ( isa => Int, default => 0);sub on_ticker_tick { my $self = shift; $self->count($self->count() + 1);}
  72. 72. Reflex::Collection• Manages Reflex::Role::Collectible objects.• Removes them as they stop.• Great for holding autonomous things.
  73. 73. Reflex::Collection{ 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} ) ); }}
  74. 74. Reflex::Collection{ 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} ) ); }}
  75. 75. Reflex::Collection{ 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} ) ); }}
  76. 76. EchoStreampackage EchoStream;use Moose;extends Reflex::Stream;sub on_data { my ($self, $args) = @_; $self->put($args->{data});}1;
  77. 77. But is Reflex ready?
  78. 78. Reflex is Newish• Large swathes of design are stable.• Details need to be ironed out.• Will happen faster if you use it.• Help me find the edge cases.
  79. 79. How To Help• http://github.com/rcaputo/reflex • See docs/TODO.otl• #reflex on irc.perl.org• poe-subscribe@perl.org• Hackathon?• Hire someone to use it on your project.
  80. 80. Contribute to a Project• Nick Perez’s Reflex-based psgi server.• Reflexive::Stream::Filtering • Attach POE filters to Reflex streams.• Reflexive::Role::TCPServer • Consumable full-featured TCP server.• (Your Project Here)
  81. 81. Thank you!

×