의존성 주입은 UnitTesting 외부에서 가치가 있습니까?


17

초기화하는 여러 객체의 다른 구현을 절대 사용하지 않아도되는 생성자가 주어지면 DI를 사용하는 것이 여전히 실용적입니까? 결국, 우리는 여전히 단위 테스트를 원할 수 있습니다.

문제의 클래스는 생성자에서 몇 가지 다른 클래스를 초기화하며 사용하는 클래스는 매우 구체적입니다. 다른 구현을 사용하지 않습니다. 인터페이스 프로그래밍을 피하는 것이 정당합니까?



3
키스 -항상 최선의 방법입니다.
Reactgular

5
내 생각 에이 질문은 제안 된 사본보다 더 구체적입니다. 미래를위한 설계 변경 또는 문제를 해결하기 위해이
k3b

1
테스트 가능성이 충분하지 않습니까?
ConditionRacer

실제로 답 자체만큼 복제본처럼 들리지 않습니다. 결코 일어나지 않는다면, 디자인은 미래의 변화를위한 디자인이 아닙니다. 심지어 건축 우주 비행사조차도 나쁜 판단에서 결코 일어나지 않을 변화만을 설계합니다.
Steve314

답변:


13

"응용 프로그램이 사용되는 시간 동안" "결코 절대로"정확하지 않은지 여부에 따라 다릅니다.

일반적으로

  • 테스트 가능성을 위해서만 디자인을 수정하지 마십시오 . 단위 테스트는 그 반대가 아니라 당신을 위해 제공됩니다.
  • 반복하지 마십시오. 상속자가 하나만있는 인터페이스를 만드는 것은 쓸모가 없습니다.
  • 클래스를 테스트 할 수없는 경우 실제 사용 사례에 대해서도 유연하거나 확장 할 수 없습니다. 때로는 괜찮습니다. 유연성이 필요하지는 않지만 단순성 / 신뢰성 / 유지 보수성 / 성능 / 무엇보다 중요한 것이 있습니다.
  • 모르는 경우 인터페이스로 코딩하십시오. 요구 사항 변경.

12
" 테스트 용으로 디자인을 수정하지 마십시오"에 대해 거의 -1을 표시했습니다 . 시험 성을 얻는 것은 IMHO가 설계를 변경해야하는 가장 큰 이유 중 하나입니다! 그러나 다른 요점은 괜찮습니다.
Doc Brown

5
@docBrown-(그리고 다른 사람들) 나는 여기에서 많은 사람들, 그리고 아마도 대다수와 다릅니다. ~ 95 %의 시간이 걸리므로 테스트가 가능해 지거나 유연 해집니다. 대부분 의 시간 동안 디자인에 디자인을 추가하거나 디자인에 추가해야합니다 . 테스트 가능성이 손상됩니다. 다른 ~ 5 %는 이상한 요구 사항을 가지고있어 다른 종류를 선호하는 이러한 종류의 유연성을 방해하거나, 필수 테스트 / 변경없이 전용 테스트 없이도 고장이 나면 아주 빨리 찾을 수 있습니다.
Telastyn

4
확실하지만, 위의 첫 번째 진술은 "유일한 관심사가 테스트 가능성 일 때 잘못 설계 한 코드를 그대로 두는 것"으로 너무 쉽게 잘못 해석 될 수 있습니다.
Doc Brown

1
왜 "하나의 상속자가있는 인터페이스를 만드는 것은 쓸모가 없다"고 말 하시겠습니까? 인터페이스는 계약으로 작동 할 수 있습니다.
kaptan

2
@kaptan-콘크리트 객체는 계약뿐만 아니라 작동 할 수 있기 때문입니다. 두 개만 만들면 코드를 두 번 작성하고 코드가 변경되면 코드를 두 번 수정해야합니다. 물론, 대다수의 인터페이스는 여러 가지 (테스트되지 않은) 구현을 갖거나 해당 상황에 대비해야합니다. 그러나 드문 경우에 필요한 모든 것이 단순한 밀폐 된 물체이기 때문에 바로 사용하십시오.
Telastyn

12

인터페이스 프로그래밍을 피하는 것이 정당합니까?

인터페이스에 대한 코딩의 장점은 분명하지만, 그렇게하지 않으면 정확히 무엇을 얻을 수 있는지 스스로에게 물어봐야합니다.

다음 질문은 : 구현을 선택하는 것이 아닌지 해당 클래스의 책임의 일부입니까? 그럴 수도 있고 아닐 수도 있으며 그에 따라 행동해야합니다.

궁극적으로, 일부 구피 제약이 항상 파란색으로 나타날 가능성이 있습니다. 동일한 코드를 동시에 실행하고 싶을 수 있으며 구현을 삽입하면 동기화에 도움이 될 수 있습니다. 또는 앱을 프로파일 링 한 후 일반 인스턴스화와 다른 할당 전략을 원할 수도 있습니다. 또는 교차 절단 문제가 발생하고 AOP 지원이 제공되지 않습니다. 누가 알아?

YAGNI는 코드를 작성할 때 불필요한 것을 추가하지 않는 것이 중요하다고 제안합니다. 프로그래머가 코드를 알지 못하고 코드에 추가하는 경향 중 하나는 불필요한 가정입니다. "이 방법은 유용 할 수 있습니다"또는 "이것은 절대 바뀌지 않을 것입니다"와 같이. 둘 다 디자인에 혼란을 더합니다.


2
여기에서 YAGNI DI에 대한 논쟁으로 인용하여 +1 합니다.
Doc Brown

4
@DocBrown : 여기에서 YAGNI를 사용 하여 DI를 사용 하지 않음 을 정당화 할 수 있습니다 . 나는 그것이 YAGNI가 무엇인가에 대한 유용한 척도가되는 것에 반대되는 주장이라고 생각합니다.
Steven Evers

1
YAGNI에 포함 된 불필요한 가정에 대해 +1, 몇 번이나 우리를
맞이

@SteveEvers : 의존성 반전 원리를 무시하기 위해 YAGNI를 사용하면 YAGNI 또는 DIP에 대한 이해가 부족하거나 프로그래밍 및 추론의보다 근본적인 원칙 중 일부를 배제 할 수 있다고 생각합니다. YAGNI가 본질적으로 적용 할 수없는 상황 인 경우 필요한 경우에만 DIP를 무시 해야 합니다.
back2dos

@ back2dos : DI가 '아마도 요구 사항'과 "누가 아는가"때문에 유용하다고 가정합니다. YAGNI가 싸워야한다는 생각의 기차입니다. 대신 추가 툴링 및 인프라에 대한 정당화로 사용하고 있습니다.
Steven Evers

7

다양한 매개 변수에 따라 다르지만 DI를 계속 사용할 수있는 몇 가지 이유는 다음과 같습니다.

  • 테스트 자체가 꽤 좋은 이유입니다.
  • 객체에 필요한 클래스는 다른 장소에서 사용될 수 있습니다. 주입하면 리소스를 풀링 할 수 있습니다 (예 : 문제의 클래스가 스레드 또는 데이터베이스 연결 인 경우). 사이)
  • 다른 객체를 초기화하지 못하면 스택보다 높은 코드가 클래스보다 문제를 처리하는 데 더 좋을 것입니다.

결론 :이 경우 DI없이 살 수 있지만 DI를 사용하면 더 깨끗한 코드로 끝날 가능성이 있습니다.


3

당신이 프로그램 또는 기능을 디자인 할 때, 생각의 과정의 일부가 되어야 당신이 그것을 테스트하기 위해가는 방법을합니다. 의존성 주입은 테스트 도구 중 하나이며 혼합의 일부로 고려해야합니다.

Dependency Injection의 추가 이점과 클래스 대신 인터페이스를 사용하면 응용 프로그램을 확장 할 때도 도움이되지만 나중에 검색 및 바꾸기를 사용하여 소스 코드에 아주 쉽고 안전하게 개조 할 수도 있습니다. -매우 큰 프로젝트에서도.


2
 > Dependency Injection worth it **outside** of UnitTesting?
 > Are we justified in avoiding trying to program to an interface?

이 질문에 대한 많은 답변은 단위 테스팅을 원하지 않는 경우 YAGNI로 "필요할 수 있기 때문에 필요할 수 있습니다."로 논의 될 수 있습니다.

unittests 이외의 이유를 인터페이스에 프로그래밍해야하는 경우

, 제어 반전 이 필요한 경우 의존성 주입 은 UnitTesting 외부 에서 가치가 있습니다 . 예를 들어 한 모듈 구현에 해당 계층에서 액세스 할 수없는 다른 모듈이 필요한 경우.

예 : 모듈이있는 경우 gui=> businesslayer=> driver=>를 common.

이 시나리오에서는 businesslayer사용할 수 driver있지만 driver사용할 수는 없습니다 businesslayer.

driver높은 수준의 기능이 필요한 경우 businesslayer인터페이스를 common계층으로 구현하는 이 기능 을 구현할 수 있습니다 . 계층 driver의 인터페이스 만 알아야합니다 common.


1

그렇습니다. 첫째, 단위 테스트 도구를 중심으로 코드를 설계하는 이유로 단위 테스트를 잊어 버리십시오. 인위적인 제약 조건에 맞게 코드 디자인을 구부리는 것은 결코 좋은 생각이 아닙니다. 도구로이 작업을 수행해야하는 경우 더 나은 도구를 얻을 수 있습니다 (예 : 모의 객체를 만들기위한 더 많은 옵션을 허용하는 Microsoft 가짜 / 몰).

예를 들어 테스트 도구가 개인용 메서드와 작동하지 않기 때문에 클래스를 공용 메서드만으로 분할 하시겠습니까? (개인적인 방법을 테스트 할 필요가없는 척하는 것이 보편적 인 지혜라는 것을 알고 있지만, 이것이 현재 도구로는 수행하기 어려운 문제에 대한 반응이라고 생각합니다.

Fowler가 설명 하는 "모의 자"는 사용하는 도구에 맞게 코드를 변경해야하는 반면, "고전적인"테스터는 자연적으로보다 통합 된 테스트를 생성합니다. (즉, 각 방법이 아닌 단위로 클래스를 테스트하십시오), 특히 구체적인 클래스를 조롱 할 수있는 도구를 사용하는 경우 인터페이스가 덜 필요합니다.


3
나는 개인적인 방법을 테스트해서는 안된다는 일반적인 지혜가 테스트의 어려움과 관련이 있다고 생각하지 않습니다. 개인 메서드에 버그가 있었지만 객체의 동작에 영향을 미치지 않으면 아무 영향도 미치지 않습니다. 개인 메소드에 오브젝트의 작동에 영향을 미치는 버그가있는 경우 오브젝트의 공개 메소드 중 하나 이상에 대해 실패하거나 누락 된 테스트가 있습니다.
Michael Shaw

그것은 행동이나 상태를 테스트하는지 여부에 달려 있습니다. 개인 메소드는 분명히 어떤 방식으로 테스트해야하지만, 고전적인 TDD 인 경우 클래스를 "전체적으로"테스트하여 테스트합니다. 대부분의 사람들이 사용하는 테스트 도구는 각 메소드 테스트에 중점을 둡니다. 개별적으로 ... 그리고 내 요점은 후자가 전체 테스트를 수행 할 기회를 놓치므로 효과적으로 테스트하지 않는 것입니다. 그래서 저는 오늘날 일부 (대부분의) 사람들이 단위 테스트를 수행하는 방식으로 TDD가 어떻게 파괴되었는지 강조하려고 노력하는 것에 동의합니다.
gbjbaanb

1

의존성 삽입 (Dependency Injection)은 개체가 있다는 것이 명확하게 갖고 종속성을.

다른 사람이 생성자를 보지 않고 순진하게 객체를 사용하면 서비스, 연결 등을 설정해야한다는 것을 알 수 있습니다. 생성자에게 전달할 필요가 없기 때문에 분명하지 않았습니다. . 종속성을 전달하면 필요한 것이 더 명확 해집니다.

또한 수업에서 SRP를 위반할 수 있다는 사실을 숨길 수도 있습니다. 많은 의존 관계 (3 이상)를 전달하는 경우 수업이 너무 많이 수행되어 리팩터링해야합니다. 그러나 생성자에서 생성하면이 코드 냄새가 숨겨집니다.


0

나는 여기의 두 캠프에 동의하며 문제는 여전히 내 의견으로는 논쟁의 여지가 있습니다. YAGNI는 가정에 맞게 코드를 변경하지 않아도됩니다. 단위 테스트는 여기에서 문제가되지 않습니다. 왜냐하면 나는 의존성이 결코 변하지 않을 것이라고 굳게 믿고 있기 때문입니다. 그러나 처음부터 단위 테스트를 받았다면 어쨌든이 시점에 도달하지 못했을 것입니다. 내가 결국 DI로가는 길을 좁 혔을 것이다.

시나리오에 대한 다른 대안을 구체적으로 제공하겠습니다

팩토리 패턴을 사용하면 종속성을 한 곳에서 현지화 할 수 있습니다. 테스트 할 때 컨텍스트를 기반으로 구현을 변경할 수 있으며 충분합니다. 이것은 여러 클래스 구성을 추상화하는 이점 때문에 YAGNI에 반대하지 않습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.