파이썬에서 IoC / DI가 일반적이지 않은 이유는 무엇입니까? 워크 및 Java

Java IoC / DI 는 웹 애플리케이션, 거의 모든 사용 가능한 프레임 워크 및 Java EE에서 광범위하게 사용되는 매우 일반적인 관행입니다. 다른 한편으로, 큰 파이썬 웹 응용 프로그램도 많이 있지만 Zope (코드가 정말 끔찍해야한다고 들었습니다) 외에도 IoC는 Python 세계에서 흔하지 않은 것 같습니다. (내가 틀렸다고 생각하면 몇 가지 예를 들어보십시오).

물론 파이썬, 예를 들어 스프링 피톤 에 사용할 수있는 널리 사용되는 Java IoC 프레임 워크의 여러 복제본이 있습니다 . 그러나 그들 중 누구도 실제로 사용되지 않는 것 같습니다. 적어도, 나는 그런 것을 사용하는 Django 또는 sqlalchemy + <insert your favorite wsgi toolkit here>기반 웹 응용 프로그램을 본 적이 없습니다 .

제 생각에 IoC는 합리적인 장점을 가지고 있으며 django-default-user-model을 쉽게 대체 할 수 있지만 파이썬에서 인터페이스 클래스와 IoC를 광범위하게 사용하는 것은 약간 이상하고»pythonic«이 아닙니다. 그러나 누군가 IoC가 파이썬에서 널리 사용되지 않는 이유에 대해 더 잘 설명하고 있습니다.



답변

실제로 DI / IOC의이 있다고 생각하지 않는다 파이썬에서 드문 일. 무엇 이다 드문 그러나, DI / IOC의의입니다 프레임 워크 / 컨테이너 .

DI 컨테이너의 기능은 무엇입니까? 그것은 당신이 할 수 있습니다

  1. 독립적 인 구성 요소를 완벽한 어플리케이션에 연결 …
  2. … 런타임에.

“함께 연결”과 “런타임”이라는 이름이 있습니다.

  1. 스크립팅
  2. 동적

따라서 DI 컨테이너는 다이나믹 스크립팅 언어의 해석 기일뿐입니다. 사실, 일반적인 Java / .NET DI 컨테이너는 엉덩이 기반, 때로는 XML 기반의 구문을 사용하는 매우 역동적 인 스크립팅 언어를위한 엉터리 해석 기일뿐입니다.

파이썬으로 프로그래밍 할 때, 아름답고 화려한 스크립팅 언어를 사용할 때 왜 못생긴 나쁜 스크립팅 언어를 사용하고 싶습니까? 실제로는 더 일반적인 질문입니다. 거의 모든 언어로 프로그래밍 할 때 자이 썬과 아이언 파이썬을 사용할 때 왜 못생긴 나쁜 스크립팅 언어를 사용하고 싶습니까?

요약하자면, DI / IoC 의 관행 은 정확히 같은 이유로 Java에서와 마찬가지로 Python에서도 중요합니다. 그러나 DI / IoC 의 구현 은 언어에 내장되어 있으며 종종 너무 가벼워 완전히 사라집니다.

(여기에 유추 할 수있는 간단한 설명이 있습니다. 어셈블리에서 서브 루틴 호출은 상당히 중요한 일입니다. 로컬 변수와 레지스터를 메모리에 저장하고, 리턴 주소를 어딘가에 저장하고, 호출하는 서브 루틴에 대한 명령 포인터를 변경해야합니다. 서브 루틴이 끝나면 서브 루틴으로 되돌아 가도록하고, 수신자가 찾을 수있는 곳에 인수를 넣습니다. IOW : 어셈블리에서 “서브 루틴 호출”은 디자인 패턴이며 다음과 같은 언어가 있기 전에 서브 루틴 호출이 내장 된 포트란 사람들은 자신 만의 “서브 루틴 프레임 워크”를 구축하고있었습니다. 서브 루틴 프레임 워크를 사용하지 않기 때문에 서브 루틴 호출이 파이썬에서 “흔하지 않다”고 말할 수 있습니까?)

BTW : DI를 논리적으로 결론 짓는 모습에 대한 예를 보려면 Gilad BrachaNewspeak Programming Language 와 주제에 대한 글을 살펴보십시오 .


답변

그 중 일부는 파이썬에서 모듈 시스템이 작동하는 방식입니다. 모듈에서 가져 오기만하면 일종의 “단일”을 무료로 얻을 수 있습니다. 모듈에서 객체의 실제 인스턴스를 정의하면 모든 클라이언트 코드가 가져와 실제로 작동하고 완벽하게 구성 / 채워진 객체를 얻을 수 있습니다.

이는 실제 객체 인스턴스를 가져 오지 않는 Java와 대조적입니다. 즉, 항상 직접 인스턴스화해야합니다 (또는 일종의 IoC / DI 스타일 접근 방식 사용). 정적 팩토리 메소드 (또는 실제 팩토리 클래스)를 사용하여 모든 것을 직접 인스턴스화해야하는 번거 로움을 완화 할 수 있지만 매번 실제로 새 메소드를 작성하는 데 따른 자원 오버 헤드가 여전히 발생합니다.


답변

IoC와 DI는 성숙한 파이썬 코드에서 매우 일반적입니다. 오리 타이핑 덕분에 DI를 구현하기 위해 프레임 워크가 필요하지 않습니다.

가장 좋은 예는 다음을 사용하여 Django 애플리케이션을 설정하는 방법입니다 settings.py.

# settings.py
CACHES = {
    'default': {
        'BACKEND': 'django_redis.cache.RedisCache',
        'LOCATION': REDIS_URL + '/1',
    },
    'local': {
        'BACKEND': 'django.core.cache.backends.locmem.LocMemCache',
        'LOCATION': 'snowflake',
    }
}

Django Rest Framework는 DI를 많이 활용합니다.

class FooView(APIView):
    # The "injected" dependencies:
    permission_classes = (IsAuthenticated, )
    throttle_classes = (ScopedRateThrottle, )
    parser_classes = (parsers.FormParser, parsers.JSONParser, parsers.MultiPartParser)
    renderer_classes = (renderers.JSONRenderer,)

    def get(self, request, *args, **kwargs):
        pass

    def post(self, request, *args, **kwargs):
        pass

알림 ( 출처 ) :

“종속성 주입”은 5 센트 개념의 25 달러 용어입니다. […] 의존성 주입은 객체에 인스턴스 변수를 제공하는 것을 의미합니다. […].


답변

Django는 제어 역전을 잘 활용합니다. 예를 들어, 구성 파일이 데이터베이스 서버를 선택한 다음 프레임 워크는 데이터베이스 클라이언트에 적절한 데이터베이스 랩퍼 인스턴스를 제공합니다.

차이점은 파이썬에는 일류 타입이 있다는 것입니다. 클래스를 포함한 데이터 유형 자체는 객체입니다. 특정 클래스를 사용하려는 경우 클래스 이름을 지정하십시오. 예를 들면 다음과 같습니다.

if config_dbms_name == 'postgresql':
    import psycopg
    self.database_interface = psycopg
elif config_dbms_name == 'mysql':
    ...

이후 코드는 다음을 작성하여 데이터베이스 인터페이스를 작성할 수 있습니다.

my_db_connection = self.database_interface()
# Do stuff with database.

Java 및 C ++에 필요한 상용구 팩토리 기능 대신 Python은 한두 줄의 일반 코드로이를 수행합니다. 이것이 기능적 프로그래밍 대 명령형 프로그래밍의 강점입니다.


답변

사람들은 의존성 주입과 제어 역전이 더 이상 의미하는 것을 실제로 얻지 못한다는 것을 알았습니다.

제어 반전을 사용하는 실습은 다른 클래스 또는 함수에 의존하는 클래스 또는 함수를 갖는 것이지만 함수 코드 클래스 대신 인스턴스를 작성하는 대신이를 매개 변수로 수신하는 것이 좋으므로 느슨한 결합을 달성 할 수 있습니다. 그것은 더 많은 테스트 가능성과 liskov 대체 원칙을 아카이빙하는 데 많은 이점이 있습니다.

인터페이스와 인젝션을 사용하면 코드를보다 지속 가능하게 만들 수 있습니다. 코드의 한 줄 (DI 구성에서 한 줄 또는 두 줄)을 다시 작성할 필요가 없기 때문에 동작을 쉽게 변경할 수 있기 때문입니다. 클래스가 기다리는 인터페이스를 구현하는 클래스는 인터페이스를 따르는 한 독립적으로 다를 수 있기 때문에 클래스의 동작을 변경하십시오. 코드를 분리하고 유지 관리하기 쉬운 최상의 전략 중 하나는 최소한 단일 책임, 대체 및 종속성 반전 원칙을 따르는 것입니다.

패키지 내에서 객체를 직접 인스턴스화하고 가져 와서 직접 주입 할 수있는 경우 DI 라이브러리가 무엇입니까? 자바에는 절차 적 섹션 (클래스 외부의 코드)이 없으므로 지루한 구성 xml에 들어가는 모든 것이 있으므로 지연로드 방식에 의존성을 인스턴스화하고 주입 해야하는 클래스가 필요하므로 날려 버리지 않습니다. 파이썬에서는 코드의 “절차”(클래스 외부 코드) 섹션에 주입을 코딩하기 만하면됩니다.


답변

몇 년 동안 파이썬을 사용하지는 않았지만 다른 언어보다 동적으로 유형이 지정된 언어와 관련이 있다고 말할 수 있습니다. 간단한 예를 들어, Java의 경우, 표준으로 작성된 것을 테스트하고 싶다면 DI를 사용하고 PrintStream을 전달하여 작성중인 텍스트를 캡처하고 확인할 수 있습니다. 그러나 Ruby에서 작업 할 때 STDOUT의 ‘puts’메소드를 동적으로 대체하여 확인을 수행하고 DI를 완전히 그림에서 제외시킵니다. 추상화를 생성하는 유일한 이유가 그것을 사용하는 클래스를 테스트하는 것 (파일 시스템 작업 또는 Java의 시계를 생각하는 것)이라면 DI / IoC는 솔루션에서 불필요한 복잡성을 만듭니다.


답변

실제로 DI로 충분히 깨끗하고 컴팩트 한 코드를 작성하는 것은 매우 쉽습니다 (필자는 , 그때는 pythonic 일지 모르겠지만 어쨌든 :)).

def polite(name_str):
    return "dear " + name_str

def rude(name_str):
    return name_str + ", you, moron"

def greet(name_str, call=polite):
    print "Hello, " + call(name_str) + "!"

_

>>greet("Peter")
Hello, dear Peter!
>>greet("Jack", rude)
Hello, Jack, you, moron!

예, 이것은 함수 / 클래스를 매개 변수화하는 간단한 형태로 볼 수 있지만 작동합니다. 따라서 파이썬의 기본 포함 배터리로도 충분합니다.

추신 : 나는 또한 파이썬에서 간단한 부울 논리동적으로 평가할 때이 순진한 접근법의 더 큰 예를 게시했습니다 .