Part 1. Putting Dependency Injection on the map
Dependency Injection (DI) is one of the most misunderstood concepts of object-oriented programming. The confusion is abundant and spans terminology, purpose, and mechanics. Should it be called Dependency Injection, Dependency Inversion, Inversion of Control, or even Third-Party Connect? Is the purpose of DI only to support unit testing, or is there a broader purpose? Is DI the same as Service Location? Do we need DI Containers to apply DI?
There are plenty of blog posts, magazine articles, conference presentations, and so on that discuss DI, but, unfortunately, many of them use conflicting terminology or give bad advice. This is true across the board, and even big and influential actors like Microsoft add to the confusion.
It doesnât have to be this way. In this book, we present and use a consistent terminology. For the most part, weâve adopted and clarified existing terminology defined by others, but, occasionally, we add a bit of terminology where none existed previously. This has helped us tremendously in evolving a specification of the scope or boundaries of DI.
One of the underlying reasons behind all the inconsistency and bad advice is that the boundaries of DI are quite blurry. Where does DI end, and where do other object-oriented concepts begin? We think that itâs impossible to draw a distinct line between DI and other aspects of writing good object-oriented code. To talk about DI, we have to pull in other concepts such as SOLID, Clean Code, and even Aspect-Oriented Programming. We donât feel that we can credibly write about DI without also touching on some of these other topics.
The first part of the book helps you understand the place of DI in relation to other facets of software engineering â putting it on the map, so to speak. Chapter 1 gives you a quick tour of DI, covering its purpose, principles, and benefits, as well as providing an outline of the scope for the rest of the book. Itâs focused on the big picture and doesnât go into a lot of details. If you want to learn what DI is and why you should be interested in it, this is the place to start. This chapter assumes you have no prior knowledge of DI. Even if you already know about DI, you may still want to read it â it may turn out to be something other than what you expected.
Chapters 2 and 3, on the other hand, are completely reserved for one big example. This example is intended to give you a much more concrete feel for DI. To contrast DI with a more traditional style of programming, chapter 2 showcases a typical, tightly coupled implementation of a sample e-commerce application. Chapter 3 then subsequently reimplements it with DI.
In this part, weâll discuss DI in general terms. This means we wonât use any so-called DI Container. Itâs entirely possible to apply DI without using a DI Container. A DI Container is a helpful, but optional, tool. So parts 1, 2, and 3 more or less ignore DI Containers completely, and instead discuss DI in a container-agnostic way. Then, in part 4, we return to DI Containers to dissect three specific libraries.
Part 1 establishes the context for the rest of the book. Itâs aimed at readers who donât have any prior knowledge of DI, but experienced DI practitioners can also benefit from skimming the chapters to get a feeling for the terminology used throughout the book. By the end of part 1, you should have a firm grasp of the vocabulary and overall concepts, even if some of the concrete details are still a little fuzzy. Thatâs OK â the book becomes more concrete as you read on, so parts 2, 3, and 4 should answer the questions youâre likely to have after reading part 1.
1 The basics of Dependency Injection: What, why, and how
In this chapter
- Dispelling common myths about Dependency Injection
- Understanding the purpose of Dependency Injection
- Evaluating the benefits of Dependency Injection
- Knowing when to apply Dependency Injection
You may have heard that making a sauce bĂ©arnaise is difficult. Even among people who regularly cook, many have never attempted to make one. This is a shame, because the sauce is delicious. (Itâs traditionally paired with steak, but itâs also an excellent accompaniment to white asparagus, poached eggs, and other dishes.) Some resort to substitutes like ready-made sauces or instant mixes, but these arenât nearly as satisfying as the real thing.
A sauce bĂ©arnaise is an emulsified sauce made from egg yolk and butter, thatâs flavored with tarragon, chervil, shallots, and vinegar. It contains no water. The biggest challenge to making it is that its preparation can fail. The sauce can curdle or separate, and, if either happens, you canât resurrect it. It takes about 45 minutes to prepare, so a failed attempt means that you may not have time for a second try. On the other hand, any chef can prepare a sauce bĂ©arnaise. Itâs part of their training and, as theyâll tell you, itâs not difficult.
You donât have to be a professional cook to make sauce bĂ©arnaise. Anyone learning to make it will fail at least once, but after you get the hang of it, youâll succeed every time. We think Dependency Injection (DI) is like sauce bĂ©arnaise. Itâs assumed to be difficult, and, if you try to use it and fail, itâs likely there wonât be time for a second attempt.
Definition Dependency Injection is a set of software design principles and patterns that enables you to develop loosely coupled code.
Despite the fear, uncertainty, and doubt (FUD) surrounding DI, itâs as easy to learn as making a sauce bĂ©arnaise. You may make mistakes while you learn, but once youâve mastered the technique, youâll never again fail to apply it successfully.
Stack Overflow, the software development Q&A website, features an answer to the question, âHow to explain Dependency Injection to a 5-year old?â The most highly rated answer, by John Munsch, provides a surprisingly accurate analogy targeted at the (imaginary) five-year-old inquisitor:
When you go and get things out of the refrigerator for yourself, you can cause problems. You might leave the door open, you might get something Mommy or Daddy doesnât want you to have. You might even be looking for something we donât even have or which has expired.
What you should be doing is stating a need, âI need something to drink with lunch,â and then we will make sure you have something when you sit down to eat.
What this means in terms of object-oriented software development is this: collaborating classes (the five-year-old) should rely on infrastructure (the parents) to provide necessary services.
Note In DI terminology, we often talk about services and components. A service is typically an Abstraction, a definition for something that provides a service. An implementation of an Abstraction is often called a component a class that contains behavior. Because both service and component are such overloaded terms, throughout this book, youâll typically see us use the terms âAbstractionâ and âclassâ instead.
This chapter is fairly linear in structure. First, we introduce DI, including its purpose and benefits. Although we include examples, overall, this chapter has less code than any other chapter in the book. Before we introduce DI, we discuss the basic purpose of DI â maintainability. This is important because itâs easy to misunderstand DI if you arenât properly prepared. Next, after an example (Hello DI!), we discuss benefits and scope, laying out a road map for the book. When youâre done with this chapter, you should be prep...