We are creating a large application with complex logic, consisting of modules. I used simpler methods to create larger methods, for example,
# fig. 1 package Foo; sub highlevel { my ($self, $user, $event) = @_; my $session = $self->get_session($user); my $result = $self->do_stuff($session, $event); $self->save_session($session); return $result; };
(this, of course, is simplified). Results are returned, exceptions are thrown, everyone is happy.
Now we move on to AnyEvent. My module is NOT the highest level, so I can not do only
# fig. 2 my $cv = AnyEvent->condvar;
Most of the AE modules I've seen so far work as follows:
# fig. 3 $module->do_stuff( $input, on_success => sub { ... }, on_error => sub { ... } );
So, I finished rewriting the lower level methods and tried to continue working with highlevel () and ...
# fig. 4 package Foo; sub highlevel { my ($self, $user, $event, %callbacks) = @_; my $done = $callbacks{on_success}; my $error = $callbacks{on_error}; $self->get_session( $user, on_error => $error, on_success => sub { my $session = shift; $self->do_stuff( $session, $event, on_error => $error, on_success => sub { my $result = shift; $self->save_session( $session, or_error => $error, on_success => sub { $done->($result); } ); } ); } ); };
Not quite pretty. I call it the "Endless Staircase."
Now the next thing I could think of was an ad-hoc state machine, where highlevel () is broken down into _highlevel_stage1 (), _highlevel_stage2 (), etc. But this does not satisfy me (this is unacceptable, and thinking of good names instead of stageXX gives me a headache).
We are already looking at a full-sized state machine to manage the entire application, but adding a transition for each interaction seems too generous for me.
So, the question arises: what are the best methods for writing modules that implement business logic (Fig. 1) for working in the AnyEvent application (Figure 3)?