Dependency injection is a design pattern commonly used in object-oriented software architectures in order to support Inversion of Control. At a very high level it refers to the practice of passing existing objects (or services) into a class when it is instantiated, or via a setter method, rather than creating them inside the class itself. Doing so allows some other logic external to your code to determine how to initialize and configure the service object, and keeps your code more flexible.
In the case of Drupal this allows your code to state a need, such as, "I need to access the database. Please provide me with a database service," without knowing anything about the specifics. Drupal then determines, based on other factors, what database type (MySQL, SQLite, etc.) is being used, and how to connect to it, how to authenticate, and any other requirements on your behalf.
As of Drupal 8, dependency injection is the preferred method for accessing and using services and should be used whenever possible. Rather than calling out to the global services container, services are instead passed as arguments to a constructor or injected via setter methods. This allows for a loose coupling of components, which makes things easier to test, and easier to replace with alternative implementations.
- Use dependency injection to make use of services in your module's code
- Write custom code that is easier to test and refactor
While relatively new to Drupal, dependency injection is a tried and true technique commonly used in object-oriented PHP applications. The implementation in Drupal is unlikely to change significantly, and therefore you should feel comfortable learning it just about any context and then applying it to Drupal.