Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

c++: logger class without globals or singletons or passing it to every method

Tags:

Does anyone knows if it's possible to have a class like a logger without :

  • using a singleton or a global (a la std::cout)

  • passing an instance/pointer/reference to every method which needs it

I take the example of a logger class, but I have a few classes in my application which would benefit from this (for example, the undo manager).

There are several issues with every solution :

  • using a singleton is problematic for testing (along with the many reasons it's generaly not a good idea to use one) . It's the same with a global. Furthermore, nothing guarantees there will be only ONE instance in the application, and it's not even a requirement (why not have 2 loggers for example ?)

  • passing it to every object constructor (dependency injection), leads to a lot of boilerplate code, and can be error prone because you have to copy/paste the same code a lot of times. Can one seriously consider having a pointer to a Logger in every single class' constructor ???????

So I was wondering if there is a third alternative, in C++, I never heard of ? To me it sounds like it would require some black magic under the hood, but I've been pleasantly surprised by some techniques I learned in stack overflow that I couldn't find in google, so I know there are some real gurus here ;)

Surprisingly, I found many discussions about how to design singletons, or why should one not use singletons, but I couldn't find a post addressing my issue...

like image 791
Dinaiz Avatar asked May 04 '11 02:05

Dinaiz


People also ask

Should logger be singleton or scoped?

A logger is, perhaps, the most iconic example of a singleton use case.

Why do we need singleton logger?

A singleton is a creational design pattern whose purpose is to ensure that only one instance of a class exists. We want our logger to be a singleton as we only want one logger instance to be running and logging information at any one time.


1 Answers

I would imagine you could do something similar to what is done in Java with the Log4j package (and is probably done with the Log4c version of it):

Have a static method which can return multiple logger instances:

Logger someLogger = Logger.getLogger("logger.name"); 

The getLogger() method isn't returning a singleton object. It's returning the named logger (creating it if necessary). Logger is just an interface (in C++ it could be a totally abstract class) -- the caller doesn't need to know the actual types of the Logger objects being created.

You could continue to mimic Log4j and have an overload of getLogger() that also takes a factory object:

Logger someLogger = Logger.getLogger("logger.name", factory); 

That call would use factory to build the logger instance, giving you more control over what underlying Logger objects were being created, likely helping your mocking.

So there's no need to pass anything into the constructors, methods, etc. of your own code. You just grab the desired named Logger when you need it and log to it. Depending on the thread safety of the logging code you write, you could have what getLogger() returns be a static member of your class so you'd only have to call getLogger() once per class.

like image 78
QuantumMechanic Avatar answered Sep 20 '22 19:09

QuantumMechanic