When is a logger a dependency?

There are some discussion about whether loggers should get injected into your classes (dependency injection) or if you should use the logger facade (like LogManager.GetLogger<MyClass>()).

The answer rather simple:

As for all classes, dependencies which is mandatory should get injected.

That means that you should inject the logger if the class will fail without it (= not deliver the expected result). If the class can work without a logger: simply use the logger facade.


  • http://www.cuttingedge.it/blogs/steven Steven

    In general, optional dependencies should be injected through property injection. However, when applying the Null Object pattern, there is hardly ever (for normal LOB apps that is) a reason to use optional dependencies: just inject a Null Logger when you’re not interested in logging.

    • http://www.gauffin.org jgauffin

      Allowing nulls in the constructors is imho just as bad as using a service locator in business classes.

      Why? Because it tricks the user into believing that the class requires that object as a dependency when it in fact doesn’t. The only way to know that it’s not is to either inspect the code or read the documentation.

      • http://www.cuttingedge.it/blogs/steven Steven

        I’m not talking about injectin null references, I’m talking about the Null Object Pattern: http://en.wikipedia.org/wiki/Null_Object_pattern. Injecting null references in constructors is indeed a bad thing.

        • http://www.gauffin.org jgauffin

          It’s just semantics.

          You tell by the constructor that the logger is indeed required, but then accept an fake logger which does nothing.

          A logger in the constructor means that the class requires logging. Inserting a null logger (Logger.Empty) will not log anything, hence it’s violating the contract.

          imho null object pattern should be used with care since it violates the contract of the interface that it implements. Do you expect an interface with a Write method to write somewhere, or do you expect it to silently ignore your invocation?

          • http://www.cuttingedge.it/blogs/steven Steven

            It depends on the exact contract of this ILogger interface, but it would be strange if the contract describes that a log records is always written to some store. It is up to the implementation, and the consumer should not care. Most logging frameworks already do this, by ignoring log entries below a certain (configured) severity level. Is that bad too? In a sense a null logger is a logger with the severity level ubove critical (the highest level). Should the consumer care about this? I don’t think so. The consumer just writes to the log. And how is this different than configuring a Logger.Empty to be returned when the consumer uses a static LogManager.Log? In that sense the contract stays the same. You wouldn’t want the consumer to know whether it actually logs, since this would add all kinds of check logic into the consumer, which is nasty.

            When a consumer writes to a log, that is logic you want to test. However, when you use a static facade, you make testing harder, since you need to change the logger implementation in the test setup (and need to deal with thread-safety). This hard dependency on the LogManager is unneeded, since you can just inject an ILogger.

  • http://www.gauffin.org jgauffin

    Allowing nulls in the constructors is imho just as bad as using a service locator in business classes.

    Why? Because it tricks the user into believing that the class requires that object as a dependency when it in fact doesn’t. The only way to know that it’s not is to either inspect the code or read the documentation.

  • http://www.gauffin.org jgauffin

    Heh, No more “Reply” links.

    No. A contract is a contract. A method named “Write” should write. The same should apply to logging interfaces. Well. That’s the general rule of thumb.

    I do think that it’s OK that log facades return a NullLogger. They do it to reduce complexity then fetching a logger. But that’s not the same thing as taking a logger through the constructor.

    Injecting the logger in the constructor is another thing. Constructors is always used to force dependencies. Hence the class requiring a logger in the constructor says “Hey dude, I MUST have a logger”. So giving it a logger which doesn’t log is a violation.

    This isn’t really about logging but that constructors should indicate when something is required. If the logger is a dependency (i.e. the class won’t work with it) fine: Pass it in the constructor. But then make sure that the logger do actually log.

    Your last paragraph. Exactly my point. In that case the logger is mandatory, hence it should be passed in the constructor. And that class should never get a null logger. But seriously, how often do we write applications that REALLY require logging? Financial applications might, but the average application?

    Do you get the difference?