Writing good object-oriented code under AnyEvent
anyevent, asynchronous, perl
Solution
You may want to encapsulate it in a Future object using the `Future` module. That adds syntactical sugar to make this cleaner.
Problem
We're building a large application with complex logic, which is composed of modules. I used to build larger scale methods of simpler methods, for instance, ``` # 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 is simplified of course). Results are returned, exceptions are thrown, everyone's happy. Now, we're making a move to AnyEvent. My module is NOT the uppermost level, so I can't do just ``` # fig. 2 my $cv = AnyEvent->condvar; # do stuff return $cv->recv; ``` Most AE modules I've seen so far work like this: ``` # fig. 3 $module->do_stuff( $input, on_success => sub { ... }, on_error => sub { ... } ); ``` So I'm done rewriting the lower-level methods and tried to proceed 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 exactly beautiful. I call it "the Infinite ladder". Now the next thing I could come up with was an ad-hoc state machine where highlevel() is broken up into _highlevel_stage1(), _highlevel_stage2() etc. But that doesn't satisfy me as well (it's unmaintainable, and thinking of good names instead of stageXX gives me headache). We're already looking into a full-blown state machine to drive the whole app, but having to add a transition for every interaction looks a bit too generous to me. So the question is: What are the best practices for writing modules that implement business logic (fig. 1) for running within an AnyEvent app (fig. 3)?