>백엔드 개발 >파이썬 튜토리얼 >종속성 역전, IoC 및 DI 분석

종속성 역전, IoC 및 DI 분석

DDD
DDD원래의
2025-01-20 16:26:09282검색

Breaking Down Dependency Inversion, IoC, and DI

NestJS의 종속성 주입 시스템을 탐색하면서 종속성 역전, 제어 역전 및 종속성 주입에 대해 더 자세히 알아볼 수 있었습니다. 이러한 개념은 유사해 보이지만 서로 다른 문제에 대한 고유한 솔루션을 제공합니다. 이 설명은 개인적으로 재충전의 역할을 하며, 이러한 용어와 씨름하는 다른 사람들에게 유용한 가이드가 되기를 바랍니다.


  1. 종속성 역전 원리(DIP)

정의: 상위 수준 모듈은 하위 수준 모듈에 의존해서는 안 됩니다. 둘 다 추상화에 의존해야 합니다. 추상화는 세부사항에 의존해서는 안 됩니다. 세부 사항은 추상화에 따라 달라집니다.

의미:

소프트웨어에서 상위 수준 모듈은 핵심 비즈니스 로직을 캡슐화하는 반면, 하위 수준 모듈은 특정 구현(데이터베이스, API 등)을 처리합니다. DIP가 없으면 상위 수준 모듈은 하위 수준 모듈에 직접 의존하므로 유연성을 방해하고 테스트 및 유지 관리를 복잡하게 하며 하위 수준 세부 사항을 교체하거나 확장하기 어렵게 만드는 긴밀한 결합을 생성합니다.

DIP는 이러한 관계를 역전시킵니다. 직접 제어하는 ​​대신 상위 수준 모듈과 하위 수준 모듈 모두 공유 추상화(인터페이스 또는 추상 클래스)에 의존합니다.


DIP 없음

파이썬 예제

<code class="language-python">class EmailService:
    def send_email(self, message):
        print(f"Sending email: {message}")

class Notification:
    def __init__(self):
        self.email_service = EmailService()

    def notify(self, message):
        self.email_service.send_email(message)</code>

타입스크립트 예시

<code class="language-typescript">class EmailService {
    sendEmail(message: string): void {
        console.log(`Sending email: ${message}`);
    }
}

class Notification {
    private emailService: EmailService;

    constructor() {
        this.emailService = new EmailService();
    }

    notify(message: string): void {
        this.emailService.sendEmail(message);
    }
}</code>

문제:

  1. 긴밀한 결합: NotificationEmailService에 직접적으로 의존합니다.
  2. 제한된 확장성: SMSService로 전환하려면 Notification을 수정해야 합니다.

DIP와 함께

파이썬 예제

<code class="language-python">from abc import ABC, abstractmethod

class MessageService(ABC):
    @abstractmethod
    def send_message(self, message):
        pass

class EmailService(MessageService):
    def send_message(self, message):
        print(f"Sending email: {message}")

class Notification:
    def __init__(self, message_service: MessageService):
        self.message_service = message_service

    def notify(self, message):
        self.message_service.send_message(message)

# Usage
email_service = EmailService()
notification = Notification(email_service)
notification.notify("Hello, Dependency Inversion!")</code>

타입스크립트 예시

<code class="language-typescript">interface MessageService {
    sendMessage(message: string): void;
}

class EmailService implements MessageService {
    sendMessage(message: string): void {
        console.log(`Sending email: ${message}`);
    }
}

class Notification {
    private messageService: MessageService;

    constructor(messageService: MessageService) {
        this.messageService = messageService;
    }

    notify(message: string): void {
        this.messageService.sendMessage(message);
    }
}

// Usage
const emailService = new EmailService();
const notification = new Notification(emailService);
notification.notify("Hello, Dependency Inversion!");</code>

DIP의 장점:

  • 유연성: 구현을 쉽게 교체할 수 있습니다.
  • 테스트 가능성: 테스트를 위해 모의를 사용하세요.
  • 유지관리성: 하위 수준 모듈의 변경 사항은 상위 수준 모듈에 영향을 주지 않습니다.

  1. 제어 반전(IoC)

IoC는 종속성 제어가 클래스 내에서 관리되지 않고 외부 시스템(프레임워크)으로 전환되는 설계 원칙입니다. 전통적으로 클래스는 종속성을 생성하고 관리합니다. IoC는 이를 뒤집습니다. 즉, 외부 엔터티가 종속성을 주입합니다.


Python 예: IoC 없음

<code class="language-python">class SMSService:
    def send_message(self, message):
        print(f"Sending SMS: {message}")

class Notification:
    def __init__(self):
        self.sms_service = SMSService()  # Dependency created internally

    def notify(self, message):
        self.sms_service.send_message(message)</code>

TypeScript 예: IoC 없음

<code class="language-typescript">class SMSService {
    sendMessage(message: string): void {
        console.log(`Sending SMS: ${message}`);
    }
}

class Notification {
    private smsService: SMSService;

    constructor() {
        this.smsService = new SMSService(); // Dependency created internally
    }

    notify(message: string): void {
        this.smsService.sendMessage(message);
    }
}</code>

IoC가 없는 문제:

  1. 타이트한 커플링.
  2. 유연성이 낮습니다.
  3. 어려운 테스트.

Python 예제: IoC 사용

<code class="language-python">class EmailService:
    def send_email(self, message):
        print(f"Sending email: {message}")

class Notification:
    def __init__(self):
        self.email_service = EmailService()

    def notify(self, message):
        self.email_service.send_email(message)</code>

TypeScript 예: IoC 사용

<code class="language-typescript">class EmailService {
    sendEmail(message: string): void {
        console.log(`Sending email: ${message}`);
    }
}

class Notification {
    private emailService: EmailService;

    constructor() {
        this.emailService = new EmailService();
    }

    notify(message: string): void {
        this.emailService.sendEmail(message);
    }
}</code>

IoC의 이점:

  1. 느슨한 커플링.
  2. 간단한 구현 전환.
  3. 테스트 가능성이 향상되었습니다.

  1. 의존성 주입(DI)

DI는 객체가 외부 소스로부터 종속성을 받는 기술입니다. 이는 다음을 통해 종속성을 주입하는 IoC의 실제 구현입니다.

  1. 생성자 주입
  2. 세터 주입
  3. 인터페이스 주입

Python 예제: DI 프레임워크(injector 라이브러리 사용)

<code class="language-python">from abc import ABC, abstractmethod

class MessageService(ABC):
    @abstractmethod
    def send_message(self, message):
        pass

class EmailService(MessageService):
    def send_message(self, message):
        print(f"Sending email: {message}")

class Notification:
    def __init__(self, message_service: MessageService):
        self.message_service = message_service

    def notify(self, message):
        self.message_service.send_message(message)

# Usage
email_service = EmailService()
notification = Notification(email_service)
notification.notify("Hello, Dependency Inversion!")</code>

TypeScript 예: DI 프레임워크(tsyringe 라이브러리 사용)

<code class="language-typescript">interface MessageService {
    sendMessage(message: string): void;
}

class EmailService implements MessageService {
    sendMessage(message: string): void {
        console.log(`Sending email: ${message}`);
    }
}

class Notification {
    private messageService: MessageService;

    constructor(messageService: MessageService) {
        this.messageService = messageService;
    }

    notify(message: string): void {
        this.messageService.sendMessage(message);
    }
}

// Usage
const emailService = new EmailService();
const notification = new Notification(emailService);
notification.notify("Hello, Dependency Inversion!");</code>

DI의 장점:

  • 단순화된 테스트.
  • 확장성이 향상되었습니다.
  • 유지보수성이 향상되었습니다.

이 자세한 설명은 DIP, IoC, DI 간의 관계와 차이점을 명확하게 설명하고 강력하고 유지 관리가 가능한 소프트웨어를 구축하는 데 있어 각 요소의 기여를 강조합니다.

위 내용은 종속성 역전, IoC 및 DI 분석의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.