Lets say I use Dependency Injection and don't use a DI framework. So the injection is direct rather automatic. How I should handle the logger class? All the objects, (thousands) should have a Logger reference in their constructors? (We don't consider Singletons and Service Locater as they hide the dependency, and are pathological liars.)

  • As you don't use a framework you're in the plesent position of being able to use DI when it makes sense and not when it doesn't. So does DI give you anything here? If not don't use DI for this. – Richard Tingle Oct 18 '15 at 20:09

How I should handle the logger class?

You should instantiate it and inject it into stuff that needs it.

All the objects, (thousands) should have a Logger reference in their constructors?

So what? If those objects need to log, then they need to get that dependency somewhere.

I would argue that have such pervasive dependencies is a smell, even for logging.

|improve this answer|||||

You basically have two options.

Use the composition relationship

You would't pass a class implementing a Log interface to a class, but you would create an abstract class where, in its constructor, you directly initialize it's protected Log member with new instance of your class implementing the Log interface.

All classed which need to use the logger will then inherit this class and if you at any time in the future need to change the procedure of loggin mechanism, you can just swap out the one new in your base abstract class to a new logger and the change will be propagated throughout all your classes.

Use static methods

Logging is such a simple task, it produces no side effects. It merely opens a stream to log (be it a database or a file) and flushes the log contents there.

Because of its simplicity, logger can go into the utilities package.

However, there is one problem. If you, at any time in the future, decide, you want to change the way processes are logged, you will have to alter the logger class and its logging methods. In this process you are either very likely to lose the initial logging mechanism or going to comment out code for the initial procedures, which will make your code messy.

Where I work, we use the first approach - a simple logging interface, containing methods like logInfo or logError and have classes implement the interface.

Even though we usually restrain from the composition relationship, because it is hard to mock, the logger class, as I have said, is so simple, we have made an exception for it, because we still like it a tad more than having a static logger.

|improve this answer|||||
  • This is a terrible idea that will make any unit tests brittle and slow. – RubberDuck Oct 18 '15 at 21:56
  • @RubberDuck Why would the tests be brittle and slow? We have been using the approach for quite some time and have yet to have problems with it. – Andy Oct 19 '15 at 7:58
  • Because you have no way to swap out your logging mechanism with one that doesn't hit the file system or a database. – RubberDuck Oct 19 '15 at 11:29
  • @RubberDuck of course you do, it's just only possible on a global basis. The question then becomes is that what you want. Everything is a trade off and there are few absolutes – Richard Tingle Oct 19 '15 at 11:33
  • 1
    @rubberduck you don't literally change the code, part of your test start up makes some calls that turn off logging globally (this is exactly the same as a DI framework but the DI framework pretends this isn't what it's doing) – Richard Tingle Oct 19 '15 at 13:31

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.