Apparently, I'm the only one who ever needs scores of variables passed into a single subroutine

No you are not. BUT pause a moment and think if those variables are just general configuration, settings which can span hundreds of variables. For example, often my subs require a verbosity value and a logger object (or filehandle) to dump debugging information. I can code these two variables into the signature of any sub. And call the sub like: distance($from, $to, $verbosity, $logger). The last two are optional though, if they are undef then it just logs nothing.

Inevitably, at some future time I need to refactor and add another parameter, let's say $timeout, and converting the sub to distance($from, $to, $verbosity, $logger, $timeout). It is a headache to refactor all my code to accommodate this new variable.

In the above, verbosity, logger are optional. The way I handle the complexity is to call them system-wide configuration. And put them into a hash. This hash is created at runtime by reading a configuration file:

$config = { verbosity => 3, logger => new Logger(), ... # hundreds of configuration settings };

And it is now passed around the subs like distance($from, $to, $config). If I need to add a new config variable like timeout, there is no big refactoring. Or, the refactoring is the same but now it is optional and can be done just for those subs that need the new setting, as the needs change.

But then I need to sometimes override a config setting for just one sub, e.g. the timeout. So, why not pass a hash(ref)? Something like this:

$params = { from => ..., to => ..., # override the timeout of the system-wide config timeout => ..., # this is the config read from file config => { verbosity => 3, logger => ..., timeout => 5, ... } }; sub distance { my $params = shift; # the timeout value will be the config's unless # caller passed their own value to temporarily override it my $timeout = exists($params->{timeout}) ? $params->{timeout} : $params->{config}->{timeout} ; ... # similarly, I return back multiple values in a hash(ref) return { errormsg => 'nothing', status => 1, # all OK! distance => 42 }; } # call it my $ret = distance($params); die $ret->{errormsg} unless $ret->{status} == 1;

Now, suppose that a sub needs to save some results for access by other subs to be run later. Well, why not save that into the config under $config->{stash}->{results-of-distance} = { ... }

But what I am showing here is just reinventing the OOP wheel:

# I am skipping some boilerplate package Calc; sub new { my ($configfile, ...) = @_; my $config = read_configfile($configfile); my $internal_data = { config => $config, stash => {} }; # bless etc. } sub distance { my ($internal_data, $params) = @_; # internal_data holds config, # $params holds from, to and anything to override # config just for the life of this call ... # optionally save results to the stash $internal_data->{stash}->{distance} = 42; # return something back return { errormsg => 'nothing', status => 1, # correct distance => 42 }; }

And you use this as:

my $calcobj = Calc->new('settings.config'); my $res = $calcobj->distance({ from => ..., to => ..., # optionally temporarily # override system-wide config setting timeout => ..., });

In the above example you do not have anything global which should be anathema to any programmer.

All data is inside the object, encapsulated so-to-speak. You can have two of those objects running alongside each with a different configuration file. Pass these objects around and you pass: 1) their config data, 2) their state (stash), 3) their logic (subs, algorithms).

I hope that was gentle. Note that I used hashrefs.

bw, bliako


In reply to Re^2: Ordering of parameters - Re^9: Converting Unicode by bliako
in thread Converting Unicode by BernieC

Title:
Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post, it's "PerlMonks-approved HTML":



  • Posts are HTML formatted. Put <p> </p> tags around your paragraphs. Put <code> </code> tags around your code and data!
  • Titles consisting of a single word are discouraged, and in most cases are disallowed outright.
  • Read Where should I post X? if you're not absolutely sure you're posting in the right place.
  • Please read these before you post! —
  • Posts may use any of the Perl Monks Approved HTML tags:
    a, abbr, b, big, blockquote, br, caption, center, col, colgroup, dd, del, details, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, ins, li, ol, p, pre, readmore, small, span, spoiler, strike, strong, sub, summary, sup, table, tbody, td, tfoot, th, thead, tr, tt, u, ul, wbr
  • You may need to use entities for some characters, as follows. (Exception: Within code tags, you can put the characters literally.)
            For:     Use:
    & &amp;
    < &lt;
    > &gt;
    [ &#91;
    ] &#93;
  • Link using PerlMonks shortcuts! What shortcuts can I use for linking?
  • See Writeup Formatting Tips and other pages linked from there for more info.