

Ask HN: How do you feel about optional dependency injection? - sprain

Often when writing a library I feel the need to make things simpler for quick and small projects and provide a way to skip verbose dependency injection for non-optional dependencies. I do this by using a non-injected default instance if no other dependency has been provided. I started calling this &quot;optional dependency injection&quot;.<p>I haven&#x27;t found anything about this approach so far. So I figured I&#x27;d ask you guys how you feel about it. Would you consider this good or bad?<p>Example in PHP:<p><pre><code>    public function __construct(Cache $cache = null)
    {
        $this-&gt;cache = $cache;

        &#x2F;&#x2F; Create default cache if none has been provided
        if (null == $this-&gt;cache) {
            $this-&gt;cache = new SomeCache();
        }
    }</code></pre>
======
Terr_
If it's possible in your particular language/framework, I would instead use
setter-injection, and reserve constructor parameters for things the object
truly needs access to before it can exist. In other words, let your design be
guided by some of the basic principles you'd follow if you didn't have a
dependency-injection system at all.

Assuming constructor-injection is your only choice (or the only choice you can
use autowiring for)... then this technique depends on making the correct guess
about how people will use the object. In this case, you're predicting that
most of the time a cache will not be wanted.

If it were the other way around, I would instead make it a _required_
parameter, and provide a convenient dummy/no-op Cache implementation people
could use.

~~~
sprain
Actually, in my example, a cache will _always_ be used. It is mandatory to use
a cache and therefore, if none is provided, a default cache is used. That's
why it put it into the constructor.

~~~
Terr_
Is SomeCache a dummy or no-op item, or does it contain an actual
implementation, e.g. file or database access?

To what extent is it important to make sure the person wiring things up knows
and approves of what SomeCache does?

~~~
sprain
SomeCache is a real, functioning implementation.

Maybe cache is a bad example. It could also be a HTTP client to fetch some
data over an api. Let's say the library by default uses Guzzle. But if a user
for some reason wants to inject his own implementation of Guzzle or even
BuzzBrowser (which is compatible for basic operations) instead, he can.

For most simple projects, especially without a framework, the default
implementation does the job and would save you some code.

------
bartonfink
I've written this exact idiom in some parts of a very poorly structured,
tightly-coupled PHP codebase I've inherited. I'm not a huge fan, because it
clutters the codebase a bit (that's 4 lines of overhead per dependency), but
in the absence of a true DI framework this is better than nothing. You get
many of the functional benefits of DI, but not all of the niceties when it
comes to cleaning up your code.

------
xrstf
I personally would put this fallback logic into a Factory class/method and
make the $cache parameter required for the constructor. I like to keep my
constructors as simple and cheap as possible and usually have some sort of
factory code somewhere anyway.

