Skip to main content Skills Marktplatz Entdecken und erkunden Sie KI-Skills, die von der Community erstellt wurden.
Mit Codex oder Claude installieren Kopieren Sie diesen Prompt, fügen Sie ihn in Codex, Claude oder einen anderen Assistant ein und lassen Sie die Skill-Seite prüfen und installieren.
Prompt kopierenPrompt-Details anzeigen Ein direkter Befehl überspringt den Prüf-Prompt. Prüfen Sie die Quelle, bevor Sie ihn ausführen.
npx skills add https://github.com/InugamiDev/ultrathink-oss --skill dependency-injectionDer Befehl bleibt in einer Zeile. Scrollen Sie horizontal, um ihn vor dem Kopieren vollständig zu prüfen.
Sie bevorzugen eine lokale Kopie? Laden Sie die Dateien herunter, die SkillsMP derzeit vorliegen.
ZIP herunterladen Herunterladen... Mehr aus diesem Repository Unified design foundations — design system architecture, tokens, component specs, visual principles, creative vision, figma integration, plus brand design system loader (66 real brands via DESIGN.md). Absorbs design, design-system, design-systems, design-principles, design-router, creative-vision, figma, design-md.
Render, summarize, and present markdown documents and structured content in multiple output modes
Ultra UI skill - combines Google's DESIGN.md spec (machine-readable design tokens) with the ui-ux-pro-max knowledge base (91 styles, 161 palettes, 73 font pairings, 161 products, 104 UX guidelines, 25 chart types). Generates lint-clean DESIGN.md files, validates token references and WCAG contrast, exports Tailwind/DTCG tokens, and diffs design systems version-over-version.
Verwandte Berufe SOC
Basierend auf der SOC-Berufsklassifikation
name dependency-injection description Dependency injection patterns — IoC containers, service registration, lifetime scoping, and testing. layer utility category architecture triggers ["dependency injection","IoC","inversion of control","DI container","service provider"] inputs ["DI architecture decisions","Service registration and lifetime scoping","IoC container selection and configuration","Testing with dependency injection"] outputs ["DI container setup and configuration","Service registration patterns","Lifetime management strategies","Testable architectures with DI"] linksTo ["nestjs","typescript-patterns","testing-patterns"] linkedFrom [] preferredNextSkills ["nestjs","typescript-patterns","testing-patterns"] fallbackSkills [] riskLevel low memoryReadPolicy selective memoryWritePolicy none sideEffects []
Dependency Injection Patterns
Purpose
Provide expert guidance on dependency injection (DI) and inversion of control (IoC) patterns including container configuration, service lifetimes, composition roots, and how DI enables testability. Covers both framework-based DI (NestJS, Angular) and standalone containers (tsyringe, inversify, awilix).
Core Concepts
Dependency Injection inverts the control of dependency creation. Instead of a class creating its own dependencies, they are provided (injected) from the outside.
class OrderService {
private db = new PostgresDatabase ();
private mailer = new SmtpMailer ();
async createOrder (data : CreateOrderDto ) {
const order = await this .db .insert ('orders' , data);
await this .mailer .send (data.email , 'Order confirmed' );
return order;
}
}
class OrderService {
constructor (
private readonly db : Database ,
private : ,
) {}
( ) {
order = . . ( , data);
. . (data. , );
order;
}
}
readonly
mailer
Mailer
async
createOrder
data : CreateOrderDto
const
await
this
db
insert
'orders'
await
this
mailer
send
email
'Order confirmed'
return
DI Patterns
Constructor Injection (Preferred) Dependencies provided via the constructor. Most explicit and testable:
interface Logger {
info (message : string ): void ;
error (message : string , error ?: Error ): void ;
}
interface UserRepository {
findById (id : string ): Promise <User | null >;
save (user : User ): Promise <User >;
}
class UserService {
constructor (
private readonly userRepo : UserRepository ,
private readonly logger : Logger ,
) {}
async getUser (id : string ): Promise <User > {
this .logger .info (`Fetching user ${id} ` );
const user = await this .userRepo .findById (id);
if (!user) throw new NotFoundException (`User ${id} not found` );
return user;
}
}
Factory Pattern When the dependency needs runtime parameters:
interface ConnectionFactory {
create (config : ConnectionConfig ): Connection ;
}
class DatabaseService {
constructor (private readonly connectionFactory : ConnectionFactory ) {}
connect (config : ConnectionConfig ) {
return this .connectionFactory .create (config);
}
}
Strategy Pattern with DI Inject different implementations based on context:
interface PaymentProcessor {
charge (amount : number , currency : string ): Promise <PaymentResult >;
}
class StripeProcessor implements PaymentProcessor {
async charge (amount : number , currency : string ) { }
}
class PayPalProcessor implements PaymentProcessor {
async charge (amount : number , currency : string ) { }
}
class PaymentService {
constructor (
private readonly processors : Map <string , PaymentProcessor >,
) {}
async processPayment (method : string , amount : number , currency : string ) {
const processor = this .processors .get (method);
if (!processor) throw new Error (`Unknown payment method: ${method} ` );
return processor.charge (amount, currency);
}
}
Service Lifetimes Lifetime Description Use Case Singleton One instance for the entire app Stateless services, config, loggers Transient New instance on every injection Stateful services, request-specific logic Scoped One instance per scope (e.g., HTTP request) Database connections, user context
import { container, singleton, injectable } from 'tsyringe' ;
@singleton ()
class ConfigService {
get (key : string ): string { }
}
@injectable ()
class RequestHandler {
constructor (private config : ConfigService ) {}
}
const requestContainer = container.createChildContainer ();
requestContainer.register ('RequestContext' , { useValue : { userId : '123' } });
IoC Containers
tsyringe (Lightweight, TypeScript-native)
import 'reflect-metadata' ;
import { container } from 'tsyringe' ;
container.register <Database >('Database' , { useClass : PostgresDatabase });
container.register <Mailer >('Mailer' , { useClass : SmtpMailer });
container.register <Logger >('Logger' , { useClass : PinoLogger });
const orderService = container.resolve (OrderService );
import { injectable, inject } from 'tsyringe' ;
@injectable ()
class OrderService {
constructor (
@inject ('Database' ) private readonly db : Database ,
@inject ('Mailer' ) private readonly mailer : Mailer ,
) {}
}
awilix (No decorators, function-oriented)
import { createContainer, asClass, asFunction, Lifetime } from 'awilix' ;
const container = createContainer ();
container.register ({
userRepository : asClass (PostgresUserRepository ).singleton (),
orderRepository : asClass (PostgresOrderRepository ).singleton (),
logger : asClass (PinoLogger ).singleton (),
userService : asClass (UserService ).scoped (),
orderService : asClass (OrderService ).scoped (),
dbConnection : asFunction (({ config } ) =>
createPool (config.databaseUrl )
).singleton (),
});
app.use ((req, _res, next ) => {
req.scope = container.createScope ();
req.scope .register ({ requestId : asValue (crypto.randomUUID ()) });
next ();
});
NestJS Built-in DI
@Module ({
providers : [
UserService ,
{ provide : 'MAILER' , useClass : SmtpMailer },
{
provide : 'DB_POOL' ,
useFactory : (config : ConfigService ) => createPool (config.get ('DATABASE_URL' )),
inject : [ConfigService ],
},
{ provide : 'APP_VERSION' , useValue : '1.0.0' },
],
})
export class UsersModule {}
Composition Root The composition root is the single place where the entire dependency graph is wired. Keep it at the app entry point:
import { container } from './container' ;
async function bootstrap ( ) {
container.register <Database >('Database' , { useClass : PostgresDatabase });
container.register <Cache >('Cache' , { useClass : RedisCache });
container.register <Mailer >('Mailer' , { useClass : ResendMailer });
container.register <Logger >('Logger' , { useClass : PinoLogger });
const app = container.resolve (App );
await app.start ();
}
bootstrap ();
Rules for the composition root:
It is the ONLY place that references concrete implementations
All other code depends on abstractions (interfaces/types)
Easy to swap implementations for testing or different environments
Testing with DI Unit tests — inject mocks directly:
describe ('OrderService' , () => {
let service : OrderService ;
let mockDb : jest.Mocked <Database >;
let mockMailer : jest.Mocked <Mailer >;
beforeEach (() => {
mockDb = {
insert : jest.fn (),
findById : jest.fn (),
} as any ;
mockMailer = {
send : jest.fn ().mockResolvedValue (undefined ),
} as any ;
service = new OrderService (mockDb, mockMailer);
});
it ('creates order and sends confirmation email' , async () => {
mockDb.insert .mockResolvedValue ({ id : '1' , status : 'created' });
await service.createOrder ({
email : 'user@test.com' ,
items : [{ productId : 'p1' , qty : 2 }],
});
expect (mockDb.insert ).toHaveBeenCalledWith ('orders' , expect.any (Object ));
expect (mockMailer.send ).toHaveBeenCalledWith ('user@test.com' , 'Order confirmed' );
});
});
Integration tests — override specific registrations:
describe ('OrderService (integration)' , () => {
let testContainer : typeof container;
beforeEach (() => {
testContainer = container.createChildContainer ();
testContainer.register <Mailer >('Mailer' , { useClass : NoopMailer });
});
it ('persists order to database' , async () => {
const service = testContainer.resolve (OrderService );
const order = await service.createOrder ({ });
expect (order.id ).toBeDefined ();
});
});
Best Practices
Depend on abstractions — Inject interfaces, not concrete classes.
Constructor injection only — Avoid property injection and service locator pattern.
Single composition root — Wire everything in one place at app startup.
Prefer singleton for stateless services — Transient/scoped only when state is per-request.
No new in business logic — If a class creates its own dependencies, it cannot be tested in isolation.
Avoid circular dependencies — Restructure into a shared module or use events.
Keep containers out of business logic — Only the composition root touches the container.
Use factory providers for runtime config — When a dependency needs config values.
Scope database connections per request — Prevent connection leaks and enable per-request transactions.
Test without the container — Unit tests should inject mocks via constructor, no container needed.
Common Pitfalls Pitfall Problem Fix Service locator anti-pattern container.resolve() called inside business logicInject via constructor; only resolve at the composition root Missing reflect-metadata Decorator-based DI fails silently Import reflect-metadata at app entry point Circular dependency Container throws at resolution time Break the cycle with events, mediator, or forwardRef() Overusing transient scope High memory usage, GC pressure Default to singleton; use transient only when stateful Injecting concrete classes Tight coupling, hard to mock Define interfaces and inject those Container in unit tests Tests become slow integration tests Inject mocks directly via constructor