in reply to Re (tilly) 4: Use globals or pass around everything under the sun?
in thread Use globals or pass around everything under the sun?

Trust me, I didn't miss it :-) I agree entirely that it's a judgement call whether to export/import functions, I just didn't make that judgement explicit in the previous post.

So, to be explicit: I very, very rarely use non-class/object methods in my code. So the only areas where I find exporting/importing to be an issue are CPAN modules that export functions: File::Find, File::Path, etc. My reason for this is simple: many of these modules export very generic function names ('find', 'mkpath', etc.), and I find it more instructive to see:

my $user_dir = File::Basename::dirname( $user_file );

versus:

my $user_dir = dirname( $user_file );

If something goes wrong, the second one will have me looking around for sub dirname{}, the first one won't because it's a trusted source. (Then again, you could say that all libraries should be trusted sources -- to that I'd say, depending on the module, I'd trust others before myself :-)

Again, this is two ways of doing the same thing. Instead of exporting a function I use a class or object. So instead of:

use MyModule qw( myfunc ); my $result = myfunc( \%args );

I'd do:

use MyModule; my $result = MyModule->myfunc( \%args );

What 'MyModule' does behind the scenes can be modified without the user ever knowing -- it could be transformed from a simple function to a factory method that creates an object behind the scenes based on \%args or the environment, whatever. And it opens up the possibility for a design where state needs to be maintained between invocations. It's easy to change this to:

use MyModule; my $thingy = MyModule->new( \%args ) my $result1 = $thingy->myfunc( \%overriding_args1 ); my $result2 = $thingy->myfunc( \%overriding_args2 );

So: TMTOWTDI :-)

Chris
M-x auto-bs-mode

Replies are listed 'Best First'.
Re (tilly) 6: Use globals or pass around everything under the sun?
by tilly (Archbishop) on Dec 04, 2001 at 21:19 UTC
    First of all you argument against exporting is only an argument against exporting functions in @EXPORT or through tags. If you only use @EXPORT_OK, then it is easy to find the imported subs - they are in your use line. Finding said function is very easy to do. Just look at the top of your code before you look for "sub foo".

    With the exception of a very few modules that come up so often as to be common knowledge (meaning I make an exception for param() but not much else), I never accept default export lists for exactly that reason.

    As for all of your comments about why classes and objects are good, you can do that within procedural code. I should know because I do. Plus a benefit of using procedural code over OO methods is that you are explicit about usage. It can be tricky to track down whether method foo() is in use, and if so, then where the version in this subclass might be called. And if you think you can get rid of it, but are wrong, you won't discover that until you actually exercise the call (by which point you may have forgotten all about that change.) By contrast with exporting functions it is clear which functions are public, and if you try not exporting something you think is unused, you will find that out very quickly when the other module refuses to compile with a message that indicates the broken assumption exactly.

    Of course OO has other things it does better than procedural code (I do write both), but for the simple task of controlled access to functionality from one place in another, my experience is that (at least in Perl) procedural is a significant win.