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

While I didn't comment in that thread, my sympathies went with jbert at Re: how to make a universally inherited method?. In particular I fail to see what using singletons in this case really buys you over using strict.pm and exporting variables from a configuration module using Exporter. (Other than buzzword compliance that is.)

There are valid uses of a Singleton pattern where it is a win. If producing your variable is expensive, and so you want to do it lazily, then Singletons are great. They are then basically an OO way of expressing memoization. But for just expressing configurations, what is the big win supposed to be?

  • Comment on Re (tilly) 2: Use globals or pass around everything under the sun?

Replies are listed 'Best First'.
Re: Re (tilly) 2: Use globals or pass around everything under the sun?
by lachoy (Parson) on Dec 04, 2001 at 18:42 UTC

    It's probably just me, but I find exporting variables for configuration purposes just as bad as a global variable. I hate polluting namespaces except for CONSTANTS, even when the coder asks for it, and always fully qualify all non-method subroutine calls. Paranoid? Maybe, but I think it's made my code easier to understand down the road.

    As you said, it's basically the same thing as exporting a variable but with an extremely lightweight wrapper around it that explicitly tells you (the maintainer twelve months down the road after the original programmer has left) there's only one configuration object out there. TMTOWTDI.

    Chris
    M-x auto-bs-mode

      In one sense, of course it is just as bad. It is a global. Same thing. Same problem. Sharing data across boundaries. As I point out in another post, passing by reference is also the same problem, same reasons, except that you have no opportunity to be explicit about what you are sharing, and have no opportunity for typo checks in your usage.

      But there is a big benefit that you seem to have completely missed. The point of exporting functions etc is that it makes it much easier to rewrite code. You don't make any assumptions about where things are actually implemented, you just assume that they are available to you. And that means that if some functions in your package turn out to make more sense in another, you can go ahead and move them with very little editing.

      You may think you are being careful by fully qualifying every function you use. I look at that and say that you are wasting a lot of typing to spread assumptions about where functions are implemented as widely in your code as you can. That is wasted typing for something that I consider a negative, not a benefit.

      Now I am not saying to turn around and export everything. Export reasonably. Always through @EXPORT_OK so that people have to be explicit about where things came from. But exporting functions can be a good thing. Exporting variables, while not great, is often the best of bad choices. Being painfully explicit is just being painfully explicit. It may or may not be good, whether it is in any particular case is a judgement call.

        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

      I don't think that tilly is advocating that anyone design for exported configuration variables, and I'm not, either.

      However, in the case that you're attempting to follow the rules and take spaghetti code and refactor it, yet keep the code in production up and running ... using a common module(s) that contains your configuration stuff is a very good step. It clarifies stuff and allows you to proceed forward in removing the globals with as much knowledge as you could have.

      ------
      We are the carpenters and bricklayers of the Information Age.

      Don't go borrowing trouble. For programmers, this means Worry only about what you need to implement.

Re: Re (tilly) 2: Use globals or pass around everything under the sun?
by dragonchild (Archbishop) on Dec 04, 2001 at 18:28 UTC
    When I supported the use of singletons in that thread, it was to say that anything is better than a bunch of globals. What I was proposing was exporting wrapper functions using Exporter. I also don't know the definition of a singleton, so I was guessing from context. I think I guessed wrong. :-)

    ------
    We are the carpenters and bricklayers of the Information Age.

    Don't go borrowing trouble. For programmers, this means Worry only about what you need to implement.

      The Singleton pattern is really quite simple. What you do is have a class with a private constructor that nobody ever calls. The public constructor calls the private constructor only on the first time it is called, memoizes the answer, and hands it back every time after that.

      The result is a class which will only have a single instance no matter how many places you ask for it. (The trick isn't in figuring out how to do it, it is in figuring out when doing it is a really useful thing...)