DI

When a component (in the broad sense) in your application depends on others, those dependencies must be made available at runtime in one way or another. The manner in which dependencies are located, instantiated, and provided actually matters a lot. If you're not careful, you'll quickly create strong ties (that is, strong coupling) between different pieces of your application.

Down the line, unnecessary coupling leads to code that is harder to maintain, test, and debug.

DI, also known as Inversion of Control (IoC), is a design pattern that can help us to limit coupling and thus avoid those pitfalls. With that pattern, we can use a declarative approach rather than an imperative one to define our dependencies. Using DI/IoC, each component in our application can declare its dependencies and, at runtime, the injection system will provide those dependencies for us. That way, our code will not have to care about where the dependency comes from, what precise implementation it is, and, more importantly, how it was instantiated.

Be wary of using the new keyword in your code for dependencies. Each time you new-up a dependency yourself, you're creating a coupling that you might avoid using DI/IoC or factories (another related design pattern).

By combining DI and programming against interfaces, we can limit the touchpoints between application elements to the bare minimum: a contract.

We've used this approach with MediaMan earlier. Do you remember when our MediaManController class required an instance of MediaManView and MediaService? The MediaManController class didn't get its dependencies itself—it simply required those to be passed to its constructor. That way, we could limit the coupling.

With MediaMan, the entry point of the application took care of instantiating the implementation of the orchestration. By doing that, we actually applied the IoC pattern (manually, though). The IoC pattern's name comes from the fact that we invert the responsibilities. Instead of letting the dependent components take care of instantiating their dependencies on their own, we pass over that responsibility to the "thing" that instantiates them.

DI systems can actually instantiate/configure whole graphs of objects for us and inject specific elements only where and when needed. DI/IoC is supported by many frameworks in various programming languages; for example, Spring for Java and Unity for .NET. Of course, we have introduced DI here because Angular also supports this pattern!

Creating so-called injectable elements in Angular is really easy. Most of the time, you'll be injecting services, which should be marked as injectable so that Angular's DI framework can instantiate and inject them.

Annotating a class with the @Injectable (https://angular.io/api/core/Injectable) decorator tells Angular that this element can be injected elsewhere. However, that isn't enough for Angular to be able to actually instantiate and inject that element.

In Angular terms, we say that an injectable service provides a service. For Angular to be able to inject an actual instance of an injectable service somewhere, it needs to use injectors (https://angular.io/guide/glossary#injector).

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.19.211.134