My concern is that when using either shared_ptr
or unique_ptr
I stick to one ownership model - either injected objects is shared or my own. And I think this is is secondary class responsibility - to care of injected objects lifetime.
So, does it violates SRP - assuming that class already has some responsibility.
Some simple example:
class Calculator {
public:
Calculator(std::unique_ptr<Adder> adder) : adder(adder) {}
void add();
private:
std::unique_ptr<Adder> adder;
};
When design changes - so I will have many different calculators - then I need to change unique_ptr
to shared_ptr
. So even if Calculator
main responsibility (to calculate) did not change - I need to change the class.
Wouldn't be better to use simple references for injected objects - and just left the responsibility of injected objects lifetime to some other classes?
No, the way we kept member variables in an object is the implementation detail, and it is not related in any way to design principles like Single Responsibility Principle
To illustrate this - you can encapsulate access to your members by some private method - this prevents the changes in class implementation when you changes from unique_ptr
to shared_ptr
or vice versa.
private:
Adder& add();
Adder const& add();
Or you can go even further and enclose Adder to some private object - thus preventing it totally from accidental access to "read" adder variable, like:
class Calculator
{
class AdderProxy
{
public:
using Type = std::unique_ptr<>;
AdderProxy(AdderType);
void add(...);
};
public:
Calculator(AdderProxy::Type);
private:
AdderProxy adder;
Or you can just have some DI library, like this one - and have all kind of injection hidden from application code.