Because we have changed the constructor signature, all the existing instantiations of ItemsGateway are now broken. We need to find all the places in the code where the ItemsGateway class is instantiated, and change the instantiations to pass a properly-constructed Db object and an ItemFactory.

To do so, we use our project-wide search facility to search using a regular expression for our changed class name:

Search for:

Doing so will give us a list of all instantiations in the project. We need to review each result and change it by hand to instantiate the dependencies and pass them to the ItemsGateway.

For example, if a page script from the search results looks like this:

We need to change it to something more like this:

Do this for each instantiation of the changed class.

Sometime we will discover classes that have dependencies, and the dependencies themselves have dependencies. These intermediary dependencies are passed to the outside class, which carries them along only so that the internal objects can be instantiated with them.

For example, say we have a Service class that needs an ItemsGateway, which itself needs a Db connection. Before removing global variables, the Service class might have looked like this:

After removing global variables, we are left with a new keyword, but we still need the Db object as a dependency for ItemsGateway:

How do we successfully remove the new keyword here? The ItemsGateway needs a Db connection. The Db connection is never used by the Service directly; it is used only for building the ItemsGateway.

The solution in cases like this is to inject a fully-constructed ItemsGateway. First, we modify the Service class to receive its real dependency, the ItemsGateway:

Second, throughout the entire legacy application, we change all instantiations of the Service to pass an ItemsGateway.

For example, a page script might have done this when using global variables everywhere:

And then we changed it to inject the intermediary dependency after removing globals:

But we should finally change it to inject the real dependency:

In the examples above, our Factory class only creates a single newInstance() of an object. If we regularly create collections of objects, it may be reasonable to add a newCollection() method to our Factory. For example, given our ItemFactory above, we may do something like the following:

We may go so far as to create an ItemCollection class for the collection instead of using an array. If so, it would be reasonable to use a new keyword inside our ItemFactory to create the ItemCollection instance. (The ItemCollection class is omitted here).

Indeed, we may wish to have a separate ItemCollectionFactory, using an injected ItemFactory to create Item objects, with its own newInstance() method to return a new ItemCollection.

There are many variations on the proper use of Factory objects. The key is to keep object creation (and related operations) separate from object manipulation.

All the dependency injection we have been doing so far has been manual injection, where we create the dependencies ourselves and then inject them as we create the objects we need. This can be a tedious process. Who wants to create a Db object over and over again just so it can be injected into a variety of Gateway classes? Isn't there some way to automate that?

Yes, there is. It is called a Container. A Container may go by various synonyms indicating how it is to be used. A Dependency Injection Container is intended to be used always-and-only outside the non-Factory classes, whereas an identical Container implementation going by the name Service Locator is intended to be used inside non-Factory objects.

Using a Container brings distinct advantages:

But using a Container has disadvantages as well:

At this stage of modernizing our legacy application it can be very tempting to start using a Container to automate dependency injection for use. I suggest that we do not add one just now, because so much of our legacy application remains to be modernized. We will add one eventually, but it will be as the very last step of our modernization process.