Permalink
Browse files

Remove emit() from roles.

Roles are all about static composition, and events are for dynamic
composition.  Roles that emit() events blur this distinction, so I'm
deeming them to be "bad".

Additionally, one of Reflex's prime directives is for consumers to
decide how they'll handle things.  Implementing "interface" callbacks
in roles (even default ones) takes this away from the consumer.  The
current solution is to provide declarative helpers to define the
defaults.  They also make more explicit that it's the consumer's role
(har) to define callbacks in all cases.  This is slightly less
convenient, but it's a lot cleaner.

Also add vim format lines so I stop dealing with whitespace
inconsistencies.
  • Loading branch information...
1 parent 18c07d9 commit 5b0127b4bad48d1b5a48f39309859e693a8738d8 @rcaputo committed May 30, 2011
Showing with 906 additions and 722 deletions.
  1. +62 −1 docs/TODO.otl
  2. +3 −1 docs/intro/AfterAwhileClass.pm
  3. +8 −8 docs/intro/AfterAwhileRole.pm
  4. +3 −1 docs/intro/AsyncAwhileClass.pm
  5. +8 −8 docs/intro/AsyncAwhileRole.pm
  6. +7 −2 docs/intro/intro.pod
  7. +2 −0 eg/EchoStream.pm
  8. +2 −0 eg/ExampleHelpers.pm
  9. +1 −0 eg/PoCoEvent.pm
  10. +1 −0 eg/PoCoPostback.pm
  11. +18 −4 eg/Proxy.pm
  12. +1 −0 eg/ReflexPromise.pm
  13. +17 −5 eg/Runner.pm
  14. +139 −143 eg/RunnerRole.pm
  15. +1 −0 eg/eg-02-encoding.pl
  16. +1 −0 eg/eg-04-inheritance.pl
  17. +1 −0 eg/eg-05-composition.pl
  18. +12 −1 eg/eg-06-moose-roles.pl
  19. +1 −0 eg/eg-07-wheel-run.pl
  20. +1 −0 eg/eg-08-watched-trait.pl
  21. +1 −0 eg/eg-11-poco-postback.pl
  22. +1 −0 eg/eg-12-poco-event.pl
  23. +1 −0 eg/eg-13-irc-bot.pl
  24. +1 −0 eg/eg-14-synopsis.pl
  25. +1 −0 eg/eg-15-ipc-run.pl
  26. +1 −0 eg/eg-16-timer-inheritance.pl
  27. +1 −0 eg/eg-17-inheritance-no-moose.pl
  28. +1 −0 eg/eg-18-synopsis-no-moose.pl
  29. +1 −0 eg/eg-30-promise-timer.pl
  30. +1 −0 eg/eg-31-promise-object.pl
  31. +1 −0 eg/eg-32-promise-tiny.pl
  32. +1 −0 eg/eg-33-all-callbacks.pl
  33. +1 −0 eg/eg-34-tcp-server-echo.pl
  34. +1 −0 eg/eg-35-tcp-client.pl
  35. +1 −0 eg/eg-36-tiny-coderefs.pl
  36. +1 −0 eg/eg-37-ping-pong.pl
  37. +1 −0 eg/eg-38-promise-client.pl
  38. +1 −0 eg/eg-39-signals.pl
  39. +1 −0 eg/eg-40-proxy.pl
  40. +1 −0 eg/eg-41-signal-twice.pl
  41. +1 −0 eg/eg-42-reflex-in-poe.pl
  42. +1 −0 eg/eg-50-timeout.pl
  43. +1 −0 eg/eg-51-wakeup.pl
  44. +7 −0 eg/eg-60-collection-promise.pl
  45. +1 −1 eg/ttl/Ttl/Adder.pm
  46. +1 −1 eg/ttl/Ttl/And.pm
  47. +1 −1 eg/ttl/Ttl/Bin.pm
  48. +1 −1 eg/ttl/Ttl/FlipFlop/D.pm
  49. +1 −1 eg/ttl/Ttl/FlipFlop/JK.pm
  50. +1 −1 eg/ttl/Ttl/FlipFlop/MasterSlave.pm
  51. +1 −1 eg/ttl/Ttl/FlipFlop/T.pm
  52. +2 −0 eg/ttl/Ttl/HexDecoder.pm
  53. +1 −1 eg/ttl/Ttl/Latch/ClockedNandRS.pm
  54. +1 −1 eg/ttl/Ttl/Latch/NandRS.pm
  55. +1 −1 eg/ttl/Ttl/Latch/NorRS.pm
  56. +1 −1 eg/ttl/Ttl/Nand.pm
  57. +1 −1 eg/ttl/Ttl/Nor.pm
  58. +1 −1 eg/ttl/Ttl/Not.pm
  59. +1 −1 eg/ttl/Ttl/Or.pm
  60. +1 −1 eg/ttl/Ttl/TriAnd.pm
  61. +1 −1 eg/ttl/Ttl/TriNand.pm
  62. +1 −1 eg/ttl/Ttl/Un.pm
  63. +1 −1 eg/ttl/Ttl/Xor.pm
  64. +1 −0 eg/ttl/fail-ttl-counter.pl
  65. +1 −0 eg/ttl/fail-ttl-simple.pl
  66. +1 −0 lib/Reflex.pm
  67. +8 −10 lib/Reflex/Acceptor.pm
  68. +1 −0 lib/Reflex/Base.pm
  69. +1 −0 lib/Reflex/Callback.pm
  70. +1 −0 lib/Reflex/Callback/CodeRef.pm
  71. +1 −0 lib/Reflex/Callback/Method.pm
  72. +1 −0 lib/Reflex/Callback/Promise.pm
  73. +93 −1 lib/Reflex/Callbacks.pm
  74. +2 −0 lib/Reflex/Client.pm
  75. +1 −0 lib/Reflex/Codec/Message.pm
  76. +1 −0 lib/Reflex/Codec/Message/Datagram.pm
  77. +1 −0 lib/Reflex/Codec/Message/Eof.pm
  78. +1 −0 lib/Reflex/Codec/Message/Stream.pm
  79. +2 −0 lib/Reflex/Collection.pm
  80. +11 −22 lib/Reflex/Connector.pm
  81. +1 −0 lib/Reflex/Decoder/Line.pm
  82. +9 −8 lib/Reflex/Interval.pm
  83. +5 −4 lib/Reflex/PID.pm
  84. +1 −0 lib/Reflex/POE/Event.pm
  85. +1 −0 lib/Reflex/POE/Postback.pm
  86. +1 −0 lib/Reflex/POE/Session.pm
  87. +2 −0 lib/Reflex/POE/Wheel.pm
  88. +2 −0 lib/Reflex/POE/Wheel/Run.pm
  89. +36 −96 lib/Reflex/Role.pm
  90. +19 −27 lib/Reflex/Role/Accepting.pm
  91. +1 −0 lib/Reflex/Role/Collectible.pm
  92. +28 −29 lib/Reflex/Role/Connecting.pm
  93. +2 −0 lib/Reflex/Role/Decoding.pm
  94. +2 −0 lib/Reflex/Role/Decoding/Stream.pm
  95. +17 −15 lib/Reflex/Role/InStreaming.pm
  96. +25 −24 lib/Reflex/Role/Interval.pm
  97. +23 −23 lib/Reflex/Role/OutStreaming.pm
  98. +20 −24 lib/Reflex/Role/PidCatcher.pm
  99. +4 −3 lib/Reflex/Role/Reactive.pm
  100. +20 −26 lib/Reflex/Role/Readable.pm
  101. +16 −28 lib/Reflex/Role/Reading.pm
  102. +18 −19 lib/Reflex/Role/Recving.pm
  103. +19 −23 lib/Reflex/Role/SigCatcher.pm
  104. +31 −34 lib/Reflex/Role/Streaming.pm
  105. +20 −19 lib/Reflex/Role/Timeout.pm
  106. +17 −16 lib/Reflex/Role/Wakeup.pm
  107. +21 −24 lib/Reflex/Role/Writable.pm
  108. +18 −12 lib/Reflex/Role/Writing.pm
  109. +1 −0 lib/Reflex/Sender.pm
  110. +5 −4 lib/Reflex/Signal.pm
  111. +9 −12 lib/Reflex/Stream.pm
  112. +8 −20 lib/Reflex/Timeout.pm
  113. +2 −0 lib/Reflex/Trait/EmitsOnChange.pm
  114. +2 −0 lib/Reflex/Trait/Observed.pm
  115. +2 −0 lib/Reflex/Trait/Watched.pm
  116. +13 −5 lib/Reflex/UdpPeer.pm
  117. +4 −2 lib/Reflex/Wakeup.pm
  118. +1 −0 t/000-info.t
  119. +1 −0 t/101-discrete-watcher.t
  120. +1 −0 t/102-watched-new.t
  121. +1 −0 t/103-watcher-roles.t
  122. +1 −0 t/104-emitter-trait.t
  123. +1 −0 t/105-setup.t
  124. +1 −0 t/120-rcb-coderef.t
  125. +1 −0 t/121-rcb-method.t
  126. +1 −0 t/122-rcb-object.t
  127. +1 −0 t/123-rcb-class.t
  128. +1 −0 t/124-rcb-role.t
  129. +1 −0 t/125-rcb-promise.t
  130. +1 −0 t/126-nested-emitters.t
  131. +1 −0 t/300-run-all-twice.t
View
@@ -1,4 +1,4 @@
-[_] 37% Framework Requirements
+[_] 40% Framework Requirements
About
This document summarizes the best ideas from the patterns document.
It is also a master TODO list for Reflex.
@@ -821,6 +821,67 @@
Allow the programmer to choose this overhead, only when it's likely to be necessary.
[_] 0% Remove the default emit()s.
[_] 0% Provide a consumer syntax to concisely specify emit()s at "with" time.
+ [_] 80% Parameterized role cleanup.
+ [X] 100% Role units of reactive behavior should not emit() events.
+ [X] 100% Remove event_parameter() from Reflex::Role.
+ [X] 100% Remove use of event_parameter() entirely.
+ [X] 100% Remove event_parameters declarations.
+ [X] 100% Sort the role parameter declarations.
+ [X] 100% Remove $ev_ variables.
+ [X] 100% Roles should not define default public "interface" callbacks.
+ [X] 100% Roles should require consumers to define cb_* callbacks.
+ [X] 100% Consumers should define cb_* methods, often in terms of Reflex::Callbacks make_emitter() or make_terminal_emitter().
+ [X] 100% Remove default $cb_* methods from roles.
+ [X] 100% Attribute parameters should begin with att_ to avoid confusion with simple value parameters.
+ [X] 100% Rename the attribute_parameters declarations.
+ [X] 100% Rename corresponding variables in the parameterized roles.
+ [X] 100% Rename attribute parameters in the consumers.
+ [X] 100% Require consumers to define the attributes.
+ [X] 100% The various parameters automatically add their named things to the list of required methods.
+ [X] 100% Make sure this plan works.
+ [X] 100% It doesn't.
+ The things being required depend on the values of specific parameters.
+ These values aren't known at role definition time.
+ They are known at role composition time.
+ [X] 100% Go back to explicit requires().
+ [X] 100% Rename references in callback_parameter declarations.
+ [X] 100% Rename references in method_parameter declarations.
+ [X] 100% Remove the default methods.
+ [X] 100% Implement the methods in the consumers.
+ [X] 100% Remove the methods from the roles.
+ [X] 100% Test all examples.
+ [X] 100% eg-02-encoding.pl
+ [X] 100% eg-04-inheritance.pl
+ [X] 100% eg-05-composition.pl
+ [X] 100% eg-06-moose-roles.pl
+ [X] 100% eg-07-wheel-run.pl
+ [X] 100% eg-08-watched-trait.pl
+ [X] 100% eg-11-poco-postback.pl
+ [X] 100% eg-12-poco-event.pl
+ [X] 100% eg-13-irc-bot.pl
+ [X] 100% eg-14-synopsis.pl
+ [X] 100% eg-15-ipc-run.pl
+ [X] 100% eg-16-timer-inheritance.pl
+ [X] 100% eg-17-inheritance-no-moose.pl
+ [X] 100% eg-18-synopsis-no-moose.pl
+ [X] 100% eg-30-promise-timer.pl
+ [X] 100% eg-31-promise-object.pl
+ [X] 100% eg-32-promise-tiny.pl
+ [X] 100% eg-33-all-callbacks.pl
+ [X] 100% eg-34-tcp-server-echo.pl
+ [X] 100% eg-35-tcp-client.pl
+ [X] 100% eg-36-tiny-coderefs.pl
+ [X] 100% eg-37-ping-pong.pl
+ [X] 100% eg-38-promise-client.pl
+ [X] 100% eg-39-signals.pl
+ [X] 100% eg-40-proxy.pl
+ [X] 100% eg-41-signal-twice.pl
+ [X] 100% eg-42-reflex-in-poe.pl
+ [X] 100% eg-50-timeout.pl
+ [X] 100% eg-51-wakeup.pl
+ [X] 100% eg-60-collection-promise.pl
+ [X] 100% test-observer.pl
+ [_] 0% Revise all documentation.
Philosophy
Boolean role parameters are opportunities for new roles or role subclasses.
Static behaviors should be determined at role consumption time.
@@ -5,6 +5,8 @@ extends 'Reflex::Base';
has name => ( is => 'ro', isa => 'Str', default => 'awhile' );
has awhile => ( is => 'ro', isa => 'Int', default => 1 );
-with 'AfterAwhileRole' => { cb => 'on_done' };
+with 'AfterAwhileRole' => {
+ cb => make_emitter(on_done => "done"),
+};
1;
@@ -1,23 +1,23 @@
package AfterAwhileRole;
use Reflex::Role;
-attribute_parameter name => "name";
-attribute_parameter awhile => "awhile";
-callback_parameter cb => qw( on name done );
+# TODO - Is att_name really needed?
+attribute_parameter att_awhile => "awhile";
+attribute_parameter att_name => "name";
+callback_parameter cb => qw( on att_name done );
role {
my $role_param = shift;
- my $cb_done = $role_param->cb();
- my $awhile = $role_param->awhile();
+ my $att_awhile = $role_param->att_awhile();
+ my $cb_done = $role_param->cb();
- method_emit $cb_done => "done";
+ requires $att_awhile, $p->att_name(), $cb_done;
sub BUILD {}
-
after BUILD => sub {
my $self = shift;
- sleep($self->$awhile());
+ sleep($self->$att_awhile());
$self->$cb_done();
};
};
@@ -5,6 +5,8 @@ extends 'Reflex::Base';
has name => ( is => 'ro', isa => 'Str', default => 'awhile' );
has awhile => ( is => 'ro', isa => 'Int', default => 1 );
-with 'AsyncAwhileRole' => { cb => 'on_done' };
+with 'AsyncAwhileRole' => {
+ cb => make_emitter(on_done => "done"),
+};
1;
@@ -3,23 +3,23 @@ use Reflex::Role;
use Reflex::Interval;
use Reflex::Callbacks qw(cb_method);
-attribute_parameter name => "name";
-attribute_parameter awhile => "awhile";
-callback_parameter cb => qw( on name done );
+attribute_parameter att_awhile => "awhile";
+attribute_parameter att_name => "name";
+callback_parameter cb => qw( on att_name done );
role {
my $role_param = shift;
- my $role_name = $role_param->name();
- my $cb_done = $role_param->cb();
- my $awhile = $role_param->awhile();
+ my $att_awhile = $role_param->att_awhile();
+ my $att_name = $role_param->att_name();
+ my $cb_done = $role_param->cb();
+
+ requires $att_awhile, $att_name, $cb_done;
my $timer_member = "_${role_name}_timer";
has $timer_member => ( is => 'rw', isa => 'Reflex::Interval' );
- method_emit $cb_done => "done";
-
sub BUILD {}
after BUILD => sub {
View
@@ -62,6 +62,7 @@ are named after this key by default.
That's a bit of work, but roles are generally the biggest Reflex
modules. The classes that use it are much smaller.
+TODO - Changed.
package AfterAwhileRole;
use Reflex::Role;
@@ -75,7 +76,7 @@ modules. The classes that use it are much smaller.
my $cb_done = $role_param->cb();
my $awhile = $role_param->awhile();
- method_emit $cb_done => "done";
+ method-emit $cb_done => "done";
sub BUILD {}
@@ -99,6 +100,7 @@ All Reflex classes should be based on Reflex::Base. The class exposes
"name" and "awhile" attributes so they may be set during object
construction.
+TODO - Changed.
package AfterAwhileClass;
use Moose;
extends 'Reflex::Base';
@@ -212,6 +214,7 @@ returns the next asynchrnous event they emit.
First, here's how it's done:
+TODO - Changed.
#!/usr/bin/env perl
use warnings;
@@ -227,6 +230,7 @@ First, here's how it's done:
We need to define AsyncAwhileClass before that will run. It's just a
renamed AfterAwhileClass, with the new asynchronous role.
+TODO - Changed.
package AsyncAwhileClass;
use Moose;
extends 'Reflex::Base';
@@ -243,6 +247,7 @@ This AsyncAwhileRole replaces the blocking sleep() with a non-blocking
Reflex::Interval object. Later we'll introduce magic to make it more
concise.
+TODO - Changed.
package AsyncAwhileRole;
use Reflex::Role;
use Reflex::Interval;
@@ -263,7 +268,7 @@ concise.
has $timer_member => ( is => 'rw', isa => 'Reflex::Interval' );
- method_emit $cb_done => "done";
+ method-emit $cb_done => "done";
sub BUILD {}
View
@@ -1,4 +1,6 @@
package EchoStream;
+# vim: ts=2 sw=2 noexpandtab
+
use Moose;
extends 'Reflex::Stream';
View
@@ -1,6 +1,8 @@
## Used in the examples to reduce LOC by declaring fucntions that are used
## over and over in this module
+# vim: ts=2 sw=2 noexpandtab
+
package ExampleHelpers;
use warnings;
View
@@ -1,4 +1,5 @@
package PoCoEvent;
+# vim: ts=2 sw=2 noexpandtab
# A component that accepts an event name to which return messages are
# posted. In this case, the component builds a postback for the
View
@@ -1,4 +1,5 @@
package PoCoPostback;
+# vim: ts=2 sw=2 noexpandtab
# A component that accepts postbacks to return messages.
View
@@ -1,15 +1,29 @@
package Proxy;
+# vim: ts=2 sw=2 noexpandtab
+
use Moose;
extends 'Reflex::Base';
+use Reflex::Callbacks qw(make_null_handler);
has handle_a => ( is => 'rw', isa => 'FileHandle', required => 1 );
has handle_b => ( is => 'rw', isa => 'FileHandle', required => 1 );
-with 'Reflex::Role::Streaming' => { handle => 'handle_a' };
-with 'Reflex::Role::Streaming' => { handle => 'handle_b' };
+has active => ( is => 'ro', isa => 'Bool', default => 1 );
+
+make_null_handler("on_handle_a_closed");
+make_null_handler("on_handle_b_closed");
+make_null_handler("on_handle_a_error");
+make_null_handler("on_handle_b_error");
+
+with 'Reflex::Role::Streaming' => {
+ att_active => 'active',
+ att_handle => 'handle_a',
+};
-sub on_handle_a_error { }
-sub on_handle_b_error { }
+with 'Reflex::Role::Streaming' => {
+ att_active => 'active',
+ att_handle => 'handle_b',
+};
sub on_handle_a_data {
my ($self, $arg) = @_;
View
@@ -1,4 +1,5 @@
package ReflexPromise;
+# vim: ts=2 sw=2 noexpandtab
use Moose;
extends 'Reflex::Base';
View
@@ -1,16 +1,28 @@
package Runner;
+# vim: ts=2 sw=2 noexpandtab
+
use Moose;
extends 'Reflex::Base';
+use Reflex::Callbacks qw(make_emitter make_terminal_emitter);
has [qw(stdin stdout stderr)] => ( isa => 'FileHandle', is => 'ro' );
has pid => ( isa => 'Int', is => 'ro' );
+has active => ( isa => 'Bool', is => 'ro', default => 1 );
with 'RunnerRole' => {
- stdin => 'stdin',
- stdout => 'stdout',
- stderr => 'stderr',
- pid => 'pid',
- ev_exit => 'exit',
+ att_active => 'active',
+ att_pid => 'pid',
+ att_stderr => 'stderr',
+ att_stdin => 'stdin',
+ att_stdout => 'stdout',
+ cb_exit => make_terminal_emitter(on_exit => "exit"),
+ cb_stderr_closed => make_emitter(on_stderr_closed => "stderr_closed"),
+ cb_stderr_data => make_emitter(on_stderr_data => "stderr_data"),
+ cb_stderr_error => make_emitter(on_stderr_error => "stderr_error"),
+ cb_stdin_error => make_emitter(on_stdin_error => "stdin_error"),
+ cb_stdout_closed => make_emitter(on_stdout_closed => "stdout_closed"),
+ cb_stdout_data => make_emitter(on_stdout_data => "stdout_data"),
+ cb_stdout_error => make_emitter(on_stdout_error => "stdout_error"),
};
1;
Oops, something went wrong.

0 comments on commit 5b0127b

Please sign in to comment.