From: Robert Dober Date: 2008-06-26T00:02:44+09:00 Subject: Re: Is it ellegant to use a global variable to store a Logger object? On Wed, Jun 25, 2008 at 3:36 PM, Andrea Fazzi wrote: > Robert Dober ha scritto: >> >> On Wed, Jun 25, 2008 at 11:22 AM, Robert Klemme >> wrote: >> >>> >>> 2008/6/24 Iñaki Baz Castillo : >>> >>>> >>>> El Martes, 24 de Junio de 2008, Andrea Fazzi escribió: >>>> >>>>> >>>>> require 'logger' >>>>> >>>>> class Container >>>>> def logger >>>>> @logger ||= Logger.new STDOUT >>>>> end >>>>> def foo >>>>> Foo.new(logger) >>>>> end >>>>> end >>>>> >>>>> class Foo >>>>> def initialize(logger) >>>>> @logger = logger >>>>> end >>>>> def bar >>>>> @logger.info('Foo#bar invoked.') >>>>> end >>>>> end >>>>> >>>>> c = Container.new >>>>> c.foo.bar >>>>> >>>> >>>> That's a cool solution :) >>>> >>> >>> I do not think so. Reasons: it clutters every instance with a >>> reference which can have a significant impact on memory if there are a >>> lot objects. Then, you have to change a class's #initialize signature >>> for all classes that do want to do logging and also manually code the >>> assignment inside the class. Accessing a logger from a global context >>> (whichever way you do it) saves memory and is less tedious. >>> >>> Kind regards >>> >>> robert >>> >>> >>> >>> -- >>> use.inject do |as, often| as.you_can - without end >>> >>> >>> >> >> Could not agree more with you. May I add some other reasons. >> This approach vioaltes principles we regard rather highly on this list >> It is not DRY, you are really repeating yourself and in case of the >> metaprogramming solutions you let Ruby repeat itself. >> It is just much less simple than necessary. >> You spread code dependencies all over the place, as a matter of fact >> the expression "dependency injection" says it allready it is almost as >> putting a virus (with constructive behavior) into your code, but can >> you imagine how much more work refactoring will become? >> >> My order of preference would be >> 1. $logger or $LOGGER >> 2. Logger >> >> 43. Kernel::log (or Object.log) >> >> Cheers >> >> >> >> >> > > Hi Robert, > > I would known if, in your opinion, DI is not DRY in general or you are > referring to the particular case of logging. Moreover, which are alternative > DRY solutions to DI that guarantees loose coupling between objects? > > Andrea > > > I am by no means qualified to judge DIin general and I have to admit that my wording might have been indeed to offensive. Scusa per questo. It is however intriguing to me when dependency injection is a good solution. I am sure that there is plenty space for its application, maybe even for logging in a context more specific than the one given by OP. I believe that the main concern would be the loose coupling of objects, IIUC you would need a Container method for each class *and* each class would need to have an adapted initialize method, well that just really seems too much work to me. Maybe I shall answer Robert's question at the same time ;) 41. A logging mixin module MyLogger logger = Logger::new $stderr define_method :log do logger end end now all you have to do is to do include MyLogger in all your classes and it is sufficient to change the MyLogger module once only, that of course has not yet any advantage over using a global logger variable or constant. But you might have much more flexibility by generalizing the approach above as follows module MyLogger logger1 = ... logger2 = ... class << self; self end.module_eval do define_meyhod :included do |into_module| logger = case into_module when Type1Module logger1 when Type2Module logger2 else Logger::new $stderr end into_module.module_eval do define_method :log do logger end end* That would give you pretty easy central control of logger capabilities on one single point of your project in a more transparent way. Actually DI makes him carry quite a have load, does it not? Cheers Robert -- http://ruby-smalltalk.blogspot.com/ --- Les mêmes questions qu'on se pose On part vers où et vers qui Et comme indice pas grand-chose Des roses et des orties. - Francis Cabrel