roman has asked for the wisdom of the Perl Monks concerning the following question:
Dear monks,
this is not a serious problem, but I come across its variants quite frequently.
I have a method (say open_for_reading), which accepts hashref of parameters. Since it is quite important method I need all of its parameters to be understood. The open_for_reading method is overriden in a couple of subclasses, each of them understands more parameters.
my $context = $file->open_for_reading( {} ); my $context2 = $file->open_for_reading( { 'path' => $file } ); # OK my $context_derived = $file_derived->open_for_reading( { 'path' => $file, 'join_longca +lls' => 1 } ); # this should fail my $context_derived = $file->open_for_reading( { 'join_longcalls' => 1 + } );
Without the validation the code is something like:
package MyBaseClass; sub open_for_reading { my ($this, $params_ref) = @_; $params_ref ||= {}; return $this->get_context('path' => $params_ref->{'path'} || $this +->path); } package MyDerivedClass; sub open_for_reading { my ($this, $params_ref) = @_; $params_ref ||= {}; my $context = $this->SUPER::open_for_reading(); if ($params_ref->{'join_longcalls'}){ ... modify context } return $context; }
For parameter validation I found Params::Validate from CPAN. The only way I was able to add the validation is like this:
package MyBaseClass; sub open_for_reading_validation_spec { return { 'path' => 0, }; } sub open_for_reading { my ($this, $params_ref) = @_; $params_ref ||= {}; Params::Validate::validate($params_ref, $this->open_for_reading_va +lidation_spec); return $this->do_open_for_reading($params_ref); } sub do_open_for_reading { my ($this, $params_ref) = @_; return $this->get_context('path' => $params_ref->{'path'} || $this +->path); } package MyDerivedClass; use base qw(MyBaseClass); sub do_open_for_reading { my ($this, $params_ref) = @_; my $context = $this->SUPER::do_open_for_reading($params_ref); if ($params_ref->{'join_longcalls'}){ ... modify context } return $context; } sub open_for_reading_validation_spec { my ($this) = @_; return { %{$this->SUPER::open_for_reading_validation_spec}, 'join_longcalls' => 0, }; }
Instead of one method I have three:
I can live with three methods, but besides open_for_reading there are also open_for_writing, open_for_processing, ... so whole interface suddenly "triplicates".
Do you think is there a different solution?
Even without the validation there is a "naming" problem of its own. I have an interface method which does initialization and cleanup, and between these two blocks is a code to be overriden in subclasses.
sub method { my $this = shift; $this->do_some_initialization; $this->do_something_which_can_be_overriden_in_subclasses(); $this->do_some_cleanup; }
I put the inner block into separate method, but I often have problem to name it. Do you use some naming convention for the "executive" methods? Prefixes (do_, exec_)? Postfixes (_body)?
|
|---|
| Replies are listed 'Best First'. | |
|---|---|
|
Re: Method parameters validation and inheritance
by kyle (Abbot) on Sep 18, 2008 at 15:22 UTC | |
|
Re: Method parameters validation and inheritance
by Herkum (Parson) on Sep 18, 2008 at 21:55 UTC | |
by TGI (Parson) on Sep 19, 2008 at 07:09 UTC | |
by roman (Monk) on Sep 21, 2008 at 18:41 UTC | |
|
Re: Method parameters validation and inheritance
by GrandFather (Saint) on Sep 18, 2008 at 11:49 UTC | |
|
Re: Method parameters validation and inheritance
by talexb (Chancellor) on Sep 22, 2008 at 16:27 UTC |