Best dependency-injection questions in July 2011

Is there an alternative to bastard injection? (AKA poor man's injection via default constructor)

47 votes

I most commonly am tempted to use "bastard injection" in a few cases. When I have a "proper" dependency-injection constructor:

public class ThingMaker {
    ...
    public ThingMaker(IThingSource source){
        _source = source;
    }

But then, for classes I am intending as public APIs (classes that other development teams will consume), I can never find a better option than to write a default "bastard" constructor with the most-likely needed dependency:

    public ThingMaker() : this(new DefaultThingSource()) {} 
    ...
}

The obvious drawback here is that this creates a static dependency on DefaultThingSource; ideally, there would be no such dependency, and the consumer would always inject whatever IThingSource they wanted. However, this is too hard to use; consumers want to new up a ThingMaker and get to work making Things, then months later inject something else when the need arises. This leaves just a few options in my opinion:

  1. Omit the bastard constructor; force the consumer of ThingMaker to understand IThingSource, understand how ThingMaker interacts with IThingSource, find or write a concrete class, and then inject an instance in their constructor call.
  2. Omit the bastard constructor and provide a separate factory, container, or other bootstrapping class/method; somehow make the consumer understand that they don't need to write their own IThingSource; force the consumer of ThingMaker to find and understand the factory or bootstrapper and use it.
  3. Keep the bastard constructor, enabling the consumer to "new up" an object and run with it, and coping with the optional static dependency on DefaultThingSource.

Boy, #3 sure seems attractive. Is there another, better option? #1 or #2 just don't seem worth it.

As far as I understand, this question relates to how to expose a loosely coupled API with some appropriate defaults. In this case, you may have a good Local Default, in which case the dependency can be regarded as optional. One way to deal with optional dependencies is to use Property Injection instead of Constructor Injection - in fact, this is sort of the poster scenario for Property Injection.

However, the real danger of Bastard Injection is when the default is a Foreign Default, because that would mean that the default constructor drags along an undesirable coupling to the assembly implementing the default. As I understand this question, however, the intended default would originate in the same assembly, in which case I don't see any particular danger.

In any case you might also consider a Facade as described in one of my earlier answers: Dependency Inject (DI) "friendly" library

BTW, the terminology used here is based on the pattern language from my book.

Are PHP global constants a good modern development practice?

13 votes

I'm working on a new project with a sizeable PHP codebase. The application uses quite a few PHP constants ( define('FOO', 'bar') ), particularly for things like database connection parameters. These constants are all defined in a single configuration file that is require_once()'d directly by basically every class in the application.

A few years ago this would have made perfect sense, but since then I've gotten the Unit Testing bug and this tight coupling between classes is really bothering me. These constants smell like global variables, and they're referenced directly throughout the application code.

Is this still a good idea? Would it be reasonable to copy these values into an object and use this object (i.e. a Bean - there, I said it) to convey them via dependency injection to the the classes that interact with the database? Am I defeating any of the benefits of PHP constants (say speed or something) by doing this?

Another approach I'm considering would be be to create a separate configuration PHP script for testing. I'll still need to figure a way to get the classes under test to use the sandbox configuration script instead of the global configuration script. This still feels brittle, but it might require less outright modification to the entire application.

In my opinion, constants should be used only in two circumstances:

  • Actual constant values (i.e. things that will never change, SECONDS_PER_HOUR).
  • OS-dependent values, as long as the constant can be used transparently by the application, in every situation possible.

Even then, I'd reconsider whether class constants would be more appropriate so as not to pollute the constants space.

In your situation, I'd say constants are not a good solution because you will want to provide alternative values depending on where they're used.