Perl module class method vs regular routine

So I was wondering if there is a difference in use between a Perl class method and a regular routine from a standard module. Is there a time when you will use one over the other? In this example, I assume that no object methods are present in any of the modules.

A quick little main class here:

#!/usr/local/bin/perl use strict; use warnings; use Foo; use Bar; my $arg1 = "blah"; my ($str1, $str2); $str1 = Foo::subroutine($arg1); $str2 = Bar->subroutine($arg1); exit(0); 

Foo package will contain my regular routine call

 use strict; use warnings; package Foo; sub subroutine { my $arg = shift; my $string = "Ordinary subroutine arg is $arg\n"; return $string; } 1; 

The batch panel will contain a class method call

 use strict; use warnings; package Bar; sub subroutine { my $class = shift; my $arg = shift; my $string = "Class method arg is $arg\n"; return $string; } 1; 

Usually, if I write Perl code, I would just use the class method parameter (for example, the Bar example), but I began to reflect on this issue after reading the code from a former employee who used the syntax, as in the Foo example. Both seem to do the same in their essence, but seem to do more than they seem at first glance.

+5
source share
3 answers

The solver is whether your Module object-oriented module or not.

  • If Module is just a container for a set of routines, I would expect it to use Exporter and suggest importing a subset of its routines into the namespace. Example: List::Util

  • On the other hand, if there is a Module::new constructor, and the intention is to use it in the OO wizard, then you should not mix simple routines with methods (except, perhaps, for private routines that the module uses internally). Example: LWP::UserAgent

Therefore, I would expect that the sources would be recorded as one or the other of them, and not a mixture between them. Of course, there are always situations where a rule of thumb should be ignored, but in this case nothing comes to mind.

Foo.pm

 use strict; use warnings; package Foo; use Exporter 'import'; our @EXPORT_OK = qw/ subroutine /; sub subroutine { my ($arg) = @_; "Ordinary subroutine arg is $arg\n"; } 1; 

Bar.pm

 use strict; use warnings; package Bar; sub new { my $class = shift; bless {}, $class; } sub subroutine { my $class = shift; my ($arg) = @_; "Class method arg is $arg\n"; } 1; 

main.pl

 #!/usr/local/bin/perl use strict; use warnings; use Foo 'subroutine'; use Bar; my $arg1 = "blah"; print subroutine($arg1); print Bar->subroutine($arg1); 

Exit

 Ordinary subroutine arg is blah Class method arg is blah 
+3
source

There is nothing wrong with a regular routine. They do what they have designed to do very well.

Methods, on the other hand, perform all the same actions and play great with any class that inherits from yours.

So ask yourself:

  • Do you expect / allow / encourage people to write classes that inherit from your module?
  • Is your module a more complex data structure that works well as an object?

or

  • Is your module a library of utilities that work with basic data types?

There is a lot of room for this in this world, but if you find yourself, like you, in Bar , ignoring $class (or more often $self ) in the whole module, then perhaps you are too far away, designing them as methods. More importantly, anyone trying to inherit your minimal OO "class" will be a rude surprise when your methods cannot distinguish between the two classes ...

+2
source

It is rather a matter of code paradigm.

There is absolutely nothing wrong with a non-object oriented approach to your code. It works and it works well.

However, object orientation provides a bunch of advantages that are worth considering - and if they want something, go for the OO route.

In particular, objects provide encapsulation. It's a lot easier for me to write a module, and you just use it. See, for example, LWP::UserAgent for an example:

  require LWP::UserAgent; my $ua = LWP::UserAgent->new; $ua->timeout(10); $ua->env_proxy; $ua->agent('Mozilla/5.0'); my $response = $ua->get('http://search.cpan.org/'); if ($response->is_success) { print $response->decoded_content; # or whatever } else { die $response->status_line; } 

Now you can do all of the above with the help of inherited routines. But if you want to make multiple sets of multiple pages, you will have to either:

  • Create a subsection in which all the parameters necessary for you were involved - including returning in some way "success / failure / result" - perhaps in an array?
  • Otherwise, the "state" will be hidden in your external module.

OO is simply a tidier, more understandable way to do this. (There are other benefits to doing OO, and I'm sure you could google it).

+1
source

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


All Articles