--- title: Single Responsibility for Services impact: CRITICAL impactDescription: "40%+ improvement in testability" tags: architecture, services, single-responsibility --- ## Single Responsibility for Services Each service should have a single, well-defined responsibility. Avoid "god services" that handle multiple unrelated concerns. If a service name includes "And" or handles more than one domain concept, it likely violates single responsibility. This reduces complexity and improves testability by 40%+. **Incorrect (god service anti-pattern):** ```typescript // God service anti-pattern @Injectable() export class UserAndOrderService { constructor( private userRepo: UserRepository, private orderRepo: OrderRepository, private mailer: MailService, private payment: PaymentService, ) {} async createUser(dto: CreateUserDto) { const user = await this.userRepo.save(dto); await this.mailer.sendWelcome(user); return user; } async createOrder(userId: string, dto: CreateOrderDto) { const order = await this.orderRepo.save({ userId, ...dto }); await this.payment.charge(order); await this.mailer.sendOrderConfirmation(order); return order; } async calculateOrderStats(userId: string) { // Stats logic mixed in } async validatePayment(orderId: string) { // Payment logic mixed in } } ``` **Correct (focused services with single responsibility):** ```typescript // Focused services with single responsibility @Injectable() export class UsersService { constructor(private userRepo: UserRepository) {} async create(dto: CreateUserDto): Promise { return this.userRepo.save(dto); } async findById(id: string): Promise { return this.userRepo.findOneOrFail({ where: { id } }); } } @Injectable() export class OrdersService { constructor(private orderRepo: OrderRepository) {} async create(userId: string, dto: CreateOrderDto): Promise { return this.orderRepo.save({ userId, ...dto }); } async findByUser(userId: string): Promise { return this.orderRepo.find({ where: { userId } }); } } @Injectable() export class OrderStatsService { constructor(private orderRepo: OrderRepository) {} async calculateForUser(userId: string): Promise { // Focused stats calculation } } // Orchestration in controller or dedicated orchestrator @Controller('orders') export class OrdersController { constructor( private orders: OrdersService, private payment: PaymentService, private notifications: NotificationService, ) {} @Post() async create(@CurrentUser() user: User, @Body() dto: CreateOrderDto) { const order = await this.orders.create(user.id, dto); await this.payment.charge(order); await this.notifications.sendOrderConfirmation(order); return order; } } ``` Reference: [NestJS Providers](https://docs.nestjs.com/providers)