종속성 주입이란 무엇입니까?
질문
사용시기와 프레임 워크가 어떤 프레임 워크가 있는지와 같이 종속성 주사에 대한 특정 질문에 이미 게시 된 몇 가지 질문이있었습니다.하지만,
종속성 주입이란 무엇이며, 언제 / 왜 사용해야합니까?
답변
지금까지 발견 한 가장 좋은 정의는 James Shore에 의해 하나입니다.
"의존 주사"는 25 달러입니다 5 센트 개념의 용어.[...] 의존성 주입은 A를주는 것을 의미합니다 객체 인스턴스 변수.[...].
Martin Fowler가 유용 할 수있는 기사가 있습니다.
종속성 주입은 기본적으로 객체가 자신을 구성하는 대신 객체가 필요로하는 객체를 제공합니다.그것은 테스트를위한 매우 유용한 기술이며, 종속성이 조롱되거나 좌절 될 수 있기 때문입니다.
종속성은 많은 수단 (예 : 생성자 주입 또는 세터 주입)만큼 객체로 주입 할 수 있습니다.하나는 전문 의존 주사 프레임 워크 (예 : 봄)를 사용하여 그렇게 할 수 있지만 확실히 필요하지 않습니다.종속성 주입을 갖기 위해 해당 프레임 워크가 필요하지 않습니다.객체 (종속성) 인스턴스화 및 전달 객체 (명시 적)는 프레임 워크에 의한 주사로서의 주입을 촉발 한 것입니다.
답변
종속성 주입은 다른 객체 또는 프레임 워크 (종속성 인젝터)에 대한 종속성을 전달하고 있습니다.
의존성 주입은 테스트를 쉽게 만듭니다.주입은 생성자를 통해 수행 할 수 있습니다.
someclass ()는 다음과 같이 생성자가 있습니다.
public SomeClass() {
myObject = Factory.getObject();
}
문제: MyObject가 디스크 액세스 또는 네트워크 액세스와 같은 복잡한 작업이 포함되어 있으면 SomeClass ()에서 단위 테스트를 수행하기가 어렵습니다.프로그래머는 MyObject를 모르고 공장 호출을 가로 챌 수 있습니다.
대체 해결책 :
myObject를 생성자의 인수로 전달합니다
public SomeClass (MyClass myObject) {
this.myObject = myObject;
}
MyObject는 테스트를 쉽게 만드는 직접 전달 될 수 있습니다.
하나의 일반적인 대안은 DO-Nothing 생성자를 정의하는 것입니다.의존성 주입은 setter를 통해 수행 할 수 있습니다.(h / t @mikevella). Martin Fowler는 세 번째 대안 (H / TMARCDIX)을 문서화합니다. 여기서 클래스는 명시 적으로 종속성 프로그래머를위한 인터페이스를 구현합니다.
종속성 주입없이 단위 테스트에서 구성 요소를 분리하는 것은 어렵습니다.
2013 년이 답변을 썼을 때 이것은 Google 테스트 블로그의 주요 주제였습니다.프로그래머가 런타임 디자인 (예 : 서비스 위치 지정자 또는 이와 유사한 패턴)에서 항상 유연성이 항상 필요한 것은 아닙니다.프로그래머는 종종 테스트 중에 클래스를 격리해야합니다.
답변
나는이 재미있는 예제가 느슨한 커플 링 측면에서 발견되었습니다.
출처 : 종속성 주입 이해
모든 응용 프로그램은 서로 협업하는 많은 객체로 구성되어있어 유용한 물건을 수행합니다.전통적으로 각 개체는 공동 작업의 종속 개체 (종속성)에 대한 자체 참조를 얻는 것에 대한 책임이 있습니다.이로 인해 고도로 결합 된 클래스 및 테스트 코드가 적합합니다.
예를 들어 자동차 객체를 고려하십시오.
자동차는 휠, 엔진, 연료, 배터리 등에 달려 있습니다.전통적으로 우리는 자동차 객체의 정의와 함께 이러한 종속 물체의 브랜드를 정의합니다.
의존성 주입 (DI)없이 :
class Car{
private Wheel wh = new NepaliRubberWheel();
private Battery bt = new ExcideBattery();
//The rest
}
여기서 CAR 객체는 종속 객체를 작성하는 책임이 있습니다.
초기 Nepalirubberwheel () 펑크가 끝난 후에 그 종속 물체의 유형을 변경하려는 경우 어떻게해야합니까? 우리는 새로운 종속성으로 자동차 물체를 다시 만들어야합니다. Chineserubberwheel ()이 아니라 자동차 제조업체만이 그렇게 할 수 있습니다.
그럼 종속성 주입은 우리에게 무엇을합니까?
종속성 주입을 사용할 때 객체는 컴파일 시간 (자동차 제조 시간)이 아닌 런타임에 종속성이 부여됩니다. 우리가 원할 때마다 휠을 바꿀 수 있습니다.여기서, 종속성 (휠)은 런타임에 차에 주입 될 수 있습니다.
종속성 주입을 사용한 후 :
여기서 우리는 런타임에 종속성 (휠 및 배터리)을 주입하고 있습니다.따라서 용어 : 의존 주사.우리는 일반적으로 스프링, 유스도, 용접과 같은 DI 프레임 워크에 의존하여 종속성을 만들고 필요한 경우 주입하십시오.
class Car{
private Wheel wh; // Inject an Instance of Wheel (dependency of car) at runtime
private Battery bt; // Inject an Instance of Battery (dependency of car) at runtime
Car(Wheel wh,Battery bt) {
this.wh = wh;
this.bt = bt;
}
//Or we can have setters
void setWheel(Wheel wh) {
this.wh = wh;
}
}
장점은 다음과 같습니다.
객체 생성 (다른 단어, 객체 생성에서 별도의 사용법)을 디커플링합니다. 종속성을 대체 할 수있는 능력 (예 : 휠, 배터리)을 사용하는 클래스를 변경하지 않고 (예 : 휠, 배터리) 구현되지 않는 인터페이스 "코드를 홍보"원리 " 테스트 중에 모의 의존성을 만들고 사용하는 기능 (실제 인스턴스 대신 테스트 중에 휠의 모의를 사용하고 싶다면 .. 우리는 모의 휠 객체를 만들고 디 프레임 워크가 자동차로 주입 할 수 있습니다)
답변
종속성 주입은 객체가 내부적으로 구성하는 대신 다른 코드로부터 물체의 인스턴스를받는 방식으로 객체가 설계된 연습입니다.즉, 코드를 변경하지 않고 객체가 필요로하는 인터페이스를 구현하는 인터페이스를 대체 할 수 있으며 테스트를 단순화하고 디커플링을 향상시킬 수 있습니다.
예를 들어,이 클레어를 고려하십시오.
public class PersonService {
public void addManager( Person employee, Person newManager ) { ... }
public void removeManager( Person employee, Person oldManager ) { ... }
public Group getGroupByManager( Person manager ) { ... }
}
public class GroupMembershipService() {
public void addPersonToGroup( Person person, Group group ) { ... }
public void removePersonFromGroup( Person person, Group group ) { ... }
}
이 예에서 PersonService :: AddManager 및 PersonService :: RemovEmanager의 구현은 작업을 수행하기 위해 GroupMemberShipservice의 인스턴스가 필요합니다.의존성 주입이없는 전통적인 방법은 PersonService의 생성자에서 새로운 GroupMembershipservice를 인스턴스화하고 두 기능에서 인스턴스 속성을 사용하는 것입니다.그러나 GroupMembershipservice의 생성자가 아직 필요하지만 더 나쁜 일이있는 경우, GroupMembersHipservice에서 호출 해야하는 초기화 "setter"가 있습니다. 코드는 오히려 신속하게 증가하며, 이제는 GroupMembershipservice에뿐만 아니라또한 GroupMembershipservice가 의존하는 모든 것입니다.또한 GroupMembershipservice에 대한 연결은 PersonService로 하드 코딩되어 테스트 목적으로 GroupMembersHipservice를 "더미로"할 수 없거나 응용 프로그램의 다른 부분에서 전략 패턴을 사용할 수 없다는 것을 의미합니다.
Dependency Injection을 사용하면 PersonService에서 GroupMembershipservice를 인스턴스화하는 대신 PersonService 생성자에 전달하거나 로컬 인스턴스를 설정하려면 속성 (getter 및 setter)을 추가 할 것입니다.즉, PersonService는 더 이상 GroupMembersHipservice를 만드는 방법에 대해 걱정할 필요가 없으며, 주어진 것들을 받아들이고 그와 함께 작동합니다.이것은 또한 GroupMembershipservice의 하위 클래스 인 모든 것을 구현하거나 Groupmembershipservice 인터페이스가 "주사 된"인 PersonService에 "주입"될 수 있음을 의미합니다.
답변
받아 들여진 대답은 좋은 것입니다. 그러나 나는 이것에 추가하고 싶습니다. DI는 코드에서 하드 코딩 된 상수를 피하는 고전적인 것을 방지하는 것과 매우 흡사합니다.
데이터베이스 이름과 마찬가지로 몇 가지 상수를 사용할 때 코드 내부에서 일부 구성 파일로 빠르게 이동하고 해당 값을 포함하는 변수를 포함하는 위치에있는 변수를 전달할 수 있습니다.이를 수행 할 이유는 이러한 상수가 일반적으로 코드의 나머지 코드보다 자주 변경되는 것입니다.예를 들어 테스트 데이터베이스에서 코드를 테스트하려는 경우
DI는 객체 지향 프로그래밍의 세계에서 이것과 유사합니다.지속적인 리터럴 대신 값은 전체 객체입니다. 그러나 클래스 코드에서 코드를 만드는 이유는 유사합니다. 오브젝트가 더 자주 변경된 코드를 사용하는 코드를 사용합니다.이러한 변경이 필요한 중요한 경우는 테스트입니다.
답변
자동차 및 엔진 수업으로 간단한 예를 보자, 모든 자동차는 최소한 지금 어디에서나 엔진이 필요합니다.종속성 주입없이 코드가 어떻게 보일 것인지보다 낮 춥니 다.
public class Car
{
public Car()
{
GasEngine engine = new GasEngine();
engine.Start();
}
}
public class GasEngine
{
public void Start()
{
Console.WriteLine("I use gas as my fuel!");
}
}
그리고 자동차 클래스를 인스턴스화하려면 다음 코드를 사용할 것입니다.
Car car = new Car();
우리가 Gasegine에 단단히 결합하고 전기 encyengine에 바꾸기로 결정한이 코드의 문제는 자동차 수업을 다시 작성해야합니다.그리고 응용 프로그램이 더 큰 문제와 두통이 더 큰 엔진을 추가하고 사용해야합니다.
이 접근 방식으로 우리의 높은 수준의 자동차 클래스는 종속 반전 원리 (DIP)를 고체로부터 위반하는 하위 수준의 가스 렌느 클래스에 의존한다는 것입니다.DIP는 구체적인 수업이 아닌 추상화에 의존해야한다는 것을 암시합니다.그래서 이것을 만족시키기 위해서는 IENGINE 인터페이스를 소개하고 아래와 같은 코드를 다시 작성합니다.
public interface IEngine
{
void Start();
}
public class GasEngine : IEngine
{
public void Start()
{
Console.WriteLine("I use gas as my fuel!");
}
}
public class ElectricityEngine : IEngine
{
public void Start()
{
Console.WriteLine("I am electrocar");
}
}
public class Car
{
private readonly IEngine _engine;
public Car(IEngine engine)
{
_engine = engine;
}
public void Run()
{
_engine.Start();
}
}
이제 우리의 자동차 클래스는 엔진의 특정 구현이 아닌 IENGine 인터페이스에만 의존합니다. 이제 유일한 트릭은 우리가 자동차의 인스턴스를 생성하고 GasEngine 또는 ElectryIteSegine과 같은 실제 콘크리트 엔진 클래스를 제공하는 방법입니다.그것이 종속성 주입이 들어있는 곳입니다.
Car gasCar = new Car(new GasEngine());
gasCar.Run();
Car electroCar = new Car(new ElectricityEngine());
electroCar.Run();
여기서 우리는 기본적으로 우리의 의존성 (엔진 인스턴스)을 자동차 생성자에게 주입 (합격)합니다.이제 우리의 수업은 물체와 종속성 사이에 느슨한 커플 링을 가지고 있으며 자동차 클래스를 변경하지 않고 새로운 유형의 엔진을 쉽게 추가 할 수 있습니다.
하드 코딩 된 종속성이 없기 때문에 클래스가 더 느슨하게 결합되어있는 의존 주사의 주요 이점이 있습니다.이것은 위에서 언급 한 종속성 반전 원리를 따릅니다.특정 구현을 참조하는 대신 클래스가 생성 될 때 클래스 요청 추상화 (일반적으로 인터페이스)를 요청합니다.
따라서 최종 의존성 주입에는 다음과 같은 기술이 있습니다. 물체와 종속성 사이의 느슨한 결합을 달성합니다. 클래스가 필요로하는 종속성을 직접 인스턴스화하는 것이 아니라 그 행동을 수행하기 위해 종속성이 클래스에 제공됩니다. (자주) 생성자 주입을 통해.
또한 많은 종속성을 가지고있을 때, 모든 종속성에 대한 구체적인 구현에 대한 구체적인 구현에 매핑되어야하는 인터페이스를 알려주는 인터페이스를 알려주는 컨트롤 (IOC) 컨테이너의 반전을 사용하는 것이 매우 우수합니다.우리 물건.예를 들어, IOC 컨테이너에 대해 IOC 컨테이너에 대한 매핑에서 지정할 수 있으며 차량 클래스의 인스턴스에 대해 IOC 컨테이너에 IOC 컨테이너를 요청할 때 자동차 클래스를 자동으로 구성합니다.전달했다.
업데이트 : 최근 Julie Lerman에서 EF 코어에 대한 코스를 보았고 DI에 대한 짧은 정의를 좋아했습니다.
종속성 주입은 응용 프로그램이 주입 할 수있는 패턴입니다. 그들을 요구하지 않고, 그들을 필요로하는 클래스에 날아 오는 물체 해당 객체에 대한 책임이있는 수업.코드를 입력 할 수 있습니다 더 느슨하게 결합 된 엔티티 프레임 워크 코어 플러그가 더 느슨하게 결합됩니다. 서비스 시스템.
출처:https://stackoverflow.com/questions/130794/what-is-dependency-injection
최근댓글