Skip to main content Skills Marketplace Descubra e explore skills de IA criadas pela comunidade.
Instalar com Codex ou Claude Copie este prompt, cole no Codex, Claude ou outro assistente e deixe que ele revise a página da skill e instale para você.
Copiar promptMostrar detalhes do prompt Um comando direto ignora o prompt de revisão. Verifique a origem antes de executá-lo.
npx skills add https://github.com/InugamiDev/ultrathink-oss --skill dependency-injectionO comando permanece em uma só linha. Role horizontalmente para revisá-lo antes de copiar.
Prefere uma cópia local? Baixe os arquivos disponíveis atualmente no SkillsMP.
Baixar Zip Baixando... Mais deste repositório 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.
Ocupações relacionadas SOC
Baseado na classificação ocupacional SOC
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