Dependency Injection vs. Global/Static data

Discussion in 'C++' started by thomas, Sep 2, 2010.

  1. thomas

    thomas Guest

    Hi,

    ----injection---
    class Util{
    public:
    void print(){...}
    };

    class Work{
    void SetUtil(Util* pUtil){m_pUtil = pUtil;}
    Util* m_pUtil;
    };
    ----end----

    ----static----
    class Util{
    public:
    static void print(){...}
    };
    ----------
    What's the advantages/disadvantages when comparing these two methods?
    When I use these two methods in dll interface(Work class inside dll;
    Util may be used by several modules.), anything I need to take special
    care of?
     
    thomas, Sep 2, 2010
    #1
    1. Advertising

  2. thomas wrote:
    > Hi,
    >
    > ----injection---
    > class Util{


    this class is missing base to use it in dependency injection

    > public:
    > void print(){...}
    > };
    >
    > class Work{
    > void SetUtil(Util* pUtil){m_pUtil = pUtil;}
    > Util* m_pUtil;
    > };
    > ----end----
    >
    > ----static----
    > class Util{
    > public:
    > static void print(){...}
    > };
    > ----------
    > What's the advantages/disadvantages when comparing these two methods?
    > When I use these two methods in dll interface(Work class inside dll;
    > Util may be used by several modules.), anything I need to take special
    > care of?


    The 1st method gives you flexibility, while the second is fixed. If you
    provide a base class for Util class, you can easily use another
    implementation later on, and switch between two
     
    Vladimir Jovic, Sep 2, 2010
    #2
    1. Advertising

  3. * thomas, on 02.09.2010 10:14:
    >
    > ----injection---
    > class Util{
    > public:
    > void print(){...}
    > };
    >
    > class Work{
    > void SetUtil(Util* pUtil){m_pUtil = pUtil;}
    > Util* m_pUtil;
    > };
    > ----end----
    >
    > ----static----
    > class Util{
    > public:
    > static void print(){...}
    > };
    > ----------
    > What's the advantages/disadvantages when comparing these two methods?


    There is no polymorphism for either design.

    In the first example you have the option of turning off and on printing. This
    could much more easily be accomplished via a boolean member in 'Work' + an
    internal print method that checks the boolean.

    If you meant for 'print' to be virtual, then the first example offers the
    additional functionality of customizing the effect of 'print'.

    Presumably you know that, and whatever advantage depends on your requirements,
    which you fail to state here. However, if the second example is a possible
    solution for your requirements, then there is no current advantage, only a
    possible future advantage. And in that case it's purely a methodology question,
    "Should one design for possible future requirements?", and off-topic here.

    C++ aspect: for the second example, use a namespace, not a class.


    > When I use these two methods in dll interface(Work class inside dll;
    > Util may be used by several modules.), anything I need to take special
    > care of?


    That's a Windows question, not a C++ question.


    Cheers & hth.,

    - Alf

    --
    blog at <url: http://alfps.wordpress.com>
     
    Alf P. Steinbach /Usenet, Sep 2, 2010
    #3
  4. thomas

    thomas Guest

    I should have provided more information.
    -----base class---
    struct IUtil{
    virtual void print(){}
    };
    ----end-----

    ----injection---
    class Util : public IUtil{
    public:
    void print(){...}
    };

    class Work{
    void SetUtil(IUtil* pUtil){m_pUtil = pUtil;}
    IUtil* m_pUtil;
    };
    ----end----

    ----static----
    class Util{
    public:
    static IUtil* s_pUtil;
    };
    IUtil* Util::s_pUtil = NULL; //Util::s_pUtil = pUtil; (do assignment
    somewhere else.)
    ----------

    From the above code you can see that both provides flexibility. The
    only difference is the implementation methods.
    So any essential difference?
     
    thomas, Sep 2, 2010
    #4
  5. thomas

    Goran Pusic Guest

    On Sep 2, 12:05 pm, thomas <> wrote:
    > I should have provided more information.
    > -----base class---
    > struct IUtil{
    >     virtual void print(){}};
    >
    > ----end-----
    >
    > ----injection---
    > class Util : public IUtil{
    > public:
    >     void print(){...}
    >
    > };
    >
    > class Work{
    >     void SetUtil(IUtil* pUtil){m_pUtil = pUtil;}
    >     IUtil*  m_pUtil;};
    >
    > ----end----
    >
    > ----static----
    > class Util{
    > public:
    >     static IUtil* s_pUtil;};
    >
    > IUtil* Util::s_pUtil = NULL; //Util::s_pUtil = pUtil; (do assignment
    > somewhere else.)
    > ----------
    >
    > From the above code you can see that both provides flexibility. The
    > only difference is the implementation methods.
    > So any essential difference?


    I'll presume that Work class has e.g. this:

    void Work::work() {... m_pUtil->print(); ...}

    If all instances of Work should use same Util, then clearly m_pUtil is
    overkill. If not, then it isn't. But we don't know any of that, so we
    can't tell you. It is very hard to guess these things, and it is very
    hard to predict the future.

    If, for example, at this stage, you use one Util for all Work-s, but
    think that you might need separate ones later, you can do e.g.:

    class Work
    {
    ....
    Util* GetUtil() { return GetGlobalUtil(); }
    ....
    };

    and not use m_pUtil anymore. Then, once you realize that you do want
    several Util-s, just add your SetUtil and change GetUtil to:

    Util* GetUtil() { return m_pUtil; }

    That way, you get simpler design, no runtime cost, and the ability to
    change later with less actual code changes.

    Goran.
     
    Goran Pusic, Sep 2, 2010
    #5
  6. thomas

    thomas Guest

    Thanks. Hm.. sorry for bad expression.

    I want to print debug messages and hope that I can change output
    destination according to different requirements.
    There're two ways: dependency injection; static/global instances.
    I think "static/global instances[method II] is enough, but I wonder
    whether there's anything bad to my design I don't know.

    -----Monitor class---
    struct IMonitor{
    virtual void print(){}
    };
    class Monitor : public IMonitor{
    public:
    void print(){...}
    };
    ----end-----

    [method I]
    ----injection---
    class Work{
    void SetMonitor(IMonitor* pMonitor){m_pMonitor = pMonitor;}
    IMonitor* m_pMonitor;
    };
    ----end----
    To print messages, call "m_pMonitor->print()"

    [method II]
    ----static----
    class Util{
    public:
    static IMonitor* s_pMonitor;
    };

    IMonitor* Util::s_pMonitor = NULL; //Util::s_pMonitor = pMonitor; (do
    assignment
    somewhere else.)
    -------end-----
    To print messages, call "Util::s_pMonitor->print()"
     
    thomas, Sep 2, 2010
    #6
  7. thomas

    Pavel Guest

    thomas wrote:
    > Thanks. Hm.. sorry for bad expression.
    >
    > I want to print debug messages and hope that I can change output
    > destination according to different requirements.
    > There're two ways: dependency injection; static/global instances.
    > I think "static/global instances[method II] is enough, but I wonder
    > whether there's anything bad to my design I don't know.
    >
    > -----Monitor class---
    > struct IMonitor{
    > virtual void print(){}
    > };
    > class Monitor : public IMonitor{
    > public:
    > void print(){...}
    > };
    > ----end-----
    >
    > [method I]
    > ----injection---
    > class Work{
    > void SetMonitor(IMonitor* pMonitor){m_pMonitor = pMonitor;}
    > IMonitor* m_pMonitor;
    > };
    > ----end----
    > To print messages, call "m_pMonitor->print()"
    >
    > [method II]
    > ----static----
    > class Util{
    > public:
    > static IMonitor* s_pMonitor;
    > };
    >
    > IMonitor* Util::s_pMonitor = NULL; //Util::s_pMonitor = pMonitor; (do
    > assignment
    > somewhere else.)
    > -------end-----
    > To print messages, call "Util::s_pMonitor->print()"

    If it were not for debugging, I would say the first snippet has
    advantages of flexibility, easier adoption to multi-tasking (Monostates
    are notoriously difficult to deal with in multi-threaded environment,
    and dynamic libraries are not helping).

    The second is simpler to implement, less intrusive to the existing
    classes, slightly faster at run-time, takes no memory in the object,
    easier to control as an "aspect" (e.g. turn printing on or off
    on-the-fly or via compilation macro).

    As it is for debugging, 2nd method seems to be more appropriate. I would
    not even hesitate to use a macro like UTIL_PRINT() to make sure I can
    remove this code from the binary at compilation time w/o an issue.

    -Pavel
     
    Pavel, Sep 3, 2010
    #7
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. =?iso-8859-1?B?bW9vcJk=?=

    How to build a dependency injection framework by myself?

    =?iso-8859-1?B?bW9vcJk=?=, Aug 24, 2006, in forum: Java
    Replies:
    4
    Views:
    412
    PerfectDayToChaseTornados
    Aug 24, 2006
  2. Michael Feathers

    Dependency Injection in C++

    Michael Feathers, Oct 11, 2006, in forum: C++
    Replies:
    5
    Views:
    7,444
    F.J.K.
    Oct 13, 2006
  3. Anonieko

    What is Dependency Injection?

    Anonieko, Oct 14, 2007, in forum: ASP .Net
    Replies:
    2
    Views:
    309
    Michael Nemtsev, MVP
    Oct 14, 2007
  4. Danno
    Replies:
    12
    Views:
    716
    Ke Jin
    Apr 10, 2008
  5. Philipp
    Replies:
    8
    Views:
    656
    Owen Jacobson
    Jun 29, 2009
Loading...

Share This Page