내가 알고 싶습니다 여기에 작업과 우리의 리드 개발자 중 하나의 패턴으로 DI를 소개하려고 해요 : 무엇 – 어떤 경우 -이다 단점 의존성 삽입 패턴을 사용하는가?
참고 주제에 대한 주관적인 논의가 아니라 가능한 경우 전체 목록을 찾고 있습니다.
설명 : XML 기반 (Spring과 같은) 또는 코드 기반 (Guice와 같은) 또는 “자가 롤링”여부와 상관없이 특정 프레임 워크가 아닌 Dependency Injection 패턴 ( Martin Fowler 의이 기사 참조) 에 대해 이야기하고 있습니다. .
편집 : 여기 에 / r / programming 에 대한 추가 토론 / ranting / 토론이 있습니다.
답변
몇 가지 사항 :
- DI는 책임이 더 분리되어 있기 때문에 일반적으로 클래스 수를 늘림으로써 복잡성을 증가시킵니다.
- 코드는 사용하는 의존성 주입 프레임 워크 (또는 더 일반적으로 DI 패턴을 구현하기로 결정한 방법)와 결합됩니다.
- 유형 해석을 수행하는 DI 컨테이너 또는 접근 방식은 일반적으로 약간의 런타임 페널티가 발생합니다 (매우 무시할 수는 있지만)
일반적으로 디커플링의 이점으로 인해 각 작업을 읽고 이해하기가 더 간단 해지지 만보다 복잡한 작업을 조율하는 복잡성이 증가합니다.
답변
객체 지향 프로그래밍, 스타일 규칙 및 기타 모든 것에서 흔히 발생하는 것과 동일한 기본 문제입니다. 사실 매우 일반적인 추상화는 너무 많은 추상화를하고 너무 많은 간접 성을 추가하고 일반적으로 좋은 기술을 과도하고 잘못된 곳에 적용하는 것이 가능합니다.
적용하는 모든 패턴 또는 기타 구성은 복잡성을 가져옵니다. 추상화와 간접 정보는 정보를 분산 시키며 때로는 관련이없는 세부 사항을 방해하지 않지만 때로는 정확히 무슨 일이 일어나고 있는지 이해하기 어렵게 만듭니다. 적용하는 모든 규칙은 융통성이 없어 최상의 방법 일 수있는 옵션을 배제합니다.
요점은 작업을 수행하고 강력하고 읽기 쉽고 유지 관리가 가능한 코드를 작성하는 것입니다. 아이보리 타워 빌더가 아닌 소프트웨어 개발자입니다.
관련 링크
http://thedailywtf.com/Articles/The_Inner-Platform_Effect.aspx
http://www.joelonsoftware.com/articles/fog0000000018.html
아마도 가장 간단한 형태의 의존성 주입 (웃지 마)이 매개 변수 일 것입니다. 종속 코드는 데이터에 의존하며 해당 데이터는 매개 변수를 전달하는 수단으로 주입됩니다.
그렇습니다. 어리 석고 객체 지향 의존성 주입 포인트를 다루지 않지만 함수형 프로그래머는 (첫 번째 클래스 함수가있는 경우) 이것이 필요한 유일한 의존성 주입이라고 알려줍니다. 여기서 중요한 것은 간단한 예를 들어 잠재적 인 문제를 보여주는 것입니다.
이 간단한 전통적인 함수를 생각해 봅시다-C ++ 구문은 중요하지 않지만 어떻게 든 철자를 써야합니다 …
void Say_Hello_World ()
{
std::cout << "Hello World" << std::endl;
}
텍스트 “Hello World”를 추출하고 주입하려는 종속성이 있습니다. 충분히 쉬운 …
void Say_Something (const char *p_text)
{
std::cout << p_text << std::endl;
}
원래보다 어떻게 융통성이 없습니까? 출력이 유니 코드 여야한다고 결정하면 어떨까요? 아마도 std :: cout에서 std :: wcout으로 전환하고 싶을 것입니다. 그러나 그것은 내 문자열이 char가 아니라 wchar_t이어야 함을 의미합니다. 모든 호출자를 변경하거나 (더 합리적으로) 이전 구현은 문자열을 변환하고 새 구현을 호출하는 어댑터로 대체됩니다.
그것은 우리가 원본을 유지한다면 필요하지 않은 유지 보수 작업입니다.
그리고 사소한 것처럼 보이면 Win32 API 에서이 실제 기능을 살펴보십시오 …
http://msdn.microsoft.com/en-us/library/ms632680%28v=vs.85%29.aspx
그것은 다루어야 할 12 가지 “종속성”입니다. 예를 들어, 화면 해상도가 너무 커지면 64 비트 좌표 값과 다른 버전의 CreateWindowEx가 필요할 수 있습니다. 그리고 예, 이미 구식 버전이 남아 있습니다. 아마도 이전 버전의 새로운 버전에 매핑 될 것입니다 …
http://msdn.microsoft.com/en-us/library/ms632679%28v=vs.85%29.aspx
이러한 “종속성”은 원래 개발자에게는 문제가 아닙니다. 해당 인터페이스를 사용하는 모든 사람은 종속성이 무엇인지, 지정 방법 및 의미가 무엇인지, 응용 프로그램을 위해 수행 할 작업을 찾아야합니다. 이곳에서 “기본 설정”이라는 단어가 삶을 훨씬 간단하게 만들 수 있습니다.
객체 지향 의존성 주입은 원칙적으로 다르지 않습니다. 클래스 작성은 소스 코드 텍스트와 개발자 시간 모두에서 오버 헤드이며, 해당 클래스가 일부 종속 객체 사양에 따라 종속성을 제공하도록 작성된 경우 종속 객체는 필요한 경우에도 해당 인터페이스를 지원하도록 잠겨 있습니다. 해당 객체의 구현을 대체합니다.
의존성 주입이 잘못되었다고 주장하는 것은 아닙니다. 그러나 어떤 좋은 기술이라도 과도하게 잘못 적용 할 수 있습니다. 모든 문자열을 추출하여 매개 변수로 변환 할 필요는 없지만 모든 하위 수준 동작을 고급 개체에서 추출하여 주입 가능한 종속성으로 변환 할 필요는 없습니다.
답변
여기 내 자신의 초기 반응이 있습니다 : 기본적으로 모든 패턴의 동일한 단점.
- 배우는데 시간이 걸린다
- 잘못 이해하면 선보다 더 많은 해로 이어질 수 있습니다
- 극단으로 가져 가면 이익을 정당화하는 것보다 더 많은 일이 될 수 있습니다
답변
Inversion of Control의 가장 큰 단점은 (DI는 아니지만 충분히 가깝습니다) 알고리즘의 개요를 볼 때 단일 지점을 갖는 것을 제거하는 경향이 있다는 것입니다. 기본적으로 코드를 분리 할 때 발생하는 현상입니다. 한 곳에서 볼 수있는 기능은 긴밀한 결합의 인공물입니다.
답변
나는 그러한 목록이 존재하지 않는다고 생각하지만 그 기사를 읽으십시오.
답변
지난 6 개월 동안 Guice (Java DI 프레임 워크)를 광범위하게 사용하고 있습니다. 전반적으로 나는 그것이 (특히 테스트 관점에서) 훌륭하다고 생각하지만, 특정 단점이 있습니다. 가장 주목할만한 점 :
- 코드를 이해하기가 더 어려워 질 수 있습니다.의존성 주입은 매우 독창적 인 방법으로 사용될 수 있습니다. 예를 들어 특정 IOStream (예 : @ Server1Stream, @ Server2Stream)을 삽입하기 위해 사용자 지정 주석을 사용하는 일부 코드를 발견했습니다. 이것이 효과가 있지만 특정 우아함을 인정할 것이지만, 코드를 이해하기 위해서는 Guice 주입을 이해하는 것이 전제 조건이됩니다.
- 프로젝트를 학습 할 때 더 높은 학습 곡선.이것은 포인트 1과 관련이 있습니다. 의존성 주입을 사용하는 프로젝트의 작동 방식을 이해하려면 의존성 주입 패턴과 특정 프레임 워크를 모두 이해해야합니다. 내가 현재 직장에서 시작했을 때 나는 Guice가 무대 뒤에서 무엇을하고 있는지에 대해 혼란스러워하는 몇 시간을 보냈다.
- 생성자가 커집니다. 기본 생성자 또는 팩토리를 사용하여 대부분 해결할 수 있습니다.
- 오류가 난독 화 될 수 있습니다. 이것의 가장 최근의 예는 2 개의 깃발 이름에 충돌이 있었다는 것입니다. Guice가 자동으로 오류를 삼키고 내 플래그 중 하나가 초기화되지 않았습니다.
- 런타임에 오류가 발생합니다. Guice 모듈을 잘못 구성하면 (원형 참조, 잘못된 바인딩 등) 컴파일시 대부분의 오류가 발견되지 않습니다. 대신 프로그램이 실제로 실행될 때 오류가 노출됩니다.
이제 내가 불평했습니다. 현재 프로젝트 및 다음 프로젝트에서 Guice를 계속 사용하겠다고 말하겠습니다. 의존성 주입은 훌륭하고 믿을 수 없을만큼 강력한 패턴입니다. 그러나 확실히 혼란 스러울 수 있으며 선택한 의존성 주입 프레임 워크에서 무엇이든 저주하는 데 거의 시간이 걸릴 것입니다.
또한 의존성 주입이 과도하게 사용될 수 있다는 다른 포스터에 동의합니다.
답변
DI가없는 코드는 스파게티 코드에 얽히게 될 위험이 잘 알려져 있습니다. 일부 증상은 클래스와 방법이 너무 커서 너무 많고 쉽게 변경, 분류, 리팩토링 또는 테스트 할 수 없다는 것입니다.
DI가 많이 사용 된 코드 는 각각의 작은 클래스가 개별 라비올리 너겟과 같은 라비올리 코드 일 수 있습니다. 하나의 작은 일만하고 단일 책임 원칙 을 고수하는 것이 좋습니다. 그러나 스스로 클래스를 살펴보면 시스템 전체가 무엇을하는지 알기가 어렵습니다. 왜냐하면 이것은 수많은 작은 부분이 모두 어떻게 맞는지에 달려 있기 때문입니다. 단지 작은 것의 큰 더미처럼 보입니다.
큰 클래스 내에서 큰 비트의 결합 된 코드의 스파게티 복잡성을 피함으로써 간단한 작은 클래스가 많고 이들 간의 상호 작용이 복잡한 또 다른 종류의 복잡성의 위험이 있습니다.
나는 이것이 치명적인 단점이라고 생각하지 않습니다-DI는 여전히 매우 가치가 있습니다. 한 가지만하는 작은 클래스를 가진 어느 정도의 라비올리 스타일이 좋을 것입니다. 초과하여도 스파게티 코드만큼 나쁘지 않다고 생각합니다. 그러나 너무 멀리 갈 수 있다는 것을 아는 것이 피하는 첫 단계입니다. 그것을 피하는 방법에 대한 토론 링크를 따르십시오.