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