I'm interested in opinions on the use of FP (functional-Perl, ie: non-OO) routines exposed to consumers of an otherwise OO-module. Given that this is almost completely a style preference, I've chosen to Meditate on it. See the concept code below for an idea what's involved. While the examples are terse, the idea is to expose package-configs, possibly defaults to constructor use, or any package-wide tuning a module may support.
As I see it, there are 3 potential options:
#1 above is what my code samples use, and seems to best represent what the routine does. On the other hand, callers now need to remember if they're invoking an FP routine verses a method/constructor.
#2 is basically the same, but lets consumers be lazy and use the infix operator in all cases. This might be written in the module as:
sub conf { shift; # throw away unused class. # .. do real work here }
#3 would make callers always provide every default option (or not have any say in configuring other package-level adjustments.) Perhaps the callers re-use lengthy/common constructor arguments like so:
I'm not really fond of making callers do extra work if it's considered likely that use of a particular library might wish to set sensible defaults throughout use of the module. Further, this means package-config (not used by constructors) could only be adjusted by reaching into something like $Ex::Mod::DefaultTimeout to enact changes, which also feels messy.my %re_use = (name => 'Alice'); Ex::Mod->new( override=>'whatever', %re_use );
Below is the example consumer, and the example Ex::Mod class:
consumer.pl
use strict; use warnings; use lib '.'; require Ex::Mod; Ex::mod::conf( user => 'Alice' ); my $a = Ex::mod->new(); # Presumably more constructor use wanting user=>'Alice' goes here.. my $b = Ex::mod->new( user=>'Bob'); printf "User a is: %s\n", $a->whoami(); printf "User b is: %s\n", $b->whoami();
Ex/Mod.pm
package Ex::mod; use strict; use warnings; # package-scoped config. my %conf = ( user => undef, ); # config routine. NB: FP! # <class>::conf( 'key' => 'value' ); sub conf { my %c = ( @_ ); for (keys %c) { $conf{$_} = $c{$_} if exists $conf{$_}; } } # new(), the constructor. sub new { my $class = shift; $class = ref($class) || $class; # subclass boilerplate. my %opts = ( @_ ); my $self = { user => $opts{user} // $conf{user} // '', }; return bless $self, $class; } # whoami() - method to say who this object's user is: sub whoami { my $self = shift; return $self->{user} // undef; }
|
|---|
| Replies are listed 'Best First'. | |
|---|---|
|
Re: OO APIs and FP interfaces
by Your Mother (Archbishop) on Dec 04, 2015 at 02:13 UTC | |
by Discipulus (Canon) on Dec 04, 2015 at 09:28 UTC | |
|
Re: OO APIs and FP interfaces (storage scope)
by tye (Sage) on Dec 04, 2015 at 15:27 UTC | |
by Apero (Scribe) on Dec 04, 2015 at 15:55 UTC | |
|
Re: OO APIs and FP interfaces
by choroba (Cardinal) on Dec 04, 2015 at 13:45 UTC |