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?

zadane
  • 385
  • 1
  • 3
  • 11

2 Answers2

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/

user1703394
  • 234
  • 2
  • 4
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();
Midhun MP
  • 139
  • 5
  • 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 01: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
  • Would it be preferably to declare member variable in each module in its constructor using this approach or get the instance like this in each member function? Chances are the modules is gonna log in many functions not just one. Alternatively why don't just declare static member functions as well like `Logger::Write("logging on the fly!")` that way we don't even need to access the object? – zadane Mar 18 '14 at 19:26
  • @MartinYork How exactly do you mean "combine the singelton with a creation pattern (pick any Factory is common)"? Do you have an example how that would look like or some more concrete code maybe? That would be awesome. – Ela782 Aug 09 '18 at 13:14
  • 1
    @Ela782: https://softwareengineering.stackexchange.com/a/40374/12917 – Martin York Aug 09 '18 at 17:34
  • @MartinYork Cool, that's awesome, thank you very much! You are awesome. – Ela782 Aug 09 '18 at 19:15