JavaRush /Java Blog /Random-KO /의존성을 주입하는 쉬운 방법

의존성을 주입하는 쉬운 방법

Random-KO 그룹에 게시되었습니다
DI(종속성 주입)는 이해하기 쉬운 개념이 아니며 새 애플리케이션이나 기존 애플리케이션에 적용하는 것은 더욱 혼란스럽습니다. Jess Smith는 C# 및 Java 프로그래밍 언어에서 주입 컨테이너 없이 종속성 주입을 수행하는 방법을 보여줍니다. 의존성 주입의 간단한 방법 - 1이 기사에서는 .NET 및 Java 애플리케이션에서 DI(종속성 주입)를 구현하는 방법을 보여 드리겠습니다. 종속성 주입의 개념은 2000년에 Robert Martin이 "디자인 원리 및 패턴"(이후 약어 SOLID 로 알려짐 )이라는 기사를 작성하면서 처음으로 개발자의 관심을 끌었습니다. SOLID의 D는 DOI(Dependency of Inversion)를 나타내며 나중에 종속성 주입으로 알려졌습니다. 독창적이고 가장 일반적인 정의: 종속성 반전은 기본 클래스가 종속성을 관리하는 방식을 반전한 것입니다. CopyMartin의 원본 기사에서는 하위 수준 클래스에 대한 클래스의 종속성을 설명하기 위해 다음 코드를 사용했습니다 WritePrinter.
void Copy()
	{
	 int c;
	 while ((c = ReadKeyboard()) != EOF)
		WritePrinter(c);
	}
첫 번째 명백한 문제는 매개변수 목록이나 메소드 유형을 변경하는 경우 WritePrinter해당 메소드에 대한 종속성이 있는 곳마다 업데이트를 구현해야 한다는 것입니다. 이 프로세스는 유지 관리 비용을 증가시키고 새로운 오류의 잠재적인 원인이 됩니다.
Java에 대해 읽고 싶으십니까? Java 개발자 그룹에 가입하세요 !
또 다른 문제: Copy 클래스는 더 이상 잠재적인 재사용 후보가 아닙니다. 예를 들어, 키보드에서 입력한 문자를 프린터가 아닌 파일로 출력해야 한다면 어떻게 될까요? 이렇게 하려면 클래스를 Copy다음과 같이 수정하면 됩니다(C++ 언어 구문).
void Copy(outputDevice dev)
	{
	int c;
	while ((c = ReadKeyboard()) != EOF)
		if (dev == printer)
			WritePrinter(c);
		else
			WriteDisk(c);
	}
새로운 종속성의 도입에도 불구하고 WriteDisk상황은 개선되지 않았습니다(오히려 악화되었습니다). "소프트웨어 엔터티, 즉 클래스, 모듈, 함수 등은 확장을 위해 개방되어야 하지만 확장을 위해 폐쇄되어야 합니다." 가감." Martin은 이러한 새로운 조건부 if/else 문이 코드의 안정성과 유연성을 감소시킨다고 설명합니다. 해결책은 쓰기 및 읽기 메서드가 Copy. 종속성을 "푸시"하는 대신 생성자를 통해 전달됩니다. 수정된 코드는 다음과 같습니다.
class Reader
	{
		public:
		virtual int Read() = 0;
	};
	class Writer
	{
		public:
		virtual void Write(char) = 0;
	};
	void Copy(Reader& r, Writer& w)
	{
		int c;
		while((c=r.Read()) != EOF)
		w.Write(c);
	}
이제 클래스 메소드 및 의 다양한 구현을 통해 클래스를 Copy쉽게 재사용할 수 있습니다 . 클래스에는 유형 및 의 내부 구조에 대한 정보가 없으므로 다른 구현에서 재사용이 가능합니다. 그러나 이 모든 것이 당신에게 일종의 멍청한 짓처럼 보인다면 아마도 Java와 C#으로 작성된 다음 예제가 상황을 명확하게 해줄 것입니다. ReaderWriterCopyReaderWriter

Java 및 C#의 예

DI종속성 컨테이너 없이 종속성 주입이 얼마나 쉬운지 설명하기 위해 몇 단계만으로 사용자 정의할 수 있는 간단한 예제부터 시작해 보겠습니다 . HtmlUserPresentation메서드가 호출될 때 HTML 사용자 인터페이스를 생성하는 클래스가 있다고 가정해 보겠습니다 . 간단한 예는 다음과 같습니다.
HtmlUserPresentation htmlUserPresentation = new HtmlUserPresentation();
String table = htmlUserPresentation.createTable(rowTableVals, "Login Error Status");
이 클래스 코드를 사용하는 모든 프로젝트는 클래스에 대한 종속성을 가지며 HtmlUserPresentation위에서 설명한 유용성 및 유지 관리 문제가 발생합니다. 개선 사항은 즉시 제안됩니다. 현재 클래스에서 사용할 수 있는 모든 메서드의 시그니처로 인터페이스를 생성하는 것입니다 HtmlUserPresentation. 다음은 이 인터페이스의 예입니다.
public interface IHtmlUserPresentation {
	String createTable(ArrayList rowVals, String caption);
	String createTableRow(String tableCol);
	// Оставшиеся сигнатуры
}
HtmlUserPresentation인터페이스를 생성한 후 이를 사용하도록 클래스를 수정합니다 . type 인스턴스화로 돌아가서 HtmlUserPresentation이제 기본 유형 대신 인터페이스 유형을 사용할 수 있습니다.
IHtmlUserPresentation htmlUserPresentation = new HtmlUserPresentation();
String table = htmlUserPresentation.createTable(rowTableVals, "Login Error Status");
인터페이스를 생성하면 IHtmlUserPresentation. 예를 들어, 이 유형을 테스트하려는 경우 기본 유형을 HtmlUserPresentation이라는 다른 유형으로 쉽게 바꿀 수 있습니다 HtmlUserPresentationTest. 지금까지 변경한 사항으로 인해 코드를 더 쉽게 테스트, 유지 관리 및 확장할 수 있지만 HtmlUserPresentation해당 유형을 사용하는 모든 클래스가 여전히 해당 유형의 존재를 인식하므로 재사용할 수 없습니다. IHtmlUserPresentation이러한 직접적인 종속성을 제거하려면 이를 사용할 클래스나 메서드의 생성자(또는 메서드 매개 변수 목록)에 인터페이스 유형을 전달할 수 있습니다 .
public UploadFile(IHtmlUserPresentation htmlUserPresentation)
생성자는 UploadFile이제 유형의 모든 기능에 액세스할 수 IHtmlUserPresentation있지만 이 인터페이스를 구현하는 클래스의 내부 구조에 대해서는 아무것도 모릅니다. 이러한 맥락에서 유형 주입은 클래스의 인스턴스가 생성될 때 발생합니다 UploadFile. IHtmlUserPresentation다른 기능이 필요한 다른 클래스나 메서드에 다른 구현을 전달하면 인터페이스 유형을 재사용할 수 있습니다.

자료 통합을 위한 결론 및 권장 사항

종속성 주입에 대해 배웠고, 클래스 중 하나가 대상 유형의 기능에 액세스하기 위해 다른 클래스를 인스턴스화할 때 클래스가 서로 직접적으로 종속된다고 배웠습니다. 두 유형 간의 직접적인 종속성을 분리하려면 인터페이스를 생성해야 합니다. 인터페이스는 필요한 기능의 컨텍스트에 따라 다양한 구현을 포함할 수 있는 기능을 유형에 제공합니다. 인터페이스 유형을 클래스 생성자 또는 메소드에 전달하면 해당 기능이 필요한 클래스/메서드는 인터페이스를 구현하는 유형에 대한 세부 정보를 알 수 없습니다. 이로 인해 인터페이스 유형은 유사하지만 동일하지는 않은 동작을 요구하는 여러 클래스에서 재사용될 수 있습니다.
  • 종속성 주입을 실험하려면 하나 이상의 애플리케이션에서 코드를 살펴보고 많이 사용되는 기본 유형을 인터페이스로 변환해 보세요.

  • 이 기본 유형을 직접 인스턴스화하는 클래스를 변경하여 이 새로운 인터페이스 유형을 사용하고 이를 사용할 클래스 메소드의 생성자 또는 매개변수 목록을 통해 전달하십시오.

  • 이 인터페이스 유형을 테스트하기 위한 테스트 구현을 만듭니다. 코드가 리팩터링되면 DI구현이 더 쉬워지고 재사용 및 유지 관리 측면에서 애플리케이션이 얼마나 유연해지는지 알게 될 것입니다.
코멘트
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION