| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
The VS Code extension for Python uses Inversify, an inversion of control (IoC) container for Typescript and Javascript applications. Inversify performs dependency injection, and is intended to help developers adhere to the dependency inversion principle. IoC containers are distinct from traditional IoC, and dependency injection and dependency inversion are not the same thing. All four concepts are related, distinct, and relevant to how our codebase is written.
The dependency inversion principle (DIP) refers to depending on abstractions (i.e. interfaces) instead of concretions (i.e. classes). This is a design pattern that is part of the SOLID principles, and is not specific to Inversify and Typescript. Under DIP, classes define the interfaces they need from their dependencies, and the dependencies implement those interfaces. Variables should be typed using these interfaces rather than concrete classes.
Dependency injection (DI) refers to the technique of passing dependencies that a class needs to the class. This is one form of the broader technique of inversion of control. Inversify helps with dependency injection, but it's not the only way that you can inject dependencies into a class. Any class whose dependencies are explicitly passed in could also be said to employ dependency injection. There are two primary styles of dependency injection:
An inversion of control container is a specific style of inversion of control. Generally, inversion of control refers to handing the program flow over to a framework. An IoC container is a framework for implementing dependency injection. IoC containers also create and manage the life cycle of objects so we don't have to explicitly do that ourselves. Inversify provides such an IoC container.
For the VS Code Python extension, dependency injection offers one major benefit: it allows us to mock dependencies of the classes we want to write unit and function tests for so we can test specific functionality. Without dependency injection, constructors would internally instantiate their dependencies and, in so doing, obscure those dependencies.
By using Inversify's IoC container for dependency injection, we can mock a dependency of a class we want to test based on its interface and rebind that object in the Inversify container to the mocked object instead. IoC containers also help us avoid verbose constructor calls when using dependency injection.
Since we've defined interfaces and bound them to concrete implementations, we get dependency inversion in the process as well--consumers of our classes depend on the interfaces and not the class implementation.
A general rule of thumb is that we only add classes to the container with an interface if:
class InteractiveWindow implements IInteractiveWindow {export const IInteractiveWindow = Symbol('IInteractiveWindow');serviceManager.add<IInteractiveWindow>(IInteractiveWindow, InteractiveWindow);@injectable()
export class InteractiveWindow extends WebViewHost<IInteractiveWindowMapping> implements IInteractiveWindow {constructor(
@multiInject(IInteractiveWindowListener) private readonly listeners: IInteractiveWindowListener[],
@inject(ILiveShareApi) private liveShare : ILiveShareApi,
@inject(IApplicationShell) private applicationShell: IApplicationShell,
…)| Back | FazBrowse Home | New Git URL |