의존성 주입 : 모든 부분을 담을 Car 클래스를 만들어야합니까?


10

C ++ 애플리케이션에는 RaceTrack이 포함 된 많은 자동차가 있습니다.

각 자동차는 수백 개의 부품으로 구성됩니다. 각 부분은 다른 부분에 의존합니다.

DI와 Mark Seemann의 책에서 많은 SO 질문을 읽었으며 모든 자동차 부품이 서로 의존 하고이 수프 부품이 자동차이기 때문에 자동차 부품을 보유하기 위해 Car 클래스를 정의해서는 안되는 것처럼 보입니다. 내가 맞아?

그래서 모든 레이싱 카를 RaceTrack에 넣을 때, 트랙에 서로의 레이싱에 따라 자동차 엔터티는 없지만 많은 자동차 부품이 있습니까? 내가 맞아?

편집하다:

자동차 논리를 프로그래밍하는 경우 Car 클래스가 필요하다는 것이 분명했기 때문에 여러 해 동안 저는 Car 클래스를 프로그래밍했습니다. 그러나 DI로는 나에게 그렇게 분명하지 않습니다. 정의 된 역할이없는 경우 DI가 Car 클래스를 작성하지 않는 것이 관용적 인 일인지 궁금합니다.

나는 운전을 위해 SteeringWheel, 구덩이 승무원을위한 바퀴에 BoltsAndNuts 및 자동차 전체를 대표하는 인스턴스가없는 모든 종류의 다른 재미있는 인터페이스를 갖는 것이 괜찮습니까?

답변:


24

레이스 트랙에 앉아있는 많은 자동차 부품이 누구에게 좋은가요?

모든 자동차 클래스가 자동차 부품을 잡는 것이라면 젖은 부품 백만큼 유용합니다.

용법

운전자로서 내가 원하는 것은 내가 통제 할 수있는 것입니다. 속도를 요구할 때 응답합니다. 그것은 온 레일과 같이 처리됩니다. 그것은 한푼도 멈출 수 있습니다.

내가 원하는 것은 사용할 수있는 자동차 클래스입니다. 기화기가 어떻게 작동하는지에 대해 생각할 필요없이 말할 수 있습니다. 나는 단지 가스 페달에 대해 생각합니다. 그것들이 어떻게 연결되어 있는지는 내가 걱정하는 것이 아닙니다. 그것은 추상화입니다.

의존성 주입

의존성 주입 은 그와 아무 관련이 없습니다. 차를 운전할 때 차가 어떻게 만들어 졌는지 생각하지 않습니다. 그것이 작동하는 한, 나는 그들이 그것을 어떻게 구성하는지 상관하지 않습니다.

아니요, DI는 구덩이 승무원이 트랙에서 비가 내리기 시작할 때 타이어를 빨리 교체하여 더 나은 타이어를 만들 수있게 해줍니다. 완전히 다른 차에 타지 않고도 그렇게 할 수 있다는 것이 좋습니다.

DI는 실제로 원칙을 따르는 것입니다. 건축과 분리하여 사용하십시오.

한 시간에 90 마일로 새 타이어를 설치할 수있는 차가 시원하게 들릴지 모르지만 타이어를 설치 한 타이어로 어떤 경주에서도 이길 수는 없다고 생각합니다.

DI는 피트 승무원이 접근 할 수있는 방식으로 부품을 설치하는 것입니다. new같은 장소에서 사용하면 행동을 프로그래밍하는 것이 기화기를 제자리에 용접하는 것과 같습니다. 아세틸렌 토치가 제거 할 수는 있지만 너트와 볼트 사용을 먼저 고려하십시오.

이것이 바로 DI입니다. 물론 new원하는 것을 알아 차리 자마자 쉬운 일이 아닙니다 . 대신 자동차를 만드는 방법을 알고있는 별도의 코드를 작성해야합니다. 그러나 나중에 쉽게 변경할 수 있습니다. 또한 자동차 조립 공장을 트랙 주위로 끌지 않아도됩니다.

구성

어딘가에 타이어가 Goodyear인지 알아야합니다. 그러면 자동차 건설 코드를 어디에 둘까요? 차가 아니라면 피트 승무원? 트랙 은요? 아니요. 모든 행동 코드가 있습니다. 레이스 중에 수행해야하는 코드. 자동차를 건설하는 것은 행동 코드에서 제거 된 장소에서 레이스 전에 발생해야합니다. Mark Seemans는 이곳을 작곡 루트 라고 불렀습니다 . 대부분의 사람들은 그것을 주라고 부릅니다.

간단한 패턴입니다. 기본적으로 개체 그래프를 구성한 다음 개체 그래프의 한 개체에 대해 하나의 동작 메서드를 호출하십시오. 그게 다야. 이곳은 유일한 장소 건설과 행동이 함께 있어야합니다.

그렇다고해서 시공이 순서대로 배치 된 절차 코드가되어야한다는 의미는 아닙니다. 언어로 된 모든 도구를 사용하여 구성 할 수 있습니다. 행동과 혼동하지 마십시오.

언어로 이것을하고 일부 DI 프레임 워크 또는 IoC 컨테이너를 사용하지 않는 것을 순수 DI 라고 합니다. 잘 작동합니다. 오랫동안 가지고 있습니다. 우리는 그것을 참조 전달 이라고 부릅니다 .

DI 툴

DI 도구가 구입하는 것은 시공 세부 사항이 시공과 동작을 분리하는 다른 언어 (xml, json 등)로 이동 한 것입니다. 동료 프로그래머가 신뢰 new해서는 안될 때 사용하지 말 것을 신뢰하지 않으면 호소력이 있습니다.

단점은 DI 툴 세부 사항이 코드베이스 전체에 퍼져 나가고 싶어한다는 것입니다. 독점적 인 주석으로 코드베이스를 감염시키는 경우가 있습니다. 그들이 제공하는 예는 확실히 이것을 장려합니다. 이 도구는 작업을 Java 프로그래밍 작업이 아니라 Java / Spring 프로그래밍 작업으로 광고 할 수있을 때까지 언어 공간으로 이동하는 경향이 있습니다.

설계 원칙

자동차 논리를 프로그래밍하는 경우 Car 클래스가 필요하다는 것이 분명했기 때문에 여러 해 동안 저는 Car 클래스를 프로그래밍했습니다. 그러나 DI로는 나에게 그렇게 분명하지 않습니다. 정의 된 역할이없는 경우 DI가 Car 클래스를 작성하지 않는 것이 관용적 인 일인지 궁금합니다.

추상화에 대해 배우고 수업 결정 방법을 변경하는 것이 필요하다고 생각합니다. 잘 됐네요 그러나 그것은 DI에 관한 것이 아닙니다. DI는 카 클래스가 필요한지 결정하는 데 도움이되지 않습니다. 타이어가 Goodyear 타이어 인 경우 DI를 사용하면 자동차를 알지 못하도록하여 돌보는 일을 방지 할 수 있습니다. DI는 차량이 일본에서 만들어진 것인지 트랙을 알 수 없도록 도와줍니다.

소프트웨어 디자인에서 가장 근본적인 질문 중 하나는 "무엇을 알고 있는가?"입니다. 이것이 UML 다이어그램이 보여주는 주요 내용입니다. 당신이 과거에 도달하고있는 무언가를 새로 만들면 그것은 당신이 묶여있는 구체적인 것에 대한 인터페이스입니다. 차는 이제 타이어가 Goodyear임을 알아야합니다. 미쉐린이 당신을 후원하고 싶다면 어떤 짜증이납니다.

이를 피하는 것은 의존성 역전 원칙에 따라 호출 됩니다. 공식적으로, 자동차 등급과 같은 높은 수준의 모듈은 GoodyearTire 등급과 같은 낮은 수준의 모듈에 직접 의존해서는 안됩니다. 타이어 인터페이스와 같은 추상화에 의존해야합니다.

이를 피하는 방법을 제어 반전 이라고 합니다. 여기서는 제어 흐름 변경에 중점을 둡니다. 타이어가 자동차를 움직입니까, 아니면 자동차가 타이어를 움직입니까? 이를 올바른 방법으로 생각하면 자동차와 타이어를 정적으로 연결할 수 없습니다. DI는 Inversion of Control을 따르는 특별한 방법 중 하나입니다.

이 중 어느 것도 자동차 클래스가 필요한지 알려주지 않습니다. "car logic"을 프로그래밍하는 경우 한 곳에 보관하는 것이 아니라 모든 곳에 분산시키는 것이 좋습니다. 자동차 구성 로직이 자동차 행동 로직과 동일하므로 모두 같은 장소에 살아야한다고 생각하는 것에 속지 마십시오. 그러나 자동차에 대한 롤을 정의하지 않은 경우 필요하지 않습니다. 원한다면 트랙 주위에 오토바이를 경주하십시오.

나는 운전을 위해 SteeringWheel, 구덩이 승무원을위한 바퀴에 BoltsAndNuts 및 자동차 전체를 대표하는 인스턴스가없는 모든 종류의 다른 재미있는 인터페이스를 갖는 것이 괜찮습니까?

DI 또는 DI 없음, 자동차 전체를 나타내는 인스턴스를 갖는 것은 좋지만, 그 인스턴스는 내가 필요하지 않은 경우 직접 알고 싶은 것이 아닙니다. 자동차를 추상화 할 때 가스, 디젤 또는 전기를 사용할 때 신경 쓰지 않아도됩니다. 그것은 내가 그것을 만들거나 유지할 때주의해야 할 것입니다. 자동차를 사용하는 코드가 작동 방식을 알거나 신경 쓸 필요가 없다면 좋습니다. "모릅니다. 알고 싶지 않습니다."


코드를 나타내는 데 사용하는 질문에 자동차 및 피트 승무원 은유를 사용하지 않으면 멋질 것입니다. 그러나 여전히 좋은 대답입니다.
S. Tarık Çetin

6
그리고 나는 항상 제어의 반전이 당신이 왼쪽으로
향할 때라고

CandiedOrange, 의미있는 인터페이스와 명확한 책임이 없다면 Car 클래스가 없습니까? 그리고 내 프로젝트에는 Car.h가 없습니다. 그리고 동료가 내 코드를 살펴보고 그것이 자동차 부품 전자 상점 또는 차고 관리 응용 프로그램인지 궁금합니다. :)
Anton Petrov

@AntonPetrov "오리처럼 보이고 오리처럼 찌르지 만 배터리가 필요한 경우 추상화가 잘못되었을 수 있습니다." 좋은 이름은 매우 중요하고 생각하기 어려울 수 있지만, 잘 정의 된 책임과 의미있는 인터페이스를 반영하여 놀랍지 않게 변경되어야합니다. 이름을 읽은 다음 인터페이스를보고 "실제 예상 한 것"이라고 생각하면 이름이 좋습니다.
candied_orange

15

모든 자동차 부품이 서로 의존하고 부품 수프가 자동차이기 때문에 자동차 부품을 보유하기 위해 Car 클래스를 정의해서는 안됩니다. 내가 맞아?

아니.

의존성 주입 지점은 전혀 없다 종속성 낙담. 정반대.

의존성 주입은 문제에 관한 것입니다. 자동차는 어디서 부품 얻 습니까? 그것들은 어디에서 어떻게 만들어졌으며, 자동차는 어떻게 그것들을 참조합니까?

순진하게 자동차는을 호출하여 자체 부품을 만듭니다 new. 이것은 쉽고 간단하지만 매우 융통성이 없습니다. 자동차는 부품을 생성하는 데 필요한 모든 것을 알고 있어야하며, 부품이 다른 두 대의 자동차를 원한다면 그 논리도 자동차에 들어가야합니다.

의존성 주입을 사용하면 모든 로직을 자동차에서 꺼내 구성 구성 요소에 배치하여 모든 부품을 만들고 참조를 연결합니다. 완전히 구성된 종속성은 자동차에 주입 됩니다.


1
마지막으로, dependency injection개념에 대한 명확한 설명 .
anatoly techtonik

1
"순진한"접근 방식에 대한보다 일반적인 시스템은 자동차가 새로운 것을 부르는 것이 아니라 자동차 클래스의 사용자가 해당 속성에 부품을 할당하고 그 동안 자동차 클래스는 미정 상태. DI는 기계적으로 클래스의 유효성을 보장하는 수단을 제공합니다.
whatsisname

2
@whatsisname DI를 사용하여 유효하지 않은 반 객체를 쉽게 만들 수 있습니다. 유효성 검사는 DI 책임이 아닙니다. 불변도 아닙니다. DI는 유효하고 불변의 객체를 만드는 일을 맡을 수 있습니다. DI는 이것이 객체를 구성하고 사용하는 유일한 방법임을 강요 할 방법이 없습니다. 객체가이를 시행해야합니다.
candied_orange

@ CandiedOrange : 어떤 기술을 사용하여 쉽게 반쯤 낼 수 있습니까? 생성자에 의존성을 요구하고 불변성을 만드는 것은 은총 알이 아니지만 그럼에도 불구하고 많은 일반적인 나쁜 상황을 막는 매우 유용한 방법입니다.
whatsisname

0

그래서 모든 레이싱 카를 RaceTrack에 넣을 때, 트랙에 서로의 레이싱에 따라 자동차 엔터티는 없지만 많은 자동차 부품이 있습니까? 내가 맞아?

잘. 예, 아니오 자동차 회사는 여전히 유효합니다. 그리고 자동차는 부품의 합보다 더 많습니다. 운전자도 필요합니다 (당분간). 자동차의 제조사와 모델은 말할 것도없고, 경주 용 자동차에도 많은 이름이 있습니다.

그렇습니다. 자동차는 기본적으로 부품의 컨테이너이지만 자동차를 더 크게 구성하는 부품의 포장 및 협력입니다.

정말 아니에요 자동차는 단순한 금속과 플라스틱 가방이 아닙니다. 기계입니다.

이 경우 의존성 주입은 과도하지 않습니다. 팩토리 클래스 또는 Builder 객체가 될 자동차를 만들어야합니다. 차는 스스로 만드는 법을 몰라 야합니다.


2
팩토리 나 빌더 오브젝트없이 DI를 가질 수 있습니다. 간단한 생성자 매개 변수는 많은 상황에서 작동하는 유효한 방법입니다.
whatsisname
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.