파이썬에서 IoC / DI가 일반적이지 않은 이유는 무엇입니까?
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 컨테이너의 기능은 무엇입니까? 그것은 당신이 할 수 있습니다
- 독립적 인 구성 요소를 완벽한 어플리케이션에 연결 ...
- ... 런타임에.
"함께 연결"과 "런타임"이라는 이름이 있습니다.
- 스크립팅
- 동적
DI 컨테이너는 다이나믹 스크립팅 언어를위한 인터프리터 일뿐입니다. 사실, 일반적인 Java / .NET DI 컨테이너는 엉덩이 기반의, 때로는 XML 기반의 구문을 사용하는 매우 역동적 인 스크립팅 언어를위한 엉터리 해석 기일뿐입니다.
파이썬으로 프로그래밍 할 때, 아름답고 화려한 스크립팅 언어를 사용할 때 왜 못생긴 나쁜 스크립팅 언어를 사용하고 싶습니까? 실제로 더 일반적인 질문입니다. 거의 모든 언어로 프로그래밍 할 때 자이 썬과 IronPython을 사용할 때 왜 못생긴 나쁜 스크립팅 언어를 사용하고 싶습니까?
요약하자면, DI / IoC 의 실습 은 파이썬에서와 마찬가지로 Java에서와 마찬가지로 중요합니다. 그러나 DI / IoC 의 구현 은 언어에 내장되어 있으며 종종 너무 가벼워 완전히 사라집니다.
(여기에 유추 할 수있는 간단한 설명이 있습니다. 어셈블리에서 서브 루틴 호출은 상당히 중요합니다. 로컬 변수와 레지스터를 메모리에 저장하고, 리턴 주소를 어딘가에 저장하고, 호출하는 서브 루틴에 대한 명령 포인터를 변경해야합니다. 서브 루틴이 끝나면 서브 루틴으로 되돌아 가도록 준비하고, 수신자가 찾을 수있는 곳에 인수를 넣습니다. IOW : 어셈블리에서 "서브 루틴 호출"은 디자인 패턴이며 다음과 같은 언어가 있기 전에 서브 루틴 호출이 내장 된 포트란 사람들은 자신 만의 "서브 루틴 프레임 워크"를 구축하고있었습니다. 서브 루틴 프레임 워크를 사용하지 않기 때문에 서브 루틴 호출이 파이썬에서 "흔하지 않다"고 말할 수 있습니까?)
BTW : DI를 논리적으로 결론 짓는 모습의 예를 보려면 Gilad Bracha 의 Newspeak Programming Language 와 주제에 대한 그의 글을 살펴보십시오 .
그 중 일부는 파이썬에서 모듈 시스템이 작동하는 방식입니다. 모듈에서 가져 오기만하면 일종의 "단일"을 무료로 얻을 수 있습니다. 모듈에서 객체의 실제 인스턴스를 정의하면 모든 클라이언트 코드가 가져와 실제로 작동하고 완벽하게 구성 / 채워진 객체를 얻을 수 있습니다.
이는 실제 객체 인스턴스를 가져 오지 않는 Java와 대조적입니다. 즉, 항상 직접 인스턴스화해야합니다 (또는 일종의 IoC / DI 스타일 접근 방식 사용). 정적 팩토리 메소드 (또는 실제 팩토리 클래스)를 사용하여 모든 것을 직접 인스턴스화해야하는 번거 로움을 완화 할 수 있지만 매번 실제로 새 메소드를 작성하는 데 따른 자원 오버 헤드가 여전히 발생합니다.
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은 한두 줄의 일반 코드로 처리합니다. 이것이 기능적 프로그래밍 대 명령형 프로그래밍의 강점입니다.
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 달러 용어입니다. [...] 의존성 주입은 객체에 인스턴스 변수를 부여하는 것을 의미합니다. [...].
몇 년 동안 파이썬을 사용하지는 않았지만 다른 언어보다 동적으로 유형이 지정된 언어와 관련이 있다고 말할 수 있습니다. 간단한 예를 들어, Java의 경우, 표준으로 작성된 것을 테스트하고 싶다면 DI를 사용하고 PrintStream을 전달하여 작성중인 텍스트를 캡처하고 확인할 수 있습니다. 그러나 Ruby에서 작업 할 때 STDOUT의 'puts'메소드를 동적으로 대체하여 확인을 수행하여 DI를 완전히 그림에서 제외시킬 수 있습니다. 추상화를 생성하는 유일한 이유가 그것을 사용하는 클래스를 테스트하는 것 (파일 시스템 작업 또는 Java의 시계를 생각하는 것)이라면 DI / IoC는 솔루션에서 불필요한 복잡성을 만듭니다.
IoC / DI는 디자인 컨셉이지만 불행히도 종종 특정 언어 (또는 타이핑 시스템)에 적용되는 컨셉으로 간주됩니다. 의존성 주입 컨테이너가 파이썬에서 훨씬 더 인기를 얻고 싶습니다. Spring이 있지만 그것은 슈퍼 프레임 워크이며 "The Python Way"에 대한 많은 고려없이 Java 개념의 직접적인 포트 인 것 같습니다.
Python 3의 주석을 감안할 때 완전한 기능이지만 간단한 종속성 주입 컨테이너 ( https://github.com/zsims/dic)에 균열이 생기기로 결정했습니다 . 그것은 .NET 의존성 주입 컨테이너 (IMO가 그 공간에서 놀고 있다면 환상적입니다)의 일부 개념을 기반으로하지만 Python 개념으로 변경되었습니다.
사람들은 의존성 주입과 제어 역전이 더 이상 의미하는 것을 실제로 얻지 못한다는 것을 알았습니다.
제어 반전을 사용하는 실습은 다른 클래스 또는 함수에 의존하는 클래스 또는 함수를 갖는 것이지만 함수 코드 클래스 대신 인스턴스를 작성하는 대신 매개 변수로 수신하는 것이 좋으므로 느슨한 결합을 달성 할 수 있습니다. 그것은 더 많은 테스트 가능성과 liskov 대체 원칙을 아카이브하는 것으로 많은 이점을 가지고 있습니다.
인터페이스와 인젝션을 사용하면 코드를보다 지속 가능하게 만들 수 있습니다. 코드의 한 줄 (DI 구성에서 한 줄 또는 두 줄)을 다시 작성할 필요가 없기 때문에 동작을 쉽게 변경할 수 있기 때문입니다. 클래스가 기다리는 인터페이스를 구현하는 클래스는 인터페이스를 따르는 한 독립적으로 다를 수 있기 때문에 클래스의 동작을 변경하십시오. 코드를 분리하고 유지 관리하기 쉬운 최상의 전략 중 하나는 최소한 단일 책임, 대체 및 종속성 반전 원칙을 따르는 것입니다.
패키지 내에서 객체를 직접 인스턴스화하고 가져 와서 직접 주입 할 수있는 경우 DI 라이브러리가 무엇입니까? 자바에는 절차 적 섹션 (클래스 외부의 코드)이 없으므로 지루한 구성 xml에 들어가는 모든 것이 있으므로 지연로드 방식으로 종속성을 인스턴스화하고 주입 해야하는 클래스가 필요하므로 날려 버리지 않습니다. 파이썬에서는 코드의 "절차"(클래스 외부 코드) 섹션에 주입을 코딩하기 만하면됩니다.
실제로, 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!
예, 이것은 함수 / 클래스를 매개 변수화하는 간단한 형태로 볼 수 있지만 작동합니다. 따라서 파이썬의 기본 포함 배터리로도 충분합니다.
추신 : 나는 파이썬에서 간단한 부울 논리 를 동적으로 평가 하는이 순진한 접근 방식의 더 큰 예를 게시했습니다 .
"Jörg W Mittag"답변 : "DI / IoC의 Python 구현은 너무 가벼워 완전히 사라집니다."
이 문장을 백업하려면 Java에서 Python으로 포팅 된 유명한 Martin Fowler의 예제를 살펴보십시오. Python : Design_Patterns : Inversion_of_Control
위의 링크에서 볼 수 있듯이 파이썬의 "컨테이너"는 8 줄의 코드로 작성할 수 있습니다.
class Container:
def __init__(self, system_data):
for component_name, component_class, component_args in system_data:
if type(component_class) == types.ClassType:
args = [self.__dict__[arg] for arg in component_args]
self.__dict__[component_name] = component_class(*args)
else:
self.__dict__[component_name] = component_class
파이썬의 동적 특성으로 인해 사람들은 종종 다른 동적 프레임 워크가 필요하지 않다고 생각합니다. 클래스가 새로운 스타일의 '객체'에서 상속되면 새 변수를 동적으로 만들 수 있습니다 ( https://wiki.python.org/moin/NewClassVsClassicClass ).
즉 평범한 파이썬에서 :
#application.py
class Application(object):
def __init__(self):
pass
#main.py
Application.postgres_connection = PostgresConnection()
#other.py
postgres_connection = Application.postgres_connection
db_data = postgres_connection.fetchone()
그러나 https://github.com/noodleflake/pyioc를 살펴보십시오. 이것은 당신이 찾고있는 것일 수 있습니다.
즉 pyioc에서
from libs.service_locator import ServiceLocator
#main.py
ServiceLocator.register(PostgresConnection)
#other.py
postgres_connection = ServiceLocator.resolve(PostgresConnection)
db_data = postgres_connection.fetchone()
내 2cents는 대부분의 Python 응용 프로그램에서 필요하지 않으며 필요한 경우에도 많은 Java 증오 자 (및 개발자라고 생각하는 무능한 피들러)가 Java에서 인기가 있기 때문에 나쁜 것으로 간주 할 가능성이 있습니다 .
IoC 시스템은 복잡한 개체 네트워크가있는 경우 실제로 유용합니다. 여기서 각 개체는 여러 개체에 대한 종속성 일 수 있으며 결과적으로 자체는 다른 개체에 종속 될 수 있습니다. 이 경우 이러한 개체를 모두 한 번 정의하고 가능한 많은 암시 적 규칙에 따라 자동으로 구성 할 수있는 메커니즘이 필요합니다. 응용 프로그램 사용자 / 관리자가 간단한 방법으로 구성을 정의해야하는 경우, 이는 간단한 XML 파일 (구성이 될 수있는)에서 구성 요소를 읽을 수있는 IoC 시스템을 원하는 또 다른 이유입니다.
일반적인 Python 응용 프로그램은 복잡한 아키텍처없이 훨씬 간단하고 여러 스크립트 만 가능합니다. 개인적으로 나는 IoC가 실제로 무엇인지 알고 있습니다 (여기에서 특정 답변을 작성한 사람들과는 달리) 나는 제한된 Python 경험 (필자는 때가 아니라 어디서나 Spring을 사용하지 않음)에서 필요성을 느끼지 못했습니다. 개발 오버 헤드를 정당화하지는 않습니다.)
즉, IoC 접근 방식이 실제로 유용한 Python 상황이 있으며 실제로 Django가 그것을 사용한다는 것을 읽었습니다.
위와 같은 추론이 Java 세계의 Aspect Oriented Programming에 적용될 수 있지만 AOP가 실제로 가치가있는 경우의 수는 훨씬 제한적입니다.
파이썬에서 DI / IoC가 가능하고 쉽고 쉽고 아름답다는 점에서 @Jorg에 동의합니다. 누락 된 것은이를 지원하는 프레임 워크이지만 몇 가지 예외가 있습니다. 내 마음에 오는 몇 가지 예를 지적하려면 :
Django 주석을 사용하면 자신의 Comment 클래스를 사용자 지정 논리 및 양식에 연결할 수 있습니다. [더 많은 정보]
Django에서는 사용자 정의 프로파일 객체를 사용하여 사용자 모델에 연결할 수 있습니다. 이것은 완전히 IoC는 아니지만 좋은 접근 방법입니다. 개인적으로 주석 프레임 워크와 같이 구멍 사용자 모델을 바꾸고 싶습니다. [더 많은 정보]
제 생각에 의존성 주입과 같은 것은 엄격하고 복잡한 프레임 워크의 증상입니다. 코드 본문이 쉽게 변경하기에 너무 무거워지면 코드의 작은 부분을 선택하고 인터페이스를 정의한 다음 해당 인터페이스에 연결된 객체를 통해 사람들이 동작을 변경할 수 있도록해야합니다. 그것은 모두 좋고 훌륭하지만 처음에는 그런 종류의 복잡성을 피하는 것이 좋습니다.
정적 형식 언어의 증상이기도합니다. 추상화를 표현할 수있는 유일한 도구가 상속인 경우, 그것은 어디에서나 사용하는 것과 거의 같습니다. C ++은 매우 유사하지만 Java 개발자가 사용하는 모든 곳에서 빌더 및 인터페이스에 매료되지 않았습니다. 너무 많은 일반 코드를 작성하는 데 비용이 들지 않고 유연하고 확장 가능하다는 꿈을 가지고 과도한 부담을 느끼기 쉽습니다 . 문화적인 것 같아요.
일반적으로 파이썬 사람들은 작업에 적합한 도구를 선택하는 데 익숙하다고 생각합니다.이 도구는 무엇이든 할 수 있지만 가능한 구성 순열의 어색한 배열을 제공하는 하나의 진정한 도구 (천 가능한 플러그인 포함)가 아니라 일관되고 단순한 전체 도구입니다. . 필요한 경우 여전히 상호 교환 가능한 부분이 있지만, 오리 타이핑의 유연성과 언어의 상대적 단순성으로 인해 고정 인터페이스를 정의하는 큰 형식이 필요하지 않습니다.
Java의 강력한 유형과 달리. 파이썬의 오리 타이핑 동작은 객체를 쉽게 전달할 수있게합니다.
Java 개발자는 객체를 유연하게 유지하면서 클래스 구조와 객체 간의 관계를 구성하는 데 집중하고 있습니다. 이를 달성하기 위해서는 IoC가 매우 중요합니다.
파이썬 개발자는 작업 수행에 집중하고 있습니다. 필요할 때 수업을 연결하기 만하면됩니다. 그들은 수업의 종류에 대해 걱정할 필요조차 없습니다. qua 수있는 한 오리입니다! 이 자연은 IoC를위한 여지를 남기지 않습니다.
참고 URL : https://stackoverflow.com/questions/2461702/why-is-ioc-di-not-common-in-python
'IT' 카테고리의 다른 글
Twitter API 버전 1.1로 user_timeline을 검색하기위한 가장 간단한 PHP 예제 (0) | 2020.03.20 |
---|---|
PHP를 사용하여 폴더에서 모든 파일을 삭제 하시겠습니까? (0) | 2020.03.20 |
싱글 톤 : 어떻게 사용해야합니까 (0) | 2020.03.20 |
매개 변수 및 리턴 값의 포인터 대 값 (0) | 2020.03.20 |
복제하기 전에 github 저장소의 크기를 보시겠습니까? (0) | 2020.03.20 |