4

I am pursuing object oriented design. So we don't want to use globals but yet sometime we have a module that most other modules use. This means we have to just pass it to all other modules and this can be literally all modules!

class Logger
{
public:
    Logger(void);
    ~Logger(void);
};


class Calculator
{
public:
    Calculator(Logger *logger);
    ~Calculator(void);
};


class Taxation
{
public:
    Taxation(Logger *logger);
    ~Taxation(void);
};

So the idea is that the Calculator and Taxation modules use the Logger module to log everything. Similarly most other modules will use it too, and logging is required everywhere. Is this method okay or should Logger be global instead?

migrated from codereview.stackexchange.com Mar 14 '14 at 20:40

This question came from our site for peer programmer code reviews.

4

Avoiding global variables (and singletons, that are global variables in disguise) is a good thing to strive for. The most important is not to think about it as global and singletons being impure OO, that doesn't get you anywhere. The important concept to keep in mind is 'dependencies'. Any dependency that is explicitly injected into the client is loosely coupled. Any dependency that is invisible from the outside of the client is tightly coupled. Yes, it takes more code to explicitly inject dependencies, but your code ends up being more flexible, more testable and also easier to reason about.

In C++, if you can, inject your dependencies as template parameters. If that isn't an option, consider using std::function. Passing by raw pointer isn't a good idea, but you could consider using a const reference.

B.t.w, a while ago resulting from a linkedin discussion I created a logging library (that later others contributed to) excactly for the reason that in logging libraries the singleton pattern is grocely overused. There is no need to use singletons (or global variables) for things like a logging library.

http://pibara.github.io/libKISSlog/

In other situations, singletons are often used in resource management scenario's. This blog post on an alternative to global variables and singletons for scarce-resource allocation, may be useful:

http://minorfs.wordpress.com/2013/01/18/raiicap-pattern-injected-singleton-alternative-for-c/

3

It would be better if you define the Logger as a Singleton instead of passing the object on each class.

Define the Logger like:

class Logger
{
  private:
    Logger()
    {
        //private constructor
    }
  public:
    static Logger& sharedInstance()
    {
        static Logger singleTon;
        return singleTon;
    }
    ~Logger()
    {
       // Cleanup
    }
};

Wherever you need logger, get it like:

Logger::sharedInstance();
  • 3
    Singletons are just a global in disguise. – Doval Mar 14 '14 at 20:57
  • 1
    @Doval: that's true, but sometimes a global is the most pragmatic solution. – Doc Brown Mar 14 '14 at 22:23
  • 1
    Specifically when it comes to loggers, singletons seems to be the best practice (or at least most common). Either that, or a static factory (which probably uses a singleton somewhere within it). – Simon Forsberg Mar 15 '14 at 1:07
  • 1
    Singeltons should not be used in isolation. You need to combine the singelton with a creation pattern (pick any Factory is common) so that you are not tied to the same code for production/testing or other situations. – Martin York Mar 15 '14 at 17:29
  • 1

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.