Larry Wall <[EMAIL PROTECTED]> writes:

> On Wed, Jul 06, 2005 at 11:47:47PM +0100, Piers Cawley wrote:
> : Or you could use a global, but globals are bad...
>
> Globals are bad only if you use them to hold non-global values.
> In this case it seems as though you're just going through contortions
> to hide the fact that you're trying to do something naturally
> global.  You might argue that a singleton object lets you hide the
> implementation of the delegation from the world, but there's really not
> much to implement if you just want to tell the world that whenever the
> world says "LOGGER" the world is really delegating to "LOGGER::DBI".
> Plus if you really need to reimplement you just vector the world
> through "LOGGER::SELECTOR" or some such.

The thing about the version where the language handles the vectoring through
Logger, or whatever, is that you can retrofit such indirection without having
to make sure all your code uses the global. For instance, in the Test::* world,
there's a huge number of test modules that all play nicely because they work
with Test::Harness, and that's fine until you reach the point where you want to
specialize Test::Harness itself (say you want to write a graphical test
runner). With the global variable approach, you have to alter everything that
uses Test::Harness, with an injection approach, you only have to make changes
to Test::Harness itself.

Hmm... thinking about this a little further, the interface I proposed can't be
as automagical as simply loading a class that injects into your injectable
class because said class could well inherit from another injecting class. You
would have to make it a two step process like:

    use InjectableClass;

    use InjectingClass;

    InjectableClass.inject_with(InjectingClass);

What I'm after is another way to hide implementation details from client
classes and allow programmers to write natural code. 

> One nice thing about a variable is that you're guaranteed to
> be able to temporize it:
>
>     temp $*LOGGER = pick_a_logger();

I'm not sure that, in the particular case, that's all that useful. It'd be cool
if, say in a debugging situation, I could say that, from now on, all messages
to Logger from class Foo are actually dispatched to InstrumentedLogger, and
then to turn it off again, but I'm not sure how I'd do that with a global.

    $Package::Name::OUR::*LOGGER = ::InstrumentedLogger

perhaps?

Reply via email to