← Назад к вопросам

Как реализовывал принципы SOLID на практике?

2.0 Middle🔥 171 комментариев
#Архитектура и паттерны#ООП

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI29 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Реализация принципов SOLID на практике

Принципы SOLID — это фундамент чистого архитектурного дизайна, и я применял их постоянно в реальных проектах Node.js.

Single Responsibility Principle (SRP)

В одном из микросервисов обработки платежей я выделил отдельные классы для каждой ответственности:

// ❌ Плохо — множественная ответственность
class PaymentHandler {
  async process(payment) {
    // валидация
    // обработка платежа
    // отправка письма
    // логирование
    // обновление БД
  }
}

// ✅ Хорошо — каждый класс отвечает за одно
class PaymentProcessor {
  async process(payment) {
    // только обработка платежа
  }
}

class EmailNotificationService {
  async sendReceipt(email, data) {
    // только отправка писем
  }
}

class PaymentLogger {
  async log(transactionId, status) {
    // только логирование
  }
}

Open/Closed Principle (OCP)

При разработке системы различных способов оплаты я использовал абстрактный класс:

abstract class PaymentProvider {
  abstract async charge(amount: number): Promise<void>;
  abstract async refund(transactionId: string): Promise<void>;
}

class StripeProvider extends PaymentProvider {
  async charge(amount: number) { /* Stripe логика */ }
  async refund(transactionId: string) { /* Stripe возвраты */ }
}

class PayPalProvider extends PaymentProvider {
  async charge(amount: number) { /* PayPal логика */ }
  async refund(transactionId: string) { /* PayPal возвраты */ }
}

Таким образом, новый провайдер добавляется без изменения существующего кода.

Liskov Substitution Principle (LSP)

Все провайдеры заменяемы друг на друга благодаря единому интерфейсу:

class PaymentService {
  constructor(private provider: PaymentProvider) {}
  
  async processPayment(amount: number) {
    return this.provider.charge(amount);
  }
}

// Работает с любым провайдером
const stripeService = new PaymentService(new StripeProvider());
const paypalService = new PaymentService(new PayPalProvider());

Interface Segregation Principle (ISP)

Вместо одного толстого интерфейса я разделил на несколько узких:

// ❌ Плохо — клиент зависит от ненужных методов
interface PaymentProvider {
  charge(): void;
  refund(): void;
  validateCard(): void;
  storeCrypto(): void;
}

// ✅ Хорошо
interface Chargeable {
  charge(amount: number): Promise<void>;
}

interface Refundable {
  refund(transactionId: string): Promise<void>;
}

class CryptoBridgeProvider implements Chargeable, Refundable { }

Dependency Inversion Principle (DIP)

В высокоуровневых модулях зависимости от низкоуровневых передаются через конструктор:

class OrderService {
  constructor(
    private paymentProvider: PaymentProvider,
    private notificationService: EmailNotificationService,
    private logger: Logger
  ) {}

  async createOrder(order) {
    await this.paymentProvider.charge(order.amount);
    await this.logger.log("Order created");
    await this.notificationService.sendConfirmation(order.email);
  }
}

На практике это позволило нам легко тестировать через mock-объекты, быстро переключаться между провайдерами и поддерживать код в чистоте на протяжении всей разработки.

Как реализовывал принципы SOLID на практике? | PrepBro