Best way to add dynamic code to a perl application

I know that specific instances of this question were received before:

Perl Monks also has some good answers:

But I would like to create a reliable way to add functionality to a Perl application, which will be:

  • Effective : if the code is not needed, it should not compile.
  • Easy to debug : an error message, if something is wrong in the dynamic code, should point to the right place in the dynamic code.
  • Ease of expansion : adding new code should be as simple as adding a new file or directory + file.
  • Easy to call : the main application should be able to "add" without any problems. An effective mechanism for checking whether "added" has already been loaded and if it is not loaded will be a plus.

To illustrate this, here are a few examples that could help in a good solution:

  • , . , OpenCart Prestashop, "", ; . .

  • -, HTML . "" , . HTML, - , - , - ..

, .

:

eval `cat $file_with_function`;
if( $@ ) {
  print STDERR $@, "\n";
  die "Errors at file $file_with_function\n";
}

File::Slurp:

eval read_file("$file_with_function", binmode => ':utf8');

, :

if( !defined &myfunction ) {
  die "myfunction is not defined\n";
}

. , .

:

require $file_with_function; # needs the ".pm" extension, i.e. addon/func.pm
$name_of_module->import();   # need to know the module name, i.e. Addon::Func

$name_of_module->myfunction(...);

require eval, $@, .

Module:: Load:

load $name_of_module;

import . , , . ? ?

, , ( , ) Dancer.

. , . , , :

  • . , .
  • .
+4
1

, , . !

, . , , , Perl, . use strict use warnings, . ? :

  • , . , . , , . , .
  • " " , .
  • , . , , , , , . , , - .

?

, Perl, : eval require. , .

eval eval EXPR Perl . , . , , File:: Slurp:

eval read_file("$file_with_code", binmode => ':utf8');
if( $@ ) {
  die "$file_with_code: error $@\n";
}
if( !defined &myfunction ) {
  die "myfunction is not defined at $file_with_code\n";
}

read_file , . , . , $file_with_code :

sub myfunction(...) {
  # Do whatever; maybe return something
}

. , . .

()

, , require. use, , require . require :

my $mymodule = 'MyCompany::MyModule'; # The module name ends up in $mymodule
require $mymodule;

use, require , import. , . :

$mymodule->myfunction($a, $b);

. , . $a $b, $self. , .

require , , , :

eval "require $mymodule";

$@ + . , :

if( $mymodule->can('myfunction') ) {
  die "myfunction is not defined at module $mymodule\n";
}

.pm :

MyCompany
  MyModule.pm

MyModule.pm :

package MyCompany::MyModule;

sub myfunction {
  my ($self, $a, $b);

  # Do whatever; maybe return something
  # $self will be 'MyCompany::MyModule'
}

1;

package , , , MyCompany::MyModule. 1; require, .

, , , , namespace:: clean . , , , . :

package MyCompany::MyModule;

# Definitions by these modules will not be available to the code doing the require
use Library1 qw(def1 def2);
use Library2 qw(def3 def4);
...

# Private functions go here and will not be visible from the code doing the require
sub private_function1 {
  ...
}
...

use namespace::clean;

# myfunction will be available
sub myfunction {
  # Do whatever; maybe return something
}
...

1;

, ?

- . Perl , %INC. use require . use . require . , , %INC , module:: loaded, Perl:

use Module::Loaded;

if( !is_loaded( $mymodule ) {
  eval "require $mymodule" );
  ...
}

, Perl ?

use require Perl @INC , . ( ) PERL5LIB :

use lib '/the/path/to/my/libs';

, , , . :

:: Load:: :

use Module::Load::Conditional qw(can_load);

my $use_list = {
        CPANPLUS        => 0.05,
        LWP             => 5.60,
        'Test::More'    => undef,
};

print can_load( modules => $use_list )
        ? 'all modules loaded successfully'
        : 'failed to load required modules';
+1

Source: https://habr.com/ru/post/1688139/


All Articles