2009-10-16 10 views
39

나는 의존성 주입이 실제로 "나는 내 마음을 결정할 수 없다"라고 불리워 야한다고 생각했다. 이것은 바보 같이 들릴지도 모르지만 실제로 Dependency Injection (DI)을 사용해야하는 이유에 관한 것입니다. 더 높은 수준의 느슨한 결합을 달성하기 위해 DI를 사용해야한다고 종종 말하면서, 나는 그 부분을 얻습니다. 하지만 실제로 ... 내 선택은 MS SQL이나 MySQL에 떨어졌을 때 얼마나 자주 내 데이터베이스를 변경합니까? 매우 드문 일입니까?의존성 주입을 사용하는 경우

누군가 DI가 갈 길이 란 매우 매력적인 이유가 있습니까?

+3

나는 지금까지 당신의 모든 이유가 마음에 든다. 나는 그것이 DI를 "얻는"대부분 숙련 된 프로그래머라고 생각한다. 내가 이해하는 한 DI는 품질에 관한 것입니다. 우리는 프로그래머로서 가능한 한 최고 수준의 소프트웨어를 생산하기를 원하며이를 테스트하는 것이 도움이됩니다. 나는 지난 몇 년 동안 많은 코드를 작성해 왔으며, 10 년이 지난 지금 50 % 이상이 여전히 실행 중이고 DI가 없다고 말하면 기쁩니다. 어쩌면 내가 DI에 대해 왜 조금 비판적인지 이해하는 데 도움이 될까요? – CodeMonkey

+0

분명히 DI는 상대적으로 새로운 말입니다. 따라서 물론 고품질의 소프트웨어를 작성할 수 있습니다. 그러나 테스트 프레임 워크 및 TDD와 같은 것들이 발전함에 따라 DI는 테스트를 작성하고 미래에 유지할 수있는 코드 (커플 링)를 작성하는 것을 훨씬 쉽게 만듭니다. – digiarnie

답변

44

두 단어, 단위 테스트.

DI의 가장 큰 이유 중 하나는 데이터베이스에 도달하지 않고도 단위 테스트를 쉽게하고 '테스트'데이터 설정에 대해 걱정할 필요가 있다는 것입니다.

+2

그래서 당신은 데이터베이스를 연결 해제하는 것에 대해 이야기하고 있습니다. 유닛 테스트 중에 DB를 변경하는 대신 위조 된 객체를 사용하여 "가짜"라고 말하고 있습니다 ... 음 ... 합리적인 논의처럼 들립니다 !! – CodeMonkey

+0

하지만 테스트 데이터베이스이므로 내 데이터베이스가 정말로 중요합니까 ?? – CodeMonkey

+5

테스트는 실제 데이터베이스를 손상시키지 않고 훨씬 빠르게 실행됩니다. 또한 특정 사례를 테스트 할 때 모의 개체에서 특정 사례를 설정하는 것이 훨씬 쉽고 테스트 데이터베이스가 올바른 상태인지 아닌지 걱정할 필요가 없습니다. –

1

느슨한 커플 링과는 별도로 DI 덕분에 모든 유형의 테스트가 훨씬 쉽게 이루어집니다. 테스트중인 클래스의 기존 종속성을 모의 (mock), 더미 또는 다른 버전으로 대체 할 수 있습니다. 클래스가 의존성을 직접 인스턴스화하여 만들어지면 필요에 따라 클래스를 "스텁"하는 것이 어렵거나 불가능할 수 있습니다.

+0

"stub"과 "mock"이라는 용어에 대해 자세히 설명해 주시겠습니까? "mock"은 내가 "가짜"라고 부르는 것입니다 - 객체 – CodeMonkey

+2

스텁으로 저는 ""다른 어떤 의존성을 " 테스트. 모의 (mock) 란 jock이나 mockito (물론 자바를 사용한다면)와 같은 라이브러리를 사용하여 "모의 (mock)"객체에 기대를 선언하는 프록시를 만드는 것을 의미한다. 또한 종속성의 인터페이스를 구현하여 더미 버전의 클래스를 만들 수도 있습니다. – digiarnie

+0

객체를 모의 할 때, di registery에 등록하거나 단순히 더미 객체를 전달합니까? through 생성자를 호출합니다. – liang

5

DB 예제에서 반쯤 동의하지만 DI를 사용하는 데 도움이되는 것으로 보이는 큰 것 중 하나는 내가 데이터베이스 위에 구축 한 레이어를 테스트하는 데 도움이된다는 것입니다.

예를 들어 ...

데이터베이스가 있습니다.

데이터베이스를 액세스하고 반환

당신은 이전 항목의 객체를 가지고 그들과 함께 약간의 로직을 비즈니스 도메인 개체가 개체 코드를 가지고있다.

비즈니스 도메인 논리와 데이터 액세스를 병합하면 도메인 개체를 테스트하기가 어려워 질 수 있습니다. DI를 사용하면 자신의 데이터 액세스 개체를 도메인에 삽입 할 수 있으므로 테스트 또는 데모 용 데이터베이스에 의존하지 않습니다 (일부 데이터가 데이터베이스 대신 XML에서 가져온 데모 실행).

타사 구성 요소와 프레임 워크를 추상화하면 도움이됩니다.

테스트 예 외에도 DI가 Design by Contract 방식을 통해 사용될 수있는 몇 가지 장소가 있습니다. 삽입하려는 오브젝트의 메소드를 호출하는 일종의 처리 엔진을 작성하는 것이 적절할 수 있습니다. 진정으로 "처리"하지는 않지만 제공하는 각 객체마다 다른 구현이있는 메소드를 실행합니다.

모든 비즈니스 도메인 개체가 프로세서에 주입 된 후 호출 된 "저장"기능을 가진 예제를 보았습니다. 프로세서는 구성 정보로 구성 요소를 수정하고 저장은 객체의 기본 상태를 처리했습니다. 본질적으로 DI는 인터페이스를 준수하는 객체의 다형성 메소드 구현을 보완했습니다.

6

개발 단계에서 프로그램 구조를 변경하지 않더라도 프로그램의 여러 부분에서 여러 하위 시스템에 액세스해야합니다. DI를 통해 각 학급은 서비스를 요청하면 모든 배선을 수동으로 제공 할 필요가 없습니다.

이것은 소프트웨어 디자인에서 사물의 상호 작용에 집중하는 데 도움이되고 "나중에 다른 사람이 필요하기 때문에 주위를 휴대해야하는 사람"이 아닙니다.

또한 보일러 플레이트 코드를 작성하는 작업을 많이 절약 할 수 있습니다. 싱글 톤이 필요합니까? 클래스를 하나만 구성하면됩니다. 그러한 "싱글 톤"으로 테스트 할 수 있습니까? 네, 여전히 할 수 있습니다. (단 한번만 존재하도록 설정 되었기 때문에 테스트가 대안 구현을 인스턴스화 할 수 있습니다.)

그러나 DI를 사용하기 전에는 그 가치를 제대로 이해하지 못했지만 실제로 시도해 보았습니다. 내 디자인은 전에와 마찬가지로 훨씬 객체 지향적이었습니다. 그건 그렇고, 현재의 어플리케이션에서는 단위 테스트를하지 않습니다 (나쁘고 나쁘다).하지만 더 이상 DI와 함께 살 수는 없습니다. 물건을 옮기고 수업을 작고 간단하게 유지하는 것이 훨씬 쉽습니다.

+1

DI/IoC 컨테이너 프레임 워크가 사악한 싱글 톤 패턴을 대체 할 수있는 방법을 언급 한 +1! – TrueWill

+0

내가 보는 대부분의 DI 프레임 워크는 코드가 적어도 2000+ 개 이상인 코드 라인을 가지고 있습니다. 또한 기존 코드를 수정하지 않고 프레임 워크를 사용할 수있는 것처럼 보이지 않습니다. 귀하의 경험에 비추어 볼 때 DI 프레임 워크를 다른 프레임 워크로 쉽게 교체 할 수 있습니까? – Boon

+0

@TrueWill 싱글 톤은 왜 DI 버전인가요? – zehelvion

4

종속성 주입을 사용하면 특정 코드 단위를 개별적으로 테스트 할 수 있습니다.

예를 들어, 클래스 의 인스턴스를 해당 생성자에 사용하는 클래스 Foo이 있습니다. Foo의 메소드 중 하나는 Bar의 등록 정보 값이 Bar의 다른 처리를 허용하는 값인지 점검 할 수 있습니다.

public class Foo 
{ 
    private Bar _bar; 

    public Foo(Bar bar) 
    { 
     _bar = bar; 
    } 

    public bool IsPropertyOfBarValid() 
    { 
     return _bar.SomeProperty == PropertyEnum.ValidProperty; 
    } 
} 

이제 Bar 인스턴스화하고이 속성은 그것의 생성자에서 일부 데이터 소스에서 데이터로 설정되어 있다고 가정 해 봅시다. 메서드를 Foo으로 테스트하면 어떻게 될까요? (이것은 매우 간단한 예입니다). 글쎄, Foo은 생성자에 전달 된 Bar의 인스턴스에 따라 달라지며, 이는 차례대로 속성이 설정되는 데이터 소스의 데이터에 따라 달라집니다. 우리가하고 싶은 것은 Foo을 의존하고있는 리소스로부터 격리 시켜서 우리가 그것을 독립적으로 테스트 할 수 있도록하는 것입니다.

이것은 의존성 주입이 들어오는 곳입니다. Bar의 인스턴스가 Foo으로 전달되어이 가짜 Bar에 설정된 속성을 제어하고 수행 할 작업을 달성하면 IsPropertyOfBarValid()의 구현이 우리가 기대하는 바를 수행하는지 테스트합니다. 즉, Bar.SomeProperty == PropertyEnum.ValidProperty과 false를 반환하면 true를 반환합니다. 다른 값.

가짜 개체에는 모의 (Mock) 및 스텁 (Stub)이라는 두 가지 유형이 있습니다. 스텁은 테스트중인 애플리케이션에 대한 입력을 제공하므로 다른 테스트에서 스텁을 수행 할 수 있습니다. 반면에 모의는 pass \ fail을 결정하기 위해 테스트에 대한 입력을 제공합니다.

Martin Fowler has a great article on the difference between Mocks and Stubs

1

난 당신이 많은 서비스/그 구현 외부 구성을 기반으로 런타임에 선택해야합니다 구성 요소가있을 때 DI 사용 가치가 있다고 생각합니다. 이러한 구성은 XML 파일 또는 코드 주석과 별도의 클래스의 조합을 취할 수 있으므로 더 편리하게 선택하십시오.

그렇지 않으면 간단하게 ServiceLocator를 사용하면 훨씬 가볍고 전체 DI 프레임 워크보다 이해하기 쉽습니다.

단위 테스트의 경우 테스트에서 테스트 단위에 "주입"하는 대신 필요에 따라 객체를 모의 할 수있는 조롱 API를 사용하는 것이 좋습니다. Java의 경우 해당 라이브러리 중 하나가 내 자신 인 JMockit입니다.

+0

servicelocator를 언급하는 +1. 나는 사람들이 단지 "서비스 위치"측면을 사용할 때 DI가 과도하게 보일 때가 있다고 생각합니다. –

0

나는 단지 오늘 밤을 이해했다. 나를 위해, 의존성 주입은 특정 상황에서 많은 매개 변수가 작동해야하는 객체를 인스턴스화하는 방법입니다.

의존성 주입은 언제 사용해야합니까? 정적 인 방법으로 객체를 인스턴스화하면 종속 삽입을 사용할 수 있습니다. 예를 들어 객체를 XML 파일이나 JSON 파일로 변환 할 수있는 클래스를 사용하고 XML 파일 만 필요한 경우 의존성 주입을 사용하지 않으면 객체를 생성하고 많은 것을 구성해야합니다.

depandancy injection을 언제 사용해야합니까? 오브젝트가 요청 매개 변수 (제출 양식 이후)로 인스턴스화 된 경우, 오브젝트가 정적 인 방법으로 인스턴스화되지 않았으므로 depandancy injection을 사용하지 않아야합니다.

+0

저는 몇 년 전에이 질문을했습니다. 그 이후로 많이 배웠습니다. 당신이 설명하는 것은 IoC 컨테이너를 사용하여 잘 풀릴 것이고 DI를 사용하여 생성 된 객체를 삽입 할 것입니다. 예를 들어, IoC 컨테이너의 레지스트리에있는 "복잡한"객체를 구성하고 필요한 곳에 코드에 삽입하는 인스턴스를 "요청"합니다. 나는 이것이 DI 사용의 타당한 이유이기도하다는 데 동의합니다. – CodeMonkey

9

DI는 시스템을 분리하는 데 매우 유용합니다. 데이터베이스 구현을 나머지 응용 프로그램과 분리하는 것이 목적이라면 응용 프로그램이 매우 간단하거나 문제 도메인에 대해 더 많은 분석을 수행하고 문제 도메인 내의 구성 요소를 찾아야합니다 가장 많이 변경 될 가능성이 높으며 시스템 내에서 많은 양의 결합이있는 구성 요소가 있습니다.

DI는 코드 재사용, 다양성 및 문제 도메인의 변경에 대한 견고성을 목표로 할 때 가장 유용합니다.

프로젝트의 관련성은 예상되는 코드 수명에 따라 다릅니다. 작업 유형에 따라 작성중인 코드의 대부분을 하나의 프로젝트에서 다음 프로젝트로 재사용하지 않아도됩니다.

DI를 사용하는 예제는 DI를 사용하여 여러 클라이언트에 배포 할 수있는 응용 프로그램을 만드는 것입니다.이 응용 프로그램은 클라이언트에 대한 사용자 정의를 주입하는데, GOF 전략 패턴이라고도합니다. DI 프레임 워크를 사용하여 많은 GOF 패턴을 촉진 할 수 있습니다.

DI는 많은 양의 코드, 복잡한 비즈니스 요구 사항 및 수년 또는 수십 년 동안 시스템을 유지하려는 기대 (또는 희망)가있는 엔터프라이즈 응용 프로그램 개발과 관련이 있습니다.

+0

유연성을 추구하면 신속한 개발 중에도 유용합니다 (실험을 수행하기를 원하므로). 서로 다른 뷰, 데이터 구조, 메뉴, 제어 체계 등을 쉽게 연결할 수 있습니다. 기본적으로 (이해하고 올바르게 사용하는 경우) 보일러 플레이트 코드 노이즈를 줄여보다 유연하고 체계적인 방식으로 "종속성"을 관리 할 수 ​​있습니다. 물론 오용 될 수 있으며 어떻게 든 코드를 잠재적으로 더욱 복잡하게 만들 수 있습니다. – zehelvion

관련 문제