본문 바로가기

카테고리 없음

[Clean Architecture] - SOLID 원칙 ISP (4)

반응형

오늘은 SOLID 원칙 4번째인 ISP에 대해 알아본다. 
 

SOLID 원칙 시리즈

해당 시리즈는 로버트 C.마틴의 Clean Architecture 책을 보며 쉬운 이해를 위해 ChatGPT와 함께 공부한 내용을 정리해 놓은 글입니다.

 

SRP: 단일 책임 원칙

OCP: 개방-폐쇄 원칙

LSP: 리스코프 치환 원칙

ISP: 인터페이스 분리 원칙

DIP: 의존성 역전 원칙


 

ISP: 인터페이스 분리 원칙

- 클라이언트는 자신이 사용하지 않는 메서드에 의존하지 않아야 한다.
- 인터페이스는 사용자가 필요로 하는 기능만 제공하도록 작게 분리해야 하며, 불필요한 메서드를 포함하지 말아야 한다.
 
파이썬의 경우 동적 타입 언어로, 소스 코드 의존성이 없으며, ISP에 영향을 많이 받지 않는다고 한다. 또한, 파이썬에는 명시적인 인터페이스를 정의하는 키워드가 없기 때문에, Abstract Class로 개념만 익혀보고 넘어가자. 
 
아래와 같이 Printer 클래스와 이를 상속받는 MultiFunctionPrinter와 SimplePrinter가 있다고 하자. 

from abc import ABC, abstractmethod

class Printer(ABC):
    @abstractmethod
    def print_document(self, document):
        pass

    @abstractmethod
    def scan_document(self, document):
        pass

    @abstractmethod
    def fax_document(self, document):
        pass


class MultiFunctionPrinter(Printer):
    def print_document(self, document):
        print(f"Printing: {document}")

    def scan_document(self, document):
        print(f"Scanning: {document}")

    def fax_document(self, document):
        print(f"Faxing: {document}")

class SimplePrinter(Printer):
    def print_document(self, document):
        print(f"Printing: {document}")

 
여기서 SimplePrinter의 경우 몇개의 필요없는 함수가 있으나, 구현하지 않을 경우 오류가 발생한다. 불필요한 함수에 의존성이 부여되는 것이다. 
 
 
이를 해결하기 위해 각각의 기능(프린트, 스캔, 팩스)을 별도의 인터페이스로 분리하여 구현하자. 

from abc import ABC, abstractmethod

class Printable(ABC):
    @abstractmethod
    def print_document(self, document):
        pass

class Scannable(ABC):
    @abstractmethod
    def scan_document(self, document):
        pass

class Faxable(ABC):
    @abstractmethod
    def fax_document(self, document):
        pass

 

class SimplePrinter(Printable):
    def print_document(self, document):
        print(f"Printing: {document}")

class MultiFunctionPrinter(Printable, Scannable, Faxable):
    def print_document(self, document):
        print(f"Printing: {document}")

    def scan_document(self, document):
        print(f"Scanning: {document}")

    def fax_document(self, document):
        print(f"Faxing: {document}")

 
 
이런식으로 오퍼레이션을 인터페이스 단위로 분리하여 관리하면, 불필요한 것에 의존하는 상황을 없앨 수 있다!

반응형