파이썬 Dependency Injection (의존성 주입)

Parker cho·2021년 7월 10일
3

파이썬 정복

목록 보기
2/2

개요

개발을 하다보면 의존성 주입이 필요한 경우가 생긴다. 예를 들어 아래와 같은 코드에서 우리는 어떻게 의존성 주입을 적용해야 할까?

의존성 주입 이전

class PngConversion:
  def converse(data: Data):
    # png conversion algorithm
    return data
  
class JPEGConversion:
  def converse(data: Data):
    # jpeg conversion algorithm
    return data
  
class Transformer:
  def __init__(self, data: Data):
    self.converser = PngConversion()
    self.data = data
  def converse(self):
    self.converser.converse(self.data)

코드를 이런식으로 구성하면 나중에 다른 Conversion 객체의 메서드를 사용하고 싶을 경우에 Transformer 클래스안에 있는 코드를 수정해야 하는 불편함이 생긴다.

현재 코드에서는 상위 클래스(Transformer) 와 하위 클래스(PngConversion) 사이의 강한 결합이 생긴다. 상위 클래스의 동작이 하위 클래스의 구현에 영향을 받는 것이다.

의존 관계 역전 원칙 (DIP) 를 지키기 위해 상위 클래스를 추상 클래스에 의존하게 만들어야 한다.

의존 관계 역전 원칙❓

의존 관계 역전 원칙(Dependency inversion Principle)은 소프트웨어 모듈들을 분리하는 특정 형식을 지칭한다. 이 원칙을 따르면, 상위 계층(정책 결정)이 하위 계층(세부 사항)에 의존하는 전통적인 의존관계를 반전(역전)시킴으로써 상위 계층이 하위 계층의 구현으로부터 독립되게 할 수 있다
첫째, 상위 모듈은 하위 모듈에 의존해서는 안된다. 상위 모듈과 하위 모듈 모두 추상화에 의존해야 한다.
둘째, 추상화는 세부 사항에 의존해서는 안된다. 세부사항이 추상화에 의존해야 한다.
-위키백과-

의존성 주입 이후

from abc import ABCMeta, abstractmethod
class Conversion(metaclass=ABCMeta):
  @abstractmethod
  def converse(data: Data):
    pass
    
class PngConversion(Conversion):
  def converse(data: Data):
    # png conversion algorithm
    return data
  
class JPEGConversion(Conversion):
  def converse(data: Data):
    # jpeg conversion algorithm
    return data
  
class Transformer:
  def __init__(self, data: Data, converser: Conversion):
    self.converser = converser
    self.data = data

  def converse(self):
    self.converser.converse(self.data)
    

Transformer(data, PngConversion()).converse()
Transformer(data, JPEGConversion()).converse()

위의 코드처럼 Transformer의 생성자 인자로 추상클래스를 상속받은 클래스를 넘겨줌으로써 의존성 주입(DI)
을 구현할 수 있다.

인자를 넘겨주는 방식말고도 파이썬 데코레이터를 활용하여 구현 할 수 있는 방법도 있다.

import inject
from abc import ABCMeta, abstractmethod
class Conversion(metaclass=ABCMeta):
  @abstractmethod
  def converse(data: Data):
    pass
    
class PngConversion(Conversion):
  def converse(data: Data):
    # png conversion algorithm
    return data
  
class JPEGConversion(Conversion):
  def converse(data: Data):
    # jpeg conversion algorithm
    return data
  
class Transformer:

  @inject.autoparams()
  def __init__(self, data: Data, converser: Conversion):
    self.converser = converser
    self.data = data

  def converse(self):
    self.converser.converse(self.data)

transformer = Transformer(data)
transformer.converse()
profile
true nobility is being superior to your former self

1개의 댓글

comment-user-thumbnail
2021년 7월 22일

@inject.autoparams() 을 활용하면 거기에 png, jpg 어떤 컨버터가 들어갈지 어떻게 정해지는지 알수있을까요..??

답글 달기