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?