vovaspace / brandi

The dependency injection container powered by TypeScript.
https://brandi.js.org
ISC License
194 stars 12 forks source link

DIP Violation #28

Open DScheglov opened 2 years ago

DScheglov commented 2 years ago

Hey, @vovaspace

This line violates Dependcy Inversion Principle:

https://github.com/vovaspace/brandi/blob/08a4748d7f6bcc301e4384fa0c291997af7bd5e3/docs/reference/dependency-modules.md?plain=1#L79

The ES-module with definition of ApiService class depends on infrastructure layer: your library brandi and on the module structue: TOKENS.

Just move this line to the composition root and everything becomes well again:

import { DependencyModule, injected } from 'brandi';
import { TOKENS } from '../tokens';
import { ApiService } from './ApiService';

export const apiModule = new DependencyModule();

apiModule.bind(TOKENS.apiKey).toConstant('#key9428');

injected(ApiService, TOKENS.apiKey); // << this code should be here
apiModule.bind(TOKENS.apiService).toInstance(ApiService).inTransientScope();

All dependency resolution rules should be placed in single place: composition root (see: Dependency Injection Principles, Practices, and Patterns by Steven van Deursen and Mark Seemann)

And if you are going to move it to the composition root, just add the inject parameter to the container methods: toFactory and toInstance:

import { DependencyModule } from 'brandi';
import { TOKENS } from '../tokens';
import { ApiService } from './ApiService';

export const apiModule = new DependencyModule();

apiModule.bind(TOKENS.apiKey).toConstant('#key9428');

apiModule
  .bind(TOKENS.apiService)
  .toInstance(ApiService, TOKENS.apiKey)
  .inTransientScope();
vovaspace commented 2 years ago

Hi!

That is great suggestion! I'm working on the next Brandi version and will try to implement that.

polerin commented 2 years ago

This is actually what I'm doing in my library usage of brandi. I'm exporting a set of tokens, a dependency module, and a default set of injected() registrations that can be used collectively or rebound by the consuming application.