On Mon, Oct 08, 2012 at 07:08:09AM -0700, Bill Moseley wrote:
> I'm looking for some design ideas, and I'll try and briefly describe it.
> I suspect this is a Role vs. subclass question.
>
> I have a job processing system where a set of one or more jobs are
> processed. At the top I have a small class that has an ArrayRef of jobs
> and a method to "submit" the jobs for processing once they have all been
> gathered. The jobs are processed independently, but they need to be
> submitted together. (They are submitted to a pool of worker machines.)
>
> It's the individual job class I have a question about.
>
> A job has about five distinct stages of processing and uses a DBIx::Class
> row as a storage backend to maintain state. The first state is before it
> has been "submitted" and doesn't have a job_id yet. A notification
> message is sent when each job has completed a stage. When I receive this
> message I need to recreate a job object, inspect the results of processing
> and then call a method to start the next stage of processing.
>
> There's some common attributes -- after submitted every job has a unique
> job_id, and they all have a DIBx::Class row object. They also to have
> connections to backend processing servers, etc. But, each stage should
> have its own set of methods for dealing with just that one stage.
>
> One approach is to create a base class with common methods and then create
> individual classes for each stage. So, when I get a message that Stage #2
> has completed I might inspect the message to decide on the stage completed
> and then:
>
> my $class = 'Job::State::' . $message->{stage}; # stage1, stage2
> my $job = $class->new;
>
> Another approach is to have just a single class ( my $job = Job->new ) and
> then based upon state indicated by the message apply a role to that job
> instance that has the methods needed for handling the transition from one
> state to the next.
>
> I think what I'd like best is to do is:
>
> my $job = Job->new( $message );
>
> and have the $job essentially "know" what state it is in and only support
> methods for that state.
>
>
> Anyone have any guidance on how to structure classes like these?
This sounds like you really just want Job to be a factory instead.
package Job;
sub new_from_message {
my $class = shift;
my ($message) = @_;
my $job_class = 'Job::State::' . $message->{stage};
return $job_class->new;
}
The individual state classes can use roles to share implementation if
you want, but I don't think this necessarily requires runtime role
application if you already have the classes written.
-doy