Beefy Boxes and Bandwidth Generously Provided by pair Networks
P is for Practical
 
PerlMonks  

Advice on style

by Anonymous Monk
on Nov 25, 2010 at 14:09 UTC ( [id://873643]=perlquestion: print w/replies, xml ) Need Help??

Anonymous Monk has asked for the wisdom of the Perl Monks concerning the following question:

Hi monks,

I'm wondering if I should put the 'require Exporter' and related statements before the 'use' statements or the other way round:

# Exporter before use package Module1; require Exporter; our @ISA = qw(Exporter); our @EXPORT = qw(&fn1 &fn2); use Module2; use Module3; # use before Exporter package Module1; use Module2; use Module3; require Exporter; our @ISA = qw(Exporter); our @EXPORT = qw(&fn1 &fn2);

Is there any style that I should adopt here?

Replies are listed 'Best First'.
Re: Advice on style
by afoken (Chancellor) on Nov 25, 2010 at 16:21 UTC

    I wouldn't inherit from Exporter at all, so I would get rid of @ISA=qw(Exporter). Exporter can export its own import() function into your module since v5.57 == Perl 5.8.3 (released 2004-01-14), so there is no need to inherit from Exporter any more. I would not use require, because it requires more typing than use and it is processed at runtime, not at compile time. use Exporter 'import'; is all you need to use Exporter's features from your module. Fall back to ...

    use Exporter; use vars qw(@ISA @EXPORT); @ISA=qw(Exporter); @EXPORT=qw( ... );

    ... only if you need to support really old Perl versions.

    Note that there are several Exporter replacements, Sub::Exporter has some very interesting features, but it can export "only" subs, no variables.

    Regarding style, I prefer the following: pragmas first, followed by core and CPAN modules, followed by my own modules (mostly application specific). So, a typical module would look like this:

    package MyApp::Foo; use strict; use warnings; use parent 'MyApp::BaseClass'; # only for OOP classes use Carp qw( croak ); # only when needed use DBI; # only when needed use CGI; # only when needed use MyApp::Tools; use MyApp::Utils; our $SVNID=q$Id$; # SVN expands this li +ne our $VERSION=sprintf('%d',q$Revision$=~/(\d+)/); # SVN expands this li +ne our @EXPORT=qw( ... ); # not for OOP classes, only when needed our @EXPORT_OK=qw( ... ); # not for OOP classes, only when needed our %EXPORT_TAGS=( ... ); # not for OOP classes, only when needed # more globals, if required # subs here 1;

    Alexander

    --
    Today I will gladly share my knowledge and experience, for there are no sweeter words than "I told you so". ;-)
Re: Advice on style
by chrestomanci (Priest) on Nov 25, 2010 at 16:01 UTC

    Firstly, do you need to export anything? If your module has an OO interface, then users will typically do:

    use Your::Clever:Module; my $instance = Your::Clever:Module::new() $instance->some_function();

    Secondly, if you read the POD for Exporter, then near the bottom they list a number of alternatives, many of them look much nicer. Exporter is an old module, and a lot of other stuff has come since, some of it will be better.

    Having said that, I don't think it makes any difference. My gut feeling is that none of it matters until perl gets to the end of your source file (or package), and then considers everything at once. In other words it is just a style thing like tabs vs spaces for indent, and you should do what ever you or your local coding conventions prefer.

    For myself, I am thinking that you have to use or require the exporter module, so it makes sense to put that use along with all the others, and then set-up the exports afterwards, Then again, I have just taken a look at some old perl I wrote about 8 years ago, and it is the other way around. I guess it makes no difference.

      Actually users should never:

      my $instance = Your::Clever:Module::new();

      Instead they should:

      my $instance = Your::Clever:Module->new();

      which works better with inheritance and is more robust against changes to the OO hierarchy.

      True laziness is hard work
Re: Advice on style
by JavaFan (Canon) on Nov 25, 2010 at 16:24 UTC
    It doesn't matter. What happens is:
    1. Some other module or program uses your module.
    2. During its compilation, the perl compiler encounters "use Module1";
    3. This triggers your module to get compiled; while doing so, Module2 and Module3 will get compiled (if not already compiled). Module2->import and Module3->import will be called.
    4. Your module will run. First thing it does is to compile Exporter (if it hasn't been compiled already).
    5. Then Module1->import is called (assuming that other module or program uses "use Module1"). Which means Exporter::import is called.
    6. Exporter::import exports fn1 and fn2 to the calling module or program.
    7. Perl will resume compiling the calling module or program.
    It doesn't matter where you place 'require Exporter'.

    I've never understood why people use the idiom 'require Exporter'. I never do. 'use Exporter();' also compiles Exporter without calling import.

Re: Advice on style
by fisher (Priest) on Nov 25, 2010 at 14:12 UTC
    So, you don't use strict? And no warnings? Expect the inquisitors =)

      Ah, thanks!

      I forgot those two. I suppose they have to go before the line 'require Exporter'? How about the other modules (Module1, Module2)?

Re: Advice on style
by Anonymous Monk on Nov 26, 2010 at 03:31 UTC

    Thanks everyone!

    I didn't know that

    require Exporter; our @ISA = qw(Exporter);
    is outdated code. Have replaced those two lines with "use Exporter 'import';" as suggested.

      I didn't know that require Exporter; our @ISA = qw(Exporter); is outdated code.

      And how should you know that?

      The synopsis of Exporter still (as of v5.63 found on CPAN) has this code as the very first example. The shorter and cleaner use Exporter 'import'; is the second example, and no word in the synopsis explains the differences. Even in the "Good Practices" section linked from the synopsis, all of the examples inherit from Exporter. Importing Exporter::import is explained in just four sentences hidden in "Advanced Features" -> "Exporting without inheriting from Exporter".

      I think the Exporter documentation needs some patches, explaining the difference. It also should tell people not to inherit from Exporter in new code. Perhaps all of the inheritance stuff should be moved to a "legacy usage" section.

      Alexander

      --
      Today I will gladly share my knowledge and experience, for there are no sweeter words than "I told you so". ;-)

        On the other hand, there's something to be said for reading all the documentation of a module you want to use.

        You find little gems like: use Some::Exporting::Module '/./';

        i'm a little late for this threads.. I never understood such thing about Exporter.. anyway the docs have been updated in this while:
        Exporting-Without-Inheriting-from-Exporter

        thanks
        L*
        There are no rules, there are no thumbs..
        Reinvent the wheel, then learn The Wheel; may be one day you reinvent one of THE WHEELS.
        Oh wow, that merits a weekly announcement in perlnews

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://873643]
Approved by marto
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others meditating upon the Monastery: (9)
As of 2024-04-18 10:11 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found