Is there any way in perl to import variables from the main script to the module?
Here is my main.pl:
#!/usr/bin/perl -w
use DBI;
our $db = DBI->connect(...);
__END__
Now I want to use the $db variable in my modules, because I want to avoid duplicate connections and duplicate codes... It is possible?
You can do that by referring to $main::db in other packages. The main namespace always point to globals in the primary namespace if there is none other given. You should read up on package.
Note that this is not a very good idea as your modules will be dependent on main having the connection. Instead, you should construct your objects in a way that let you pass a database handle in. If you require a db connection at all cost, either let them throw an exception or create their own db handle.
If you are not using OO code, make the database handle an argument of every function call.
Also note that it's best practice to name the database handle $dbh.
Let's look at this for non-OO (Foo) and OO (Bar).
# this is package main (but you don't need to say so)
use strictures;
use DBI;
use Foo;
use Bar;
my $dbh = DBI->connect($dsn);
Foo::frobnicate($dbh, 1, 2)
my $bar = Bar->new(dbh => $dbh);
$bar->frobnicate(23);
package Foo;
use strictures;
sub frobnicate {
my ($dbh, $one, $two) = #_;
die q{No dbh given} unless $dbh; # could check ref($dbh)
$dbh->do( ... );
return;
}
package Bar;
use strictures;
sub new {
my ($class, %args) = #_;
die q{No dbh given} unless $args{dbh};
return bless \%args, $class;
}
sub frobnicate {
my ($self, $stuff) = #_;
$self->{dbh}->do(q{INSERT INTO bar SET baz=?}, undef, $stuff);
return;
}
__END__
You can always pass a db handle into a method. I'm not a fan of this approach, but we have code that functions using this approach.
The problem IMHO is in the debugging. It makes it difficult to know anything about the db handle itself from the code in your module, though that might not be an issue for you. Imagine, however going in to debug code that uses a db handle, but you have no idea where it came from. If you get your db handle from a method in your class, you can trace it to that subroutine and immediately you have some information. This is definitely my preferred way of doing things.
If you do pass in a DB handle, you should do some input validation, such as checking for $dbh->isa('DBI::db') (I think that's the class into which db handles are blessed).
My preference, however would be to have a subroutine in your class that gets the db handle, either based on information you pass in, or by information in the sub itself. One thing to consider is that if you're using DBI, the connect_cached() method is very helpful. From the DBI docs:
connect_cached is like "connect", except that the database handle returned is also stored in a hash associated with the given parameters. If another call is made to connect_cached with the same parameter values, then the corresponding cached $dbh will be returned if it is still valid. The cached database handle is replaced with a new connection if it has been disconnected or if the ping method fails.
Using db handle caching of some sort will, regardless of whether you were to have created the db handle in your script or in the class, give you the same connection.
So, I recommend creating a method in your class that takes all of the parameters required to replicate the creation of the db handle as you'd do it in your script, and consider using connect_cached, Apache2::DBI or something that will handle the db connection pooling/abstraction.
Related
We have a few Third Party Perl libraries for transferring files to/from, and encrypting/decrypting files using PGP, among other things. Currently, these libraries use redundant code, and execute the above-mentioned methods using system() and command-line binaries.
I'm looking to re-write these libraries, using more modules and OOP where necessary. I'm currently racking my brain about how I want to setup the main library, which Perl scripts would include to use Net::SFTP to put/get files, and Crypt::PGPSimple to encrypt/decrypt files.
Should a library module be written in OOP? Does that make sense? Or should methods be imported (and designed procedurally) as needed, and create Net::SFTP and Crypt::PGPSimple objects as necessary? I'm just not sure I want to create a Lib object, and initialize SFTP, PGP, Constants, etc. all in the new sub. I figure I see this type of class more like a Java class with static methods, but there should be only one SFTP object/connection (not sure if Net::SFTP already takes care of this?), and one Crypt::PGPSimple, etc.
Also, back to the redundancy, this library should also have a parent which defines functions which many of the Third-Party libraries use (FTP, PGP, etc).
I'm not looking for a definite answer, as there probably isn't one, but maybe how others approach a design like this, and what makes the most "sense".
Thanks
Update: Added sample code of my OOP Library Module, which also utilizes other objects (PGPSimple, SFTP). Let me know if you can think of a better design/implementation. Thanks again.
Lib.pm
use Crypt::PGPSimple;
use Net::SFTP;
use File::Copy;
use Log::Log4perl qw(get_logger :levels);
use File::Basename;
my %CONS = (
RECIPIENT => "ClientName";
URL => 'ftp.host.com';
USER => 'user';
PASS => ''; # use subroutine to obfuscate the password
PORT => '22'
HOME_DIR => '/Home';
IN_DIR => '/Incoming';
OUT_DIR => '/Outgoing';
);
my %VARS;
# private member variables
my ($logger);
BEGIN {
%VARS = (
IS_PROD => $L_is_prod ? 1 : 0;
APPS => $ENV{'APPS'};
OUTDIR => $ENV{'OUTDIR'};
TIME_ZONE => $ENV{"TZ"};
);
$logger = get_logger("Lib");
}
sub new {
my ($class, $self) = #_;
$self = {
pgp => _setup_pgp();
sftp => undef; # Don't create SFTP connection until we need it
};
return bless($self, $class);
}
sub _setup_pgp {
my $pgp = Crypt::PGPSimple->new();
$pgp->PgpVersion(6.5.8);
$pgp->PgpExePath("/path/to/pgp-6.5.8");
$pgp->PgpKeyPath("/home/username/.pgp"); # Set this based on environment
$pgp->PublicKey("pubring.pkr");
$pgp->PrivateKey("secring.skr");
$pgp->Password(pp());
$pgp->UserId();
$pgp->PgpTempDir("/tmp/");
$pgp->PgpTimeZone();
$pgp->PgpVerbose(2);
return $pgp;
}
sub _setup_sftp {
# Create SFTP connection
my $sftp;
my ($host, $user, $pass);
$host = $CONS{URL};
$user = $CONS{USER};
$pass = $CONS{PASS};
$sftp = _connect_sftp($host, (user => $user, password => $pass));
return $sftp;
}
sub encrypt {
my ($self, $plain_file) = #_;
my $pgp = $self->{pgp};
$logger->info("Setting \$pgp->PlainTextFile to $plain_file");
$pgp->PlainTextFile($plain_file);
$pgp->PgpFlags("e");
my $result = $pgp->EncryptFile;
if($result != 0) {
$logger->info("Failed to successfully encrypt $plain_file. Error code: " . $pgp->ErrCode() . ", Result: " . $pgp->Result());
}
return $result;
}
sub put {
my $self = shift;
$self->{sftp} = _setup_sftp() if(!defined $self->{sftp});
my $local = $self->{pgp}->EncryptedTextFile();
my $remote = basename($local);
...
$sftp->put($local, $remote)
...
}
I tend to use OO if I need some kind of state for each instance. But I think nothing is bad about a procedural approach, where no "state" is needed.
Concerning the single connection problem: we (my company) use a "service-class" (procedural), which returns a suitable connection - that is useful if using threads / forks or if there can be multiple connections possible (e.g. with different options).
Update: If you decide to go OO, I would strongly recommend using Moose if possible. It will save you a lot of time, work and bugs... Have a look, how blessed references work, but use Moose or Mouse for your code.
If it makes sense to organize your data and subroutines that way, take a look at Moose, which adds a lot of OOP semantic glue to Perl 5, including inheritance.
Design the interface whichever way makes the most sense to you, anyone else who will be using the module, and the way that you intend to use it. You can even make it dual-interface relatively easily (at least if you don't use Moose; I've never made a dual-interface module with Moose, but I suspect that Moose would fight against you pretty hard if you tried it) by implicitly creating a private instance which procedural calls are run against.
Personally, I tend to go OOP for anything that requires reusable data (state, settings, etc.) for the code to run against and semi-dual-interface (specifically, procedural code which tolerates being called as MyMod->proc_name in addition to MyMod::proc_name) when every call will include all necessary data as parameters.
In this specific case, I think I'd go with a straight OO interface, with one instance of the class per open connection, then perhaps extend it to dual-interface if most apps using it only require a single connection (or perhaps not; I prefer calling things with the OO syntax rather than dealing with exported subs).
I try to intercept nonexistent methods call in some subclass.
Yes, I know about AUTOLOAD,
but (for methods) it try to call parent::method first, then UNIVERSAL::method and only then ::AUTOLOAD.
But I need call (something like) ::AUTOLOAD at first.
Because I want to know what methods subclass try to call from parent.
Give me some advice about it please.
If you just want to know what methods are being used, you can use some profiling module like Devel::NYTProf.
If you want to react to that during your program execution, you can intercept directly the entersub opcode just as the profiling modules do. See the perlguts or profiling module code for more details.
You could probably create a 'Monitor' class with FETCH and EXISTS and tie it to the symbol table hash like: tie %Module::Name:: , Monitor;
But unless we know exactly what you are trying to do and why, it's hard to guess what would be the right solution for you.
Please heavily consider Jiri Klouda's suggestion that you step back and reconsider what you are trying to accomplish. You almost never want to do what you're trying to do.
But, if you're really sure you want to, here's how to get enough pure Perl rope to hang yourself...
The subs pragma takes a list of sub names to predeclare. As tchrist says above, you can predeclare subs but never actually define them. This will short-circuit method dispatch to superclasses and call your AUTOLOAD immediately.
As for the list of sub names to pass to the pragma, you could use Class::Inspector->methods (thanks to Nic Gibson's answer for teaching me about this module).
According to brian d foy's comment to Nic Gibson's answer, Class::Inspector will not handle methods defined in UNIVERSAL. If you need to do those separately, you can get inspiration from the 'use subs' line in my Class::LazyObject module.
Why not create an AUTOLOAD sub in the sub-class package which 1) reports the missing method and then 2) dispatches the call to the parent. For this to work you don't defined #ISA in the sub-class.
Something like:
package my_parent;
sub foo { warn "in my_parent::foo" }
package my_subclass;
my $PARENT_CLASS = "my_parent"; # assume only one parent
# Note: no #ISA defined here
sub AUTOLOAD {
warn "non-existent method $AUTOLOAD called\n";
my $self = shift;
(my $method = $AUTOLOAD) =~ s{.*::}{};
my $super = $PARENT_CLASS . '::' . $method;
$self->$super(#_);
}
package main;
my $x = bless {}, 'my_subclass';
$x->foo;
The syntax: $self->$super(#_) where $super has double-colons in it tells perl in which package to start looking for the method, e.g.:
$self->my_parent::foo(...)
will look for the foo method starting in the package my_parent regarless of what class $self is blessed into.
I want to make some tests on my modules.
Unfortunately, some functions in these modules use hardcoded configurations files.
package My::Module;
use strict;
use warnings;
use Readonly;
Readonly my $CONF_FILE => '/my/conf_file.xml';
=head1 FUNCTIONS
=head2 Info($appli)
Returns Application Information
=cut
sub Info
{
my $appli = shift;
my $conf = MyXML::Read($CONF_FILE);
foreach my $a (ARRAY($conf->{application}))
{
return ($a) if ($a->{name} eq $appli);
}
return (undef);
}
[some others functions that use this config file...]
The solution that came to my mind is to create a new function in each module that will change this default config file when I need it.
Then I will use that function in my tests...
Do you have any other (better ?) ideas ?
Well, the proper thing for me to tell you would be "don't use hard coded paths". It'll come back and bite you at some point in the future, I promise.
But... assuming you're resolved to using them, there are a number of ways to allow an override. You're right you could add a function that would let you change it, or you could use an environmental variable:
Readonly my $CONF_FILE => $ENV{'MY_CONF_FILE'} || '/foo/bar';
But the right thing to do is still to allow for other items to be passed in properly if you have a choice.
I'm finding it very convenient to pass configuration and other data that is read or calculated once but then used many times throughout a program by using Perl's use mechanism. I'm doing this by exporting a hash into the caller's namespace. For example:
package Myconfiguration;
my %config;
sub import {
my $callpkg = caller(0);
my $expsym = $_[1];
configure() unless %config;
*{"$callpkg\::$expsym"} = \%config;
}
and then in other modules:
use MyConfiguration (loc_config_sym);
if ( $loc_config_sym{paramater} ) {
# ... do stuff ...
}
However, I'm not sure about this as a best practice. Is it better to add a method that returns a hash ref with the data? Something else?
If you only want to read the values of %config, then why not have a routine to do it for you?
my %config;
sub config_value
{
my ($value) = #_;
return $config{$value};
}
You could export this by default if you wanted to:
package Mypackage;
require Exporter;
#EXPORT = qw/config_value/;
The reason that I would not allow access to the hash all over the place in lots of different modules is that I would have a hard time mentally keeping track of all the places it was being used. I would rather make the above kind of access routine so that, if some bug happened, I could add a print statement to the routine, or something, to find out when the value was being accessed. I don't know if that is related to "best practices" or it is just because I'm stupid, but the kind of confusion created by global variables scares me.
There's no reason you can't have a set routine too:
sub set_value
{
my ($key, $value) = #_;
$config{$key} = $value;
}
I think it's better to work with a copy of the config hash. This way, if you modify some elements, this won't affect the rest of your code.
I usually use simple object (optionally Singleton) for this with a single method like get_property().
I suggest never exporting variables. Create a class that can return a reference to a private variable instead. People can then store it in a variable with whichever name they like, and only when they decide they want to use it.
In general, it's best to let the user decide whether or not to import symbols. Exporter makes this easy. Writing a custom import method to let the user decide what to name imported symbols can be useful on rare occasions but I don't think this is one of them.
package MyConfiguration;
require Exporter;
our #ISA = qw(Exporter);
our #EXPORT_OK = qw(Config);
our %Config;
And then, in your script:
use MyConfiguration;
print $MyConfiguration::Config{key};
or
use MyConfiguration qw(Config);
print $Config{key};
Can you intercept a method call in Perl, do something with the arguments, and then execute it?
Yes, you can intercept Perl subroutine calls. I have an entire chapter about that sort of thing in Mastering Perl. Check out the Hook::LexWrap module, which lets you do it without going through all of the details. Perl's methods are just subroutines.
You can also create a subclass and override the method you want to catch. That's a slightly better way to do it because that's the way object-oriented programming wants you do to it. However, sometimes people write code that doesn't allow you to do this properly. There's more about that in Mastering Perl too.
To describe briefly, Perl has the aptitude to modify symbol table. You call a subroutine (method) via symbol table of the package, to which the method belongs. If you modify the symbol table (and this is not considered very dirty), you can substitute most method calls with calling the other methods you specify. This demonstrates the approach:
# The subroutine we'll interrupt calls to
sub call_me
{
print shift,"\n";
}
# Intercepting factory
sub aspectate
{
my $callee = shift;
my $value = shift;
return sub { $callee->($value + shift); };
}
my $aspectated_call_me = aspectate \&call_me, 100;
# Rewrite symbol table of main package (lasts to the end of the block).
# Replace "main" with the name of the package (class) you're intercepting
local *main::call_me = $aspectated_call_me;
# Voila! Prints 105!
call_me(5);
This also shows that, once someone takes reference of the subroutine and calls it via the reference, you can no longer influence such calls.
I am pretty sure there are frameworks to do aspectation in perl, but this, I hope, demonstrates the approach.
This looks like a job for Moose! Moose is an object system for Perl that can do that and lots more. The docs will do a much better job at explaining than I can, but what you'll likely want is a Method Modifier, specifically before.
You can, and Pavel describes a good way to do it, but you should probably elaborate as to why you are wanting to do this in the first place.
If you're looking for advanced ways of intercepting calls to arbitrary subroutines, then fiddling with symbol tables will work for you, but if you want to be adding functionality to functions perhaps exported to the namespace you are currently working in, then you might need to know of ways to call functions that exist in other namespaces.
Data::Dumper, for example, normally exports the function 'Dumper' to the calling namespace, but you can override or disable that and provide your own Dumper function which then calls the original by way of the fully qualified name.
e.g.
use Data::Dumper;
sub Dumper {
warn 'Dumping variables';
print Data::Dumper::Dumper(#_);
}
my $foo = {
bar => 'barval',
};
Dumper($foo);
Again, this is an alternate solution that may be more appropriate depending on the original problem. A lot of fun can be had when playing with the symbol table, but it may be overkill and could lead to hard to maintain code if you don't need it.
Yes.
You need three things:
The arguments to a call are in #_ which is just another dynamically scoped variable.
Then, goto supports a reference-sub argument which preserves the current #_ but makes another (tail) function call.
Finally local can be used to create lexically scoped global variables, and the symbol tables are buried in %::.
So you've got:
sub foo {
my($x,$y)=(#_);
print "$x / $y = " . ((0.0+$x)/$y)."\n";
}
sub doit {
foo(3,4);
}
doit();
which of course prints out:
3 / 4 = 0.75
We can replace foo using local and go:
my $oldfoo = \&foo;
local *foo = sub { (#_)=($_[1], $_[0]); goto $oldfoo; };
doit();
And now we get:
4 / 3 = 1.33333333333333
If you wanted to modify *foo without using its name, and you didn't want to use eval, then you could modify it by manipulating %::, for example:
$::{"foo"} = sub { (#_)=($_[0], 1); goto $oldfoo; };
doit();
And now we get:
3 / 1 = 3