简体   繁体   中英

Several questions regarding Dependency Injection in C++

I am practicing dependency injection and there are several issues that i am not sure how to deal with them.

  1. class A may be dependant on 3-4 other behaviour (interfaces). On the one hand, passing all of them in the constructor makes the object harder to create and initialize. On the other hand, using setters might be problematic in case a client forgot to set one of the dependencies. What would be the correct way to deal with this?

  2. Eventually, all dependencies must be created somewhere. How do i prevent a case in which i have many initialization in one class (for example, the main class) ?

  3. Is it considered a good practice to use shared_ptr when doing dependency injection? In such cases the creator of the dependencies usually could not delete the objects, so it makes sense to me to use shared pointers.

class A may be dependant on 3-4 other behaviour (interfaces). On the one hand, passing all of them in the constructor makes the object harder to create and initialize. On the other hand, using setters might be problematic in case a client forgot to set one of the dependencies. What would be the correct way to deal with this?

There's no perfect solution, so you just have to tune to taste. Options include:

  • having the/a constructor accept a structure grouping the injected objects (if you're passing the same set of dependencies to many constructors)

  • dividing dependencies between run-time and compile-time and having compile-time dependencies factored using derivation/ using / typedef ("Policies" ala Modern C++ Design by Alexandrescu)

  • providing defaults for some/all dependencies, or some dynamic lookup "service" that still lets you modify the injections but persists across multiple dependent-object constructions

A bit of imagination and analysis of your repetitive code would hopefully suggest an approach to you....

Eventually, all dependencies must be created somewhere. How do i prevent a case in which i have many initialization in one class (for example, the main class) ?

This is a matter of factoring redundant dependency creation and the access to objects - your choices are similar - passing around references or pointers, using structures or containers or management objects to group them and re-access them....

Is it considered a good practice to use shared_ptr when doing dependency injection? In such cases the creator of the dependencies usually could not delete the objects, so it makes sense to me to use shared pointers.

For functions, often the client code necessarily outlives the use by the function being called so there's no need for shared pointers... a reference is ideal. If you're using threads, or creating objects that can outlive the client code, then shared pointers can make a lot of sense.

All personal opinions, but there we go.

1) Pass the dependencies to the constructor. If there are sensible defaults, then provide multiple constructors or use default arguments.

2) If you're going to be using the same set of dependencies frequently, you might be able to save yourself some typing by creating a "dependency set" class, an instance of which can be passed to a constructor, something like:

struct Iface1;
struct Iface2; // Dependent interfaces
struct Iface3;

struct DependencySet
{
    Iface1& iface1;
    Iface2& iface2;
    Iface3& iface3;
};

class Dependent
{
public:
    Dependent(DependencySet& set)
        : iface1(set.iface1)
        , iface2(set.iface2)
        , iface3(set.iface3)
    {}

private:
    Iface1& iface1;
    Iface2& iface2;
    Iface3& iface3;
};

3) Personally I'd favour using references as above and managing the lifetimes so that the dependencies outlive the dependent class, but shared pointers could be used if you want to "forget" about the dependencies once you've used them.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM