yoongrammer

의존성 역전 원칙 (DIP: Dependency Inversion Principle) 본문

OOP

의존성 역전 원칙 (DIP: Dependency Inversion Principle)

yoongrammer 2022. 6. 19. 22:04
728x90

목차

    의존성 역전 원칙 (DIP: Dependency Inversion Principle)


    1. 상위 모듈은 하위 모듈에 의존해서는 안 되고 둘 다 추상화에 의존해야 한다.
    2. 추상화는 세부 사항에 의존해서는 안 되고 세부사항(구체적인 구현)은 추상화에 의존해야 한다.

    로버트 C. 마틴

     

    의존성 역전 원칙(DIP)은 변화하기 쉬운 것에 의존하지 말라는 원칙입니다.

    DIP를 지킴으로써 하위 모듈(or 클래스)에 대한 상위 모듈(or 클래스)의 종속성을 줄일 수 있습니다.

    • 상위 모듈(or 클래스): 도구로 작업을 실행하는 클래스
    • 하위 모듈(or 클래스): 작업을 실행하는데 필요한 도구

    DIP 적용 전


    다음 예를 보겠습니다.

    Calculator 클래스가 Add클래스를 사용하여 덧셈을 하는 예입니다.

    여기서 Calculator 클래스는 상위 모듈이고 Add클래스는 하위 모듈입니다.

    class Add:
    	def calculate(self, num1, num2):
    		ret = num1 + num2
    		print(f'{num1} + {num2} = {ret}')
    		return ret
    
    class Calculator:
    	def start(self, num1, num2):
    		operation = Add()
    		operation.calculate(num1, num2)
    
    if __name__ == '__main__':
    	cal = Calculator()
    	cal.start(1, 2)

    Output:

    1 + 2 = 3

    여기서 뺄셈을 추가하고 싶다면 Calculator 클래스를 수정해야 합니다.

     

    DIP 적용 후


    DIP적용 후 모습은 다음과 같습니다.

     

    Calculator는 Add클래스 대신 인터페이스 역할을 하는 CurrentOperation 추상 클래스에 의존하고 있고 구현체인 Add 및 Sub 클래스 또한 CurrentOperation 추상 클래스에 의존하고 있어 DIP를 만족하고 있습니다.

     

    이렇게 되면 Calculator는 구현체에 의존하고 있지 않기 때문에 구현 내용이 바뀌어도 수정할 필요가 없게 됩니다.

    from abc import ABC
    
    class CurrentOperation(ABC):
    	def calculate(self, num1, num2):
    		pass
    
    class Add(CurrentOperation):
    	def calculate(self, num1, num2):
    		ret = num1 + num2
    		print(f'{num1} + {num2} = {ret}')
    		return ret
    
    class Sub(CurrentOperation):
    	def calculate(self, num1, num2):
    		ret = num1 - num2
    		print(f'{num1} - {num2} = {ret}')
    		return ret
    
    class Calculator:
    	def __init__ (self, operation: CurrentOperation):
    		self.operation = operation
    	
    	def start(self, num1, num2):
    		self.operation.calculate(num1, num2)
    
    if __name__ == '__main__':
    	operation = Add()
    	cal = Calculator(operation)
    	cal.start(1, 2)

    Output:

    1 + 2 = 3

     

    이제 다음과 같이 Caclulator 클래스는 수정 없이 뺄셈을 사용할 수 있게 되었습니다.

    if __name__ == '__main__':
    	operation = Sub()
    	cal = Calculator(operation)
    	cal.start(1, 2)

    Output:

    1 - 2 = -1

    결론


    DIP는 상위 모듈을 구체적인 구현이 아닌 추상화(인터페이스)에 종속적으로 만들어 하위 모듈에 대한 상위 모듈의 종속성을 줄이는 것을 목표로 합니다.

     

    DIP를 지키면 종속성을 줄일 수 있기 때문에 유지관리 및 수정이 쉬운 코드를 작성할 수 있게 됩니다.

     

     

     

    728x90
    Comments