태그 보관물: dependency-injection

dependency-injection

의존성 주입 : 프레임 워크를 사용해야합니까? 인스턴스를 만드는 함수 (때로는

최근에 앱을 테스트 할 수 있어야하기 때문에 의존성 주입을 많이 수행하는 Python 프로젝트에서 작업했지만 프레임 워크를 사용하지 않았습니다. 때로는 모든 종속성을 수동으로 연결하는 것이 약간 지루했지만 때로는 전반적으로 훌륭했습니다.

객체를 여러 곳에서 만들어야했을 때 프로덕션 인스턴스를 만드는 함수 (때로는 해당 객체의 클래스 메서드)가있었습니다. 이 함수는 해당 객체가 필요할 때마다 호출되었습니다.

테스트에서 동일한 작업을 수행했습니다. 여러 번 객체의 ‘테스트 버전’을 만들어야하는 경우 (즉, 모의 객체가 지원하는 실제 인스턴스)이 ‘테스트 버전’을 만드는 기능이있었습니다. 테스트에 사용될 클래스의

내가 말했듯이, 이것은 일반적으로 잘 작동했습니다.

이제 새 Java 프로젝트를 시작하고 있으며 DI 프레임 워크를 사용할지 아니면 수동으로 DI를 수행할지 결정합니다 (이전 프로젝트에서와 같이).

DI 프레임 워크를 사용한 작업이 어떻게 다른지, 그리고 수동 ‘바닐라’의존성 주입보다 어떤 방식으로 나쁘거나 나쁜지 설명하십시오.

편집 : 나는 또한 질문에 추가하고 싶습니다 : 프레임 워크없이 DI를 수동으로 수행하는 ‘전문가 수준의’프로젝트를 목격 했습니까?



답변

DI 컨테이너의 핵심은 추상화 입니다. DI 컨테이너는 이러한 설계 문제를 추상화합니다. 짐작할 수 있듯이 코드에 현저한 영향을 미치며 종종 생성자, 세터, 팩토리 및 빌더 수가 적습니다. 결과적으로 코드가 더 느슨하게 결합되어 (기본 IoC 로 인해 ) 더 깨끗하고 간단 해집니다. 비용이 없지는 않지만.

배경

몇 년 전, 그러한 추상화는 다양한 구성 파일을 작성해야했습니다 ( 선언적 프로그래밍 ). LOC의 수가 크게 줄어드는 것은 환상적이지만 LOCS는 줄어든 반면 구성 파일의 수는 약간 증가했습니다. 중소형 프로젝트의 경우 전혀 문제가되지 않았지만 더 큰 프로젝트의 경우 코드와 XML 설명자 사이에 “코드 어셈블리”가 50 % 흩어져있는 것이 문제가되었습니다. 그럼에도 불구하고 주요 문제는 패러다임 자체. 디스크립터가 사용자 정의를위한 공간을 거의 남기지 않았기 때문에 상당히 융통성이 없었습니다.

패러다임은 구성에 대한 컨벤션 으로 점차 바뀌었고 , 이는 구성 파일을 주석 또는 속성으로 교환합니다. XML이 할 수 없었던 유연성을 제공하면서 코드를 더 깨끗하고 단순하게 유지합니다.

아마도 이것은 지금까지 일한 방식과 관련하여 가장 중요한 차이 일 것입니다. 적은 코드와 더 많은 마법.

하락세로…

컨피규레이션에 대한 컨벤션은 추상화가 너무 무거워서 어떻게 작동하는지 거의 알 수 없습니다. 때로는 마술처럼 보이고 여기에 한 가지 더 단점이 있습니다. 일단 작동하면 많은 개발자는 작동 방식에 신경 쓰지 않습니다.

이것은 DI 컨테이너로 DI를 배운 사람들에게 핸디캡입니다. 이들은 컨테이너가 추상화 한 디자인 패턴, 모범 사례 및 원칙의 관련성을 완전히 이해하지 못합니다. 개발자들에게 DI와 그 장점에 대해 잘 알고 있는지 물어 보았으며 다음과 같이 대답했습니다.- 예, Spring IoC를 사용했습니다 . (이게 무슨 소리 야?!?)

이러한 각각의 “단점”에 동의하거나 동의하지 않을 수 있습니다. 겸손한 의견으로는 프로젝트에서 무슨 일이 일어나고 있는지 알아야합니다. 그렇지 않으면 우리는 그것을 완전히 이해하지 못합니다. 또한 DI가 무엇인지 알고 그것을 구현하는 방법에 대한 개념을 갖는 것도 고려할만한 장점입니다.

긍정적 인 측면에서는…

한마디 생산성 . 프레임 워크를 통해 실제로 중요한 것에 집중할 수 있습니다. 응용 프로그램의 사업.

언급 된 결점에도 불구하고, 우리 중 많은 사람들 (마감일과 비용에 의해 조절되는 직무)에게이 도구는 귀중한 자원입니다. 제 생각에는 이것이 DI 컨테이너 구현에 유리한 우리의 주요 논거가되어야합니다. 생산성 .

테스팅

순수한 DI 또는 컨테이너를 구현하든 테스트는 문제가되지 않습니다. 정반대. 동일한 컨테이너가 종종 단위 테스트를위한 모형을 제공합니다. 몇 년 동안 나는 테스트를 온도계로 사용했습니다. 그들은 컨테이너 시설에 크게 의존했는지 말해줍니다. 이 컨테이너는 setter 또는 생성자없이 개인 속성을 초기화 할 수 있기 때문에 이것을 말합니다. 그들은 거의 모든 장소에 부품을 주입 할 수 있습니다!

유혹하는 소리? 조심해! 함정에 빠지지 마십시오 !!

제안

컨테이너를 구현하기로 결정한 경우 모범 사례를 따르는 것이 좋습니다. 생성자, 설정자 및 인터페이스를 계속 구현하십시오. 프레임 워크 / 컨테이너가 사용하도록합니다 . 다른 프레임 워크로 쉽게 마이그레이션하거나 실제 프레임 워크를 제거 할 수 있습니다. 컨테이너에 대한 종속성을 크게 줄일 수 있습니다.

이 관행과 관련하여 :

DI 컨테이너를 사용하는 경우

내 대답은 DI 컨테이너를 주로 선호하는 자신의 경험에 의해 편향 될 것입니다.

이 주제에 대한 Mark Seeman의 흥미로운 기사를 찾을 수 있으며, 순수한 DI 구현 방법에 관한 질문에 대한 답변도 제공 됩니다.

마지막으로 Java에 관해 이야기한다면 먼저 JSR330-Dependency Injection을 살펴보십시오 .

요약

장점 :

  • 비용 절감 및 시간 절약. 생산력.
  • 더 적은 수의 구성 요소.
  • 코드가 더 단순 해지고 깨끗해집니다.

단점 :

  • DI는 타사 라이브러리에 위임됩니다. 우리는 그들의 장단점을 알고 있어야합니다.
  • 학습 곡선.
  • 그들은 빨리 좋은 습관을 잊게 만듭니다.
  • 프로젝트의 의존성 증가 (더 많은 라이브러리)
  • 리플렉션을 기반으로하는 컨테이너 에는 더 많은 리소스 (메모리)가 필요합니다. 자원에 의해 제약을받는 경우에 중요합니다.

순수한 DI와의 차이점 :

  • 코드가 적고 구성 파일 또는 주석이 더 많습니다.

답변

내 경험에 따르면, 의존성 주입 프레임 워크는 많은 문제를 야기합니다. 일부 문제는 프레임 워크와 툴링에 따라 다릅니다. 문제를 완화하는 관행이있을 수 있습니다. 그러나 이것은 내가 맞은 문제입니다.

비전 역 객체

경우에 따라 전역 객체, 즉 실행중인 응용 프로그램에 인스턴스가 하나만있는 객체를 주입하려고 할 수도 있습니다. 이것은 a MarkdownToHtmlRendererer, a DatabaseConnectionPool, api 서버의 주소 등일 수 있습니다. 이러한 경우 종속성 주입 프레임 워크는 매우 간단하게 작동하며 생성자에 필요한 종속성을 추가하면됩니다.

그러나 세계적이지 않은 객체는 어떻습니까? 현재 요청에 사용자가 필요한 경우 어떻게합니까? 현재 활성화 된 데이터베이스 트랜잭션이 필요한 경우 어떻게합니까? 이벤트를 방금 시작한 텍스트 상자 인 양식을 포함하는 div에 해당하는 HTML 요소가 필요한 경우 어떻게해야합니까?

DI 프레임 워크에서 사용한 솔루션은 계층 적 인젝터입니다. 그러나 이것은 주입 모델을 더 복잡하게 만듭니다. 계층의 어떤 계층에서 무엇이 주입 될지 파악하기가 더 어려워집니다. 주어진 개체가 응용 프로그램, 사용자, 요청, 기타 등등에 존재하는지 알기가 어려워집니다. 더 이상 종속성을 추가하여 작동시킬 수 없습니다.

도서관

종종 재사용 가능한 코드 라이브러리를 원할 것입니다. 여기에는 해당 코드에서 객체를 구성하는 방법에 대한 지침도 포함됩니다. 종속성 주입 프레임 워크를 사용하는 경우 일반적으로 바인딩 규칙이 포함됩니다. 라이브러리를 사용하려면 바인딩 규칙을 추가하십시오.

그러나 다양한 문제가 발생할 수 있습니다. 다른 구현에 바인딩 된 동일한 클래스로 끝날 수 있습니다. 라이브러리는 특정 바인딩이 존재할 것으로 예상 할 수 있습니다. 라이브러리가 일부 기본 바인딩을 재정 의하여 코드에서 이상한 일을 유발할 수 있습니다. 코드가 일부 기본 바인딩을 재정 의하여 라이브러리 코드가 이상한 일을 할 수 있습니다.

숨겨진 복잡성

팩토리를 수동으로 작성할 때 응용 프로그램의 종속성이 서로 어떻게 일치하는지에 대한 감각이 있습니다. 의존성 주입 프레임 워크를 사용하면 이것을 볼 수 없습니다. 대신, 객체는 조만간 모든 것이 거의 모든 것에 의존 할 때까지 점점 더 많은 의존성을 키우는 경향이 있습니다.

IDE 지원

IDE가 종속성 주입 프레임 워크를 이해하지 못할 수 있습니다. 수동 팩토리를 사용하면 생성자의 모든 호출자를 찾아서 객체가 생성 될 수있는 모든 위치를 파악할 수 있습니다. 그러나 DI 프레임 워크에서 생성 된 호출을 찾지 못합니다.

결론

의존성 주입 프레임 워크에서 무엇을 얻을 수 있습니까? 객체를 인스턴스화하는 데 필요한 간단한 상용구를 피할 수 있습니다. 나는 단순한 상용구를 없애기 위해 노력하고 있습니다. 그러나 단순한 상용구를 유지하는 것은 쉽습니다. 보일러 플레이트를 교체 할 경우 더 쉬운 것으로 교체해야합니다. 위에서 설명한 다양한 문제로 인해 프레임 워크 (적어도 서있는 것처럼)가 법안에 맞지 않는다고 생각합니다.


답변

Java + 종속성 주입 = 프레임 워크가 필요합니까?

아니.

DI 프레임 워크는 무엇을 구매합니까?

Java가 아닌 언어로 개체 생성이 발생합니다.


팩토리 메소드가 귀하의 요구에 충분히 적합하면 100 % 정통 포조 자바에서 무료로 프레임 워크가없는 Java에서 DI를 수행 할 수 있습니다. 그 이상으로 필요한 경우 다른 옵션이 있습니다.

4 개의 갱 (Gang of Four) 디자인 패턴은 많은 위대한 일을 수행하지만, 창조 패턴에 관해서는 항상 약점이있었습니다. 자바 자체에는 몇 가지 약점이 있습니다. DI 프레임 워크는 실제 주사보다 더 많은이 약점을 도와줍니다. 당신은 이미 그들없이 그것을하는 방법을 알고 있습니다. 그들이 당신을 얼마나 잘 할 것인가는 객체 구성에 얼마나 많은 도움이 필요한지에 달려 있습니다.

4의 갱 이후에 나온 많은 창조 패턴이 있습니다. Josh Bloch 빌더는 Java에 명명 된 매개 변수가 없다는 놀라운 해킹입니다. 그 외에도 많은 유연성을 제공하는 iDSL 빌더가 있습니다. 그러나 이들 각각은 중요한 작업과 상용구를 나타냅니다.

프레임 워크는이 테디 움의 일부로부터 당신을 구할 수 있습니다. 그들은 단점이 없습니다. 조심하지 않으면 프레임 워크에 의존 할 수 있습니다. 하나를 사용한 후 프레임 워크를 전환하고 직접 확인하십시오. XML이나 주석을 어떻게 든 일반화하더라도 프로그래밍 작업을 광고 할 때 나란히 언급 해야하는 두 가지 언어를 지원할 수 있습니다.

DI 프레임 워크의 힘에 매료되기 전에 시간이 걸리고 DI 프레임 워크가 필요하다고 생각할 수있는 기능을 제공하는 다른 프레임 워크를 조사하십시오. 많은 사람들이 단순한 DI 너머로 분기했습니다 . Lombok , AspectJslf4J를 고려하십시오 . 각각은 일부 DI 프레임 워크와 겹치지 만 각각 자체적으로 잘 작동합니다.

: 테스트로이하시기 바랍니다 모양의 원동력 정말 경우 의 JUnit (어떤 정말 xUnit의)Mockito (정말 어떤 모의) 당신의 인생을 장악해야 DI 프레임 워크를 생각하기 시작하기 전에.

당신이 좋아하는 것을 할 수 있지만, 진지한 작업을 위해서는 스위스 군용 칼보다 잘 채워진 도구 상자를 선호합니다. 이 선을 그리는 것이 더 쉽지만 일부는 선을 흐리게하기 위해 열심히 노력했습니다. 아무 문제가 없지만 선택에 어려움을 겪을 수 있습니다.


답변

클래스를 작성하고 종속성을 지정하는 것은 모델링 프로세스의 일부이며 재미있는 부분입니다. 대부분의 프로그래머가 프로그래밍을 즐기는 이유입니다.

사용할 구현과 클래스 구성 방법을 결정하는 것은 어떻게 든 구현되어야하며 응용 프로그램 구성의 일부입니다.

수동으로 공장을 작성하는 것은 지루한 작업입니다. DI 프레임 워크는 해결 될 수있는 종속성을 자동으로 해결하고 그렇지 않을 수있는 구성을 요구하여 더 쉽게 만듭니다.

최신 IDE를 사용하면 메소드와 사용법을 탐색 할 수 있습니다. 수동으로 팩토리를 작성하는 것은 클래스 생성자를 강조 표시하고 사용법을 보여줄 수 있으며 특정 클래스가 생성되는 위치와 방법을 보여줍니다.

그러나 DI 프레임 워크를 사용하더라도 객체 그래프 생성 구성 (지금부터 OGCC)과 같은 중심 위치를 가질 수 있으며 클래스가 모호한 종속성에 의존하는 경우 OGCC를 살펴보고 특정 클래스가 어떻게 구성되는지 확인할 수 있습니다. 바로 거기.

개인적으로 특정 생성자의 사용법을 볼 수 있다고 생각하면 반대 할 수 있습니다. 나는 당신에게 더 나은 것이 주관적 일뿐만 아니라 대부분 개인적인 경험에서 비롯된다고 말할 것입니다.

DI 프레임 워크에 의존하는 프로젝트에서 항상 작업했다면, 그 사실 만 알고 클래스의 구성을보고 싶을 때 항상 OGCC를 살펴보고 생성자가 어떻게 사용되는지 보려고하지 않을 것입니다 어쨌든 종속성이 모두 자동으로 연결되어 있음을 알기 때문입니다.

당연히 DI 프레임 워크를 모든 용도로 사용할 수있는 것은 아니며 지금도 공장 방법을 작성해야합니다. 매우 일반적인 경우는 컬렉션에 대한 반복 동안 종속성을 구성하는 것입니다. 여기서 각 반복은 다른 공통 인터페이스의 다른 구현을 생성해야하는 다른 플래그를 제공합니다.

결국 그것은 모든 것이 당신이 선호하는 것과 당신이 기꺼이 희생하려는 것 (공장을 쓰거나 투명성을 쓰는 시간)으로 나올 것입니다.


개인적인 경험 (경고 : 주관적)

DI 프레임 워크에 대한 아이디어가 마음에 들지만 PHP 개발자로 말하면 한 번만 사용했습니다. 제가 작업했던 팀이 응용 프로그램을 매우 빠르게 배포해야했기 때문에 공장을 만드는 데 시간을 허비하지 못했습니다. 그래서 우리는 단순히 DI 프레임 워크를 집어 들고 구성했고 어떻게 든 작동했습니다 .

대부분의 프로젝트에서 DI 프레임 워크 내에서 일어나는 흑 마법을 좋아하지 않기 때문에 팩토리를 수동으로 작성하는 것을 좋아합니다. 나는 클래스와 그 의존성을 모델링하는 책임을 맡은 사람이었습니다. 나는 디자인이 왜 그렇게 보이는지 결정하는 사람이었습니다. 따라서 클래스를 올바르게 구성하는 사람이 될 것입니다 (클래스가 인터페이스 대신 콘크리트 클래스와 같은 어려운 종속성을 사용하더라도).


답변

개인적으로 나는 DI 컨테이너를 사용하지 않으며 그것을 좋아하지 않습니다. 그 이유는 몇 가지 더 있습니다.

일반적으로 정적 종속성입니다. 따라서 모든 단점이 있는 서비스 로케이터 일뿐 입니다. 그런 다음 정적 종속성의 특성으로 인해 숨겨집니다. 당신은 그들을 다룰 필요가 없습니다. 그들은 이미 거기에 있습니다. 그리고 당신은 그것들을 통제하지 않기 때문에 위험합니다.

그것은 OOP 원칙 나누기 등의 결합과 같은, 데이비드 웨스트 의 레고 벽돌 개체 은유를.

따라서 프로그램의 진입 점에 최대한 가깝게 전체 개체를 작성하는 것이 좋습니다.


답변

이미 알고 있듯이 : 사용하는 언어에 따라 다른 관점이 있으며, 다른 문제는 비슷한 문제를 처리하는 방법을 취합니다.

의존성 주입과 관련해서는 다음과 같은 결과가 나옵니다. 의존성 주입이란 용어에서 알 수 있듯이 한 객체가 필요한 객체 해당 객체에 넣는 것 외에는 다른 방법과 대조됩니다. 유연성 향상을 위해 객체 생성객체 소비 를 분리 합니다 .

설계가 잘 배치되어있는 경우 일반적으로 종속성이 많은 클래스가 거의 없으므로 직접 또는 프레임 워크를 통해 종속성을 배선하는 것이 상대적으로 쉬워야하며 테스트를 작성하는 상용구의 양은 쉽게 관리 할 수 ​​있어야합니다.

즉, DI 프레임 워크가 필요하지 않습니다.

그럼에도 불구하고 왜 프레임 워크를 사용하고 싶습니까?

I) 상용구 코드를 피하십시오

공장이 작고 번거 롭다는 고통을 느끼는 프로젝트의 규모가 커지면 DI 프레임 워크를 사용해야합니다.

II) 프로그래밍에 대한 선언적 접근

자바는 한 번 살 때 XML 프로그래밍 은 지금 : 뿌리 주석 fairydust마법이 일어난다 .

그러나 진지하게 : 나는 이것에 대한 명확한 거꾸로 보입니다 . 필요한 위치와 빌드 방법 대신 필요한 것을 말하는 의도를 명확하게 전달합니다.


tl; dr

DI 프레임 워크는 코드베이스를 마술처럼 향상 시키지는 않지만 멋진 코드를 실제로 선명하게 보이도록 도와줍니다 . 필요할 때 사용하십시오. 프로젝트의 특정 시점에서 시간을 절약하고 구역질을 예방할 수 있습니다.


답변

예. Mark Seemann의 “Dependency Injection”이라는 제목의 책을 ​​읽어야 할 것입니다. 그는 몇 가지 모범 사례를 설명합니다. 당신이 말한 것 중 일부에 따르면, 당신은 혜택을 볼 수 있습니다. 작업 단위 (예 : 웹 요청) 당 하나의 컴포지션 루트 또는 하나의 컴포지션 루트를 갖는 것을 목표로해야합니다. 나는 당신이 만드는 모든 객체가 (메서드 / 생성자에 대한 매개 변수와 마찬가지로) 종속성으로 간주되므로 객체를 만드는 방법과 위치에 대해 신중해야한다고 생각합니다. 프레임 워크는 이러한 개념을 명확하게 유지하는 데 도움이됩니다. Mark의 책을 읽으면 질문에 대한 답 이상을 찾을 수 있습니다.