IoC (Inversion of Control)는 처음 발생할 때 매우 혼란 스러울 수 있습니다.
- 무엇입니까?
- 어떤 문제가 해결됩니까?
- 언제 사용하는 것이 적절합니까?
IoC (Inversion of Control)는 처음 발생할 때 매우 혼란 스러울 수 있습니다.
답변:
제어 반전 (IoC) 및 종속성 주입 (DI) 패턴은 코드에서 종속성을 제거하는 것입니다.
예를 들어, 응용 프로그램에 텍스트 편집기 구성 요소가 있고 철자 검사를 제공하려고한다고 가정하십시오. 표준 코드는 다음과 같습니다.
public class TextEditor {
private SpellChecker checker;
public TextEditor() {
this.checker = new SpellChecker();
}
}
우리가 여기서했던 것은 사이에 의존성 생성 TextEditor
과를 SpellChecker
. IoC 시나리오에서는 대신 다음과 같은 작업을 수행합니다.
public class TextEditor {
private IocSpellChecker checker;
public TextEditor(IocSpellChecker checker) {
this.checker = checker;
}
}
첫 번째 코드 예에서는 인스턴스화된다 SpellChecker
( this.checker = new SpellChecker();
수단되는) TextEditor
클래스에 따라 직접 SpellChecker
클래스.
두 번째 코드 예제에서는 SpellChecker
클래스 의 종속성을 TextEditor
초기화하지 않고의 생성자 서명 에 종속성 클래스 를 사용하여 추상화를 작성합니다 . 이를 통해 종속성을 호출 한 다음 TextEditor 클래스에 전달할 수 있습니다.
SpellChecker sc = new SpellChecker; // dependency
TextEditor textEditor = new TextEditor(sc);
이제 TextEditor
클래스를 만드는 클라이언트 SpellChecker
는 TextEditor
서명에 종속성을 주입하기 때문에 사용할 구현을 제어 할 수 있습니다 .
제어 반전은 GUI 프로그램과 같이 프로그램 콜백시 얻을 수있는 것입니다.
예를 들어 구식 메뉴에는 다음이있을 수 있습니다.
print "enter your name"
read name
print "enter your address"
read address
etc...
store in database
따라서 사용자 상호 작용의 흐름을 제어합니다.
GUI 프로그램 등에서 대신 다음과 같이 말합니다.
when the user types in field a, store it in NAME
when the user types in field b, store it in ADDRESS
when the user clicks the save button, call StoreInDatabase
이제 컴퓨터는 사용자 입력을 고정 된 순서로 받아들이지 않고 데이터를 입력하는 순서와 데이터가 데이터베이스에 저장되는시기를 제어합니다.
기본적으로, 어떤 이벤트 루프는, 콜백, 또는 실행 트리거는이 범주에 빠진다.
제어 역전이란 무엇입니까?
이 간단한 두 단계를 따르면 제어의 반전을 수행 한 것입니다.
구현에 사용중인 기술 / 언어를 기반으로 이러한 각 단계에 가능한 몇 가지 기술이 있습니다.
-
제어 반전 (IoC) 의 반전 부분은 혼란스러운 것입니다. 반전 은 상대적인 용어 이기 때문 입니다. IoC를 이해하는 가장 좋은 방법은 그 단어를 잊어 버리는 것입니다!
-
예
what-to-do
하고when-to-do
컨트롤 반전은 우려를 분리하는 것입니다.
IoC 미포함 : 랩톱 컴퓨터가 있고 실수로 화면을 깰 수 있습니다. 그리고, 당신은 같은 모델의 노트북 화면이 시장에서 어디에도 없다는 것을 알았습니다. 그래서 당신은 붙어 있습니다.
IoC 사용 : 데스크탑 컴퓨터가 있고 실수로 화면을 깰 수 있습니다. 당신은 시장에서 거의 모든 데스크탑 모니터를 잡을 수 있으며 데스크탑과 잘 작동합니다.
이 경우 데스크탑은 IoC를 성공적으로 구현합니다. 다양한 유형의 모니터를 사용할 수 있지만 랩톱은 그렇지 않지만 고정하려면 특정 화면이 필요합니다.
Inversion of Control (또는 IoC)은 자유 를 얻는 것에 관한 것입니다 (결혼하고 자유를 잃고 통제를 받고 있습니다. 이혼하고 방금 Inversion of Control을 구현했습니다. 이것이 바로 "분리"된 것입니다. 스타일을 장려 매우 밀접한 관계.) 더 많은 유연성은 (사무실에 부엌은 당신이 마시고 싶어 할 때 유일한 선택입니다 깨끗한 수돗물을 제공합니다. 당신의 상사가 새로운 커피 머신을 설정하여 컨트롤의 반전을 구현했습니다. 이제 얻을 중 수돗물 또는 커피 선택의 유연성을 제공합니다.)와 덜 의존 (파트너에게는 직업이 있고, 직업이 없으며, 재정적으로 파트너에게 의존하므로, 통제됩니다. 직업을 찾고, 제어 역전을 구현했습니다. 좋은 컴퓨터 시스템은 독립성을 장려합니다.)
데스크탑 컴퓨터를 사용하면 슬레이브 (또는 제어) 상태입니다. 화면 앞에 앉아서 봐야합니다. 키보드를 사용하여 입력하고 마우스를 사용하여 탐색합니다. 잘못 작성된 소프트웨어는 더 많은 노예가 될 수 있습니다. 데스크탑을 랩톱으로 교체하면 제어가 다소 역전됩니다. 쉽게 가지고 다닐 수 있습니다. 이제 컴퓨터를 제어하는 대신 컴퓨터의 현재 위치를 제어 할 수 있습니다.
Inversion of Control을 구현함으로써 소프트웨어 / 개체 소비자는 제어되거나 옵션이 적은 대신 소프트웨어 / 개체에 대해 더 많은 제어 / 옵션을 얻습니다.
위의 아이디어를 염두에두고 우리는 여전히 IoC의 핵심 부분을 그리워합니다. IoC 시나리오에서 소프트웨어 / 개체 소비자는 정교한 프레임 워크입니다. 즉, 생성 한 코드는 사용자가 직접 호출하지 않습니다. 이제이 방법이 웹 애플리케이션에 더 적합한 이유를 설명하겠습니다.
코드가 워커 그룹이라고 가정하십시오. 그들은 차를 만들어야합니다. 이 노동자들은 자동차를 만들 장소와 도구 (소프트웨어 프레임 워크)가 필요합니다. 전통적인 소프트웨어 프레임 워크는 많은 도구와 차고처럼 될 것입니다. 따라서 노동자들은 스스로 계획을 세우고 도구를 사용하여 자동차를 만들어야합니다. 차를 세우는 것은 쉬운 일이 아니므로, 노동자들이 제대로 계획하고 협력하기 란 정말 어려울 것입니다. 현대소프트웨어 프레임 워크는 모든 시설과 관리자가있는 현대 자동차 공장과 같습니다. 작업자는 계획을 세울 필요가 없으며, 관리자 (프레임 워크의 일부, 가장 똑똑한 사람들이며 가장 정교한 계획을 세운)는 작업자가 작업을 수행 할시기 (프레임 워크가 코드라고 함)를 알 수 있도록 조정하는 데 도움이됩니다. 작업자는 관리자가 자신에게 제공하는 도구를 사용할 수있을 정도로 유연해야합니다 (종속성 주입 사용).
근로자는 최상위 수준에서 프로젝트 관리 권한을 관리자에게 제공하지만 (프레임 워크). 그러나 일부 전문가의 도움을받는 것이 좋습니다. 이것이 바로 IoC의 개념입니다.
MVC 아키텍처를 사용하는 최신 웹 응용 프로그램은 URL 라우팅을 수행하고 프레임 워크를 호출 할 컨트롤러를 배치하는 프레임 워크에 의존합니다.
의존성 주입과 제어 역전은 관련이 있습니다. 의존성 주입은 마이크로 레벨에 있고 제어의 반전은 매크로 레벨에 있습니다. 식사 (구현 IoC)를 마치려면 모든 물린 (구현 DI)을 먹어야합니다.
Inversion of Control을 사용하기 전에 장단점이 있다는 사실을 잘 알고 있어야하며 사용하는 이유를 알아야합니다.
장점 :
단점 :
개인적으로 나는 IoC의 장점을 보았고 그것들을 정말로 좋아하지만 가능한 한 IoC를 피하는 경향이 있습니다. 소프트웨어가 더 이상 "실제"프로그램을 구성하는 것이 아니라 단지 하나의 프로그램으로 구성되어야하는 클래스 모음으로 바뀌기 때문입니다. XML 구성 또는 주석 메타 데이터가 없으면 XML 구성 또는 주석 메타 데이터가 분리됩니다.
위키피디아 기사 . 나에게 제어의 반전은 순차적으로 작성된 코드를 위임 구조로 바꾸는 것입니다. 프로그램이 명시 적으로 모든 것을 제어하는 대신, 프로그램은 특정 일이 발생할 때 호출 할 특정 함수를 가진 클래스 또는 라이브러리를 설정합니다.
코드 중복을 해결합니다. 예를 들어, 옛날에는 새로운 이벤트에 대해 시스템 라이브러리를 폴링하여 자체 이벤트 루프를 수동으로 작성했습니다. 요즘 대부분의 최신 API는 시스템 라이브러리에 관심있는 이벤트를 알려 주면 언제 발생하는지 알려줍니다.
제어 반전은 코드 중복을 줄이는 실용적인 방법이며 전체 방법을 복사하고 작은 코드 조각 만 변경하면 제어 반전으로 처리하는 것을 고려할 수 있습니다. 델리게이트, 인터페이스 또는 원시 함수 포인터의 개념을 통해 많은 언어에서 제어 반전이 쉬워졌습니다.
이런 방식으로 작성된 프로그램의 흐름을 따르기가 더 어려울 수 있으므로 모든 경우에 사용하는 것이 적절하지 않습니다. 재사용 할 라이브러리를 작성할 때 메소드를 설계하는 유용한 방법이지만 코드 복제 문제를 실제로 해결하지 않는 한 자체 프로그램의 핵심에서 드물게 사용해야합니다.
하지만 조심해야한다고 생각합니다. 이 패턴을 과도하게 사용하면 매우 복잡한 디자인과 더욱 복잡한 코드를 만들 수 있습니다.
TextEditor를 사용한이 예제와 같이 SpellChecker가 하나만있는 경우 실제로 IoC를 사용할 필요는 없습니까? 단위 테스트 또는 무언가를 작성해야하는 경우가 아니면 ...
어쨌든 : 합리적이어야합니다. 디자인 패턴은 좋은 습관 이지만 설교 할 성경은 아닙니다. 어디에나 붙이지 마십시오.
제어 반전은 시스템에서 구성 요소와 레이어를 분리하는 데 사용되는 패턴입니다. 패턴은 구성 요소가 구성 될 때 종속성을 구성 요소에 주입하여 구현됩니다. 이러한 종속성은 일반적으로 추가 디커플링 및 테스트 가능성을 지원하기위한 인터페이스로 제공됩니다. Castle Windsor, Unity와 같은 IoC / DI 컨테이너는 IoC를 제공하는 데 사용할 수있는 도구 (라이브러리)입니다. 이러한 도구는 수명, AOP / 차단, 정책 등을 포함하여 단순한 종속성 관리 이상의 확장 된 기능을 제공합니다.
ㅏ. 구성 요소가 종속성 관리를 담당하지 않도록합니다.
비. 다른 환경에서 종속성 구현을 교환 할 수있는 기능을 제공합니다.
씨. 종속성을 조롱하여 구성 요소를 테스트 할 수 있습니다.
디. 응용 프로그램 전체에서 리소스를 공유하기위한 메커니즘을 제공합니다.
ㅏ. 테스트 중심 개발을 수행 할 때 중요합니다. IoC가 없으면 테스트중인 구성 요소가 나머지 시스템과 밀접하게 연결되어 있기 때문에 테스트하기가 어려울 수 있습니다.
비. 모듈 식 시스템을 개발할 때 중요합니다. 모듈 식 시스템은 재 컴파일없이 구성 요소를 교체 할 수있는 시스템입니다.
씨. 특히 엔터프라이즈 응용 프로그램에서 해결해야 할 여러 가지 교차 문제가있는 경우 중요합니다.
첫 번째 부분에만 응답합니다. 무엇입니까?
IoC (Inversion of Control)는 클래스의 인스턴스를 먼저 생성 한 다음 클래스 인스턴스가 종속성의 인스턴스를 생성하는 대신 클래스의 인스턴스를 먼저 생성하고 클래스의 후자의 인스턴스를 생성 (선택적으로 생성자를 통해 주입)하는 것을 의미합니다. 따라서 제어의 반전 은 프로그램 의 제어 흐름을 반전 시킵니다 . 대신에 제어 수신자 제어의 흐름 (종속성을 생성하는 동안)에서, 호출자는 프로그램의 제어의 흐름을 제어한다 .
이 두 용어에 대한 간단한 이해를 적어 두겠습니다.
For quick understanding just read examples*
의존성 주입 (DI) :
의존성 주입은 일반적으로 메소드가 종속 오브젝트를 작성하지 않고 메소드에 종속 된 메소드를 매개 변수로 메소드에 전달하는 것을 의미 합니다 .
실제로 의미는 방법이 특정 구현에 직접 의존하지 않는다는 것입니다. 요구 사항을 충족하는 모든 구현은 매개 변수로 전달 될 수 있습니다.
이 객체로 그들의 의존성을 말해줍니다. 그리고 봄은 그것을 사용할 수있게합니다.
이것은 느슨하게 결합 된 응용 프로그램 개발로 이어집니다.
Quick Example:EMPLOYEE OBJECT WHEN CREATED,
IT WILL AUTOMATICALLY CREATE ADDRESS OBJECT
(if address is defines as dependency by Employee object)
IoC (Inversion of Control) 컨테이너 :
프레임 워크의 일반적인 특성으로, IOC 는
인스턴스화에서 BeanFactory를 통한 파괴에 이르기까지 Java 객체를 관리합니다 .
-IoC 컨테이너로 인스턴스화되는 Java 구성 요소를 Bean이라고하며 IoC 컨테이너는 Bean의 범위, 수명주기 이벤트 및 구성 및 코딩 된 AOP 기능 을 관리합니다 .
QUICK EXAMPLE:Inversion of Control is about getting freedom, more flexibility, and less dependency. When you are using a desktop computer, you are slaved (or say, controlled). You have to sit before a screen and look at it. Using keyboard to type and using mouse to navigate. And a bad written software can slave you even more. If you replaced your desktop with a laptop, then you somewhat inverted control. You can easily take it and move around. So now you can control where you are with your computer, instead of computer controlling it
.
Inversion of Control을 구현하면 소프트웨어 / 개체 소비자는 제어되거나 옵션이 적은 대신 소프트웨어 / 개체에 대해 더 많은 제어 / 옵션을 얻을 수 있습니다.
설계 지침으로 제어를 뒤집 으면 다음과 같은 목적으로 사용됩니다.
구현에서 특정 작업의 실행을 분리합니다.
모든 모듈은 설계된 용도에 집중할 수 있습니다.
모듈은 다른 시스템의 기능에 대한 가정을하지 않고 계약에 의존합니다.
모듈을 교체해도 다른 모듈에는 부작용이 없습니다.
여기서는 요약 할 것입니다. 주제를 자세히 이해하려면 다음 링크를 방문하십시오.
예제를 잘 읽고
NilObject에 동의 하지만 다음과 같이 추가하고 싶습니다.
전체 메소드를 복사하고 작은 코드 조각 만 변경하면 제어를 거꾸로 처리하는 것이 좋습니다.
자신이 코드를 복사하여 붙여 넣는 것을 발견하면 거의 항상 무언가 잘못하고 있습니다. 설계 원칙으로 성문화 한 번만 .
예를 들어, 작업 # 1은 객체를 만드는 것입니다. IOC 개념이 없으면 작업 1이 프로그래머가 수행해야하지만 IOC 개념이 있으면 작업 1이 컨테이너에 의해 수행됩니다.
간단히 말해 Control은 프로그래머에서 컨테이너로 바뀝니다. 제어의 반전이라고합니다.
호텔에서 회의를한다고하자.
많은 사람들, 많은 물 한 잔, 많은 플라스틱 컵.
누군가가 마시고 싶을 때, 그녀는 컵을 채우고, 마시고 컵을 바닥에 던졌습니다.
몇 시간 후 또는 우리는 플라스틱 컵과 물로 바닥을 덮었습니다.
제어를 반전 시키십시오.
같은 장소에서 같은 모임이지만 플라스틱 컵 대신 유리 컵 (싱글 톤)이있는 웨이터가 있습니다.
그리고 그녀는 항상 손님에게 술을 제공합니다.
누군가 마시고 싶을 때 웨이터 유리에서 나와서 다시 웨이터에게 돌려줍니다.
위생적인 문제를 제쳐두고, 마지막 형태의 음주 공정 제어는 훨씬 더 효과적이고 경제적입니다.
이것이 바로 Spring (예 : 다른 IoC 컨테이너, Guice)의 기능입니다. Spring IoC 컨테이너는 항상 새로운 키워드 (플라스틱 컵 사용)를 사용하여 필요한 것을 만들도록하는 대신 필요한 객체 (물 유리)의 동일한 인스턴스 (단일)를 적용 할 수 있도록 항상 제공합니다.
그러한 모임의 주최자로서 자신을 생각하십시오. 호텔 관리에게 메시지를 보내는 방법이 필요합니다.
회의 회원은 물 한 잔이 필요하지만 케이크 조각은 필요하지 않습니다.
예:-
public class MeetingMember {
private GlassOfWater glassOfWater;
...
public void setGlassOfWater(GlassOfWater glassOfWater){
this.glassOfWater = glassOfWater;
}
//your glassOfWater object initialized and ready to use...
//spring IoC called setGlassOfWater method itself in order to
//offer to meetingMember glassOfWater instance
}
유용한 링크:-
"IoC"에 대해 가장 혼동되는 것은 약어와 그 이름의 이름이 너무 매력적이어서 거의 소음이없는 것입니다.
절차 적 프로그래밍과 이벤트 중심 프로그래밍의 차이점을 설명 할 수있는 이름이 정말로 필요합니까? 우리가 필요로한다면 문제보다 더 혼란스러운 새로운 "생명보다 더 큰"이름을 선택해야합니까?
제어 역전 당신이 식료품 가게에 가서 당신의 아내는 당신이 구입하는 제품의 목록을 제공 할 때입니다.
프로그래밍 용어로 콜백 함수 getProductList()
를 실행중인 함수 에 전달했습니다.doShopping()
.
함수의 사용자가 함수의 일부를 정의 할 수있어보다 유연합니다.
getProductList()
이 돈의 원천을 찾아야 할 때 통제가 당신 편이라는 것을 의미합니다. 반전의 경우, 그녀는 통제 할 것이며, 그녀는 또한 구매를 위해 제공 할 돈을 의미합니다.
여기서 '제어가 반전되는 방법'을 설명하는 매우 명확한 예를 찾았습니다 .
클래식 코드 (종속성 주입 없음)
DI를 사용하지 않는 코드가 대략적으로 작동하는 방법은 다음과 같습니다.
의존성 주입 사용
DI를 사용하는 코드가 대략적으로 작동하는 방법은 다음과 같습니다.
종속성의 제어는 호출되는 호출에서 호출되는 호출로 반전됩니다.
어떤 문제가 해결됩니까?
의존성 주입을 통해 주입 된 클래스의 다른 구현으로 쉽게 교체 할 수 있습니다. 단위 테스트를 수행하는 동안 더미 구현을 삽입 할 수 있으므로 테스트가 훨씬 쉬워집니다.
예 : 애플리케이션이 사용자가 업로드 한 파일을 Google 드라이브에 저장한다고 가정하면 DI와 함께 컨트롤러 코드는 다음과 같습니다.
class SomeController
{
private $storage;
function __construct(StorageServiceInterface $storage)
{
$this->storage = $storage;
}
public function myFunction ()
{
return $this->storage->getFile($fileName);
}
}
class GoogleDriveService implements StorageServiceInterface
{
public function authenticate($user) {}
public function putFile($file) {}
public function getFile($file) {}
}
요구 사항이 변경되면 GoogleDrive 대신 Dropbox를 사용해야합니다. StorageServiceInterface에 대한 드롭 박스 구현 만 작성하면됩니다. Dropbox 구현이 StorageServiceInterface를 준수하는 한 컨트롤러를 변경하지 않아도됩니다.
테스트하는 동안 모든 메소드가 널 (또는 테스트 요구 사항에 따라 사전 정의 된 값)을 리턴하는 더미 구현으로 StorageServiceInterface에 대한 모의를 작성할 수 있습니다.
대신 다음과 같이 new
키워드를 사용 하여 스토리지 오브젝트를 구성하는 컨트롤러 클래스가있는 경우 :
class SomeController
{
private $storage;
function __construct()
{
$this->storage = new GoogleDriveService();
}
public function myFunction ()
{
return $this->storage->getFile($fileName);
}
}
Dropbox 구현으로 변경하려면 new
GoogleDriveService 객체가 생성 된 모든 줄을 바꾸고 DropboxService를 사용해야합니다. SomeController 클래스를 테스트 할 때 생성자는 항상 GoogleDriveService 클래스를 기대하고이 클래스의 실제 메소드가 트리거됩니다.
적절한시기와시기는? 내 생각에 당신은 클래스의 대체 구현이 있거나있을 수 있다고 생각할 때 DI를 사용합니다.
매우 간단한 서면 설명은 여기에서 찾을 수 있습니다
http://binstock.blogspot.in/2008/01/excellent-explanation-of-dependency.html
그것은 말한다-
"모든 사소한 응용 프로그램은 비즈니스 로직을 수행하기 위해 서로 협력하는 둘 이상의 클래스로 구성됩니다. 일반적으로 각 개체는 공동 작업하는 개체 (종속성)에 대한 자체 참조를 가져옵니다. DI를 적용 할 때는 객체는 시스템의 각 객체를 조정하는 외부 엔티티에 의해 생성 시점에 종속성이 부여됩니다. 즉, 종속성은 객체에 주입됩니다. "
Control of Inversion은 일반적인 원칙이며, Dependency Injection은이 원칙을 객체 그래프 구성을위한 디자인 패턴으로 인식합니다 (예 : 구성은 객체 자체가 다른 객체에 대한 참조를 얻는 방법을 제어하는 것이 아니라 객체가 서로를 참조하는 방식을 제어합니다).
Inversion of Control을 디자인 패턴으로보고, 우리가 뒤집는 것을 살펴 봐야합니다. 의존성 주입은 객체의 그래프 구성 제어를 반전시킵니다. 평신도의 용어로 말하면 제어의 반전은 프로그램의 제어 흐름의 변화를 의미합니다. 예 : 기존의 독립형 앱에는 컨트롤이 다른 타사 라이브러리로 전달되는 주요 방법이 있지만 (타사 라이브러리 기능을 사용하는 경우) 제어 제어의 반전을 통해 타사 라이브러리 코드에서 코드로 전송됩니다. , 제 3 자 도서관 서비스를 받고 있습니다. 그러나 프로그램 내에서 반전되어야하는 다른 측면들 (예 : 코드를 실행하기위한 메소드 및 스레드 호출)이 있습니다.
Inversion of Control에 대해 더 깊이 관심이있는 사람들을 위해 디자인 패턴으로서 Control of Inversion에 대한보다 완전한 그림을 요약 한 논문이 발표되었습니다 (OfficeFloor : 사무실 패턴을 사용하여 소프트웨어 디자인 개선 http://doi.acm.org/10.1145/ http://www.officefloor.net/about.html 에서 무료로 다운로드 할 수있는 2739011.2739013 ).
식별되는 것은 다음 관계입니다.
제어 역전 (방법의 경우) = 종속성 (상태) 주입 + 연속 주입 + 스레드 주입
사용 가능한 제어 역전에 대한 위의 관계 요약-http: //dzone.com/articles/inversion-of-coupling-control
IoC는 코드와 타사 코드 (라이브러리 / 프레임 워크) 간의 관계를 반전시키는 것입니다.
DI (Dependency Injection)는 응용 프로그램에서 컨트롤의 흐름에 관한 것입니다. 전통적인 데스크톱 응용 프로그램은 응용 프로그램 (main () 메서드)에서 다른 라이브러리 메서드 호출로 제어 흐름을 가졌지 만 DI 제어 흐름을 거꾸로하면 프레임 워크가 앱을 시작하고 초기화하고 필요할 때마다 메서드를 호출합니다.
결국 당신은 항상 승리 :)
나는이 설명을 좋아한다 : http://joelabrahamsson.com/inversion-of-control-an-introduction-with-examples-in-net/
간단하게 시작하고 코드 예제도 보여줍니다.
소비자 X는 무언가를 달성하기 위해 소비 클래스 Y가 필요합니다. 그것은 모두 좋고 자연 스럽지만 X는 실제로 Y를 사용한다는 것을 알아야합니까?
X가 누가 실제로 행동을 구현하는지 모르면서 Y의 행동, 방법, 속성 등을 가진 것을 사용한다는 것을 X가 아는 것만으로는 충분하지 않습니까?
아래 I과 같이 Y에서 X가 사용하는 동작에 대한 추상 정의를 추출하고 소비자 X가 Y 대신 해당 인스턴스를 사용하게하면 Y에 대한 세부 사항을 알 필요없이 계속 수행 할 수 있습니다.
위의 그림에서 Y는 I을 구현하고 X는 I의 인스턴스를 사용합니다. X가 여전히 Y를 사용하는 것이 가능하지만 흥미로운 것은 X가 그것을 모르는 것입니다. 그것은 내가 그것을 구현하는 것을 사용한다는 것을 알고 있습니다.
다음과 같은 이점에 대한 자세한 정보 및 설명은 기사를 읽으십시오.
...
답변이 이미 여기에 있음을 이해합니다. 그러나 나는 여전히 미래의 독자들을 위해 통제 역전에 대한 몇 가지 기본 사항에 대해 오랫동안 논의해야한다고 생각합니다.
IoC (Inversion of Control)는 Hollywood Principle 이라는 매우 간단한 원칙을 기반으로 구축되었습니다 . 그리고 그것은 말합니다.
전화 하지마, 전화 할께
의미는 당신이 합당하다면 꿈을 이루기 위해 할리우드에 가지 않는 것입니다. 할리우드는 당신을 찾고 꿈을 이룰 것입니다. 거꾸로 된 거지?
이제 우리는 IoC의 원칙에 대해 논의 할 때 할리우드를 잊어 버리기 위해 사용합니다. IoC를 위해서는 할리우드, 당신, 그리고 당신의 꿈을 이루기위한 과제의 세 가지 요소가 있어야합니다.
프로그래밍 세계에서 Hollywood 는 일반적인 프레임 워크 (귀하 또는 다른 사람이 작성할 수 있음) 를 나타내며, 작성한 사용자 코드 및 작업 을 나타냅니다. 나타내며 은 코드로 수행하려는 것을 나타냅니다. 이제 IoC가 아닌 혼자서 작업을 시작하지 않아도됩니다. 오히려 프레임 워크가 작업을 트리거하도록 모든 것을 설계했습니다. 따라서 누군가를 영웅이나 다른 사람으로 만들 수있는 재사용 가능한 프레임 워크를 만들었습니다. 그러나 그 프레임 워크는 항상 책임이 있으며, 누군가를 고를 때를 알고 누군가가 자신이 원하는 것을 알고 있다는 것을 압니다.
실제 사례가 여기에 주어질 것입니다. 웹 애플리케이션을 개발하려고한다고 가정하십시오. 따라서 웹 응용 프로그램이 http 요청 처리, 응용 프로그램 메뉴 생성, 페이지 제공, 쿠키 관리, 이벤트 트리거 등과 같이 웹 응용 프로그램이 처리해야하는 모든 공통 사항을 처리하는 프레임 워크를 만듭니다.
그런 다음 프레임 워크에 후크를 남겨서 사용자 정의 메뉴, 페이지, 쿠키를 생성하거나 일부 사용자 이벤트 등을 생성하는 추가 코드를 넣을 수 있습니다. 모든 브라우저 요청에서 프레임 워크가 실행되면 사용자 정의 코드가 실행되고 다시 실행됩니다. 브라우저에.
아이디어는 매우 간단합니다. 모든 것을 제어하는 사용자 응용 프로그램을 만드는 대신 먼저 모든 것을 제어하는 재사용 가능한 프레임 워크를 만든 다음 사용자 지정 코드를 작성하여 프레임 워크에 연결하여 제 시간에 실행되도록하십시오.
라 라벨과 EJB가 그러한 프레임 워크의 예입니다.
참고:
프로그래밍 말하기
쉬운 용어로 IoC : 인터페이스를 특정 클래스 (예 : 필드 또는 매개 변수)로 와일드 카드로 사용하여 일부 클래스에서 사용할 수 있습니다. 코드를 재사용 할 수 있습니다.
예를 들어 두 개의 클래스가 있다고 가정 해 봅시다. Dog 와 Cat의 . 둘 다 같은 질 / 상태를 공유합니다 : 나이, 크기, 체중. 따라서 DogService 및 CatService 라는 서비스 클래스를 작성하는 대신 IAnimal 인터페이스를 사용하는 경우에만 Dog 및 Cat을 사용할 수있는 AnimalService 라는 단일 클래스를 작성할 수 있습니다 .
그러나 실용적으로 말하면 약간 뒤로 향합니다.
a) 대부분의 개발자들은 그것을 사용하는 방법을 모른다 . 예를 들어, 나는라는 클래스 만들 수 있습니다 고객 과 내가 자동으로 생성 할 수 있습니다 라는 인터페이스 (IDE의 도구 사용) ICustomer을 . 따라서 인터페이스의 재사용 여부에 관계없이 클래스와 인터페이스로 채워진 폴더를 찾는 것은 드문 일이 아닙니다. BLOATED라고합니다. 어떤 사람들은 "나중에 우리가 그것을 사용할 수 있을지도 모른다"고 주장 할 수 있습니다. :-|
b) 한계가있다. 예를 들어, Dog and Cat 의 경우에 대해 이야기하고 개 에만 새로운 서비스 (기능)를 추가하고 싶습니다. 내가 개를 훈련시키는 데 필요한 일 수를 계산하고 싶다고 가정 해 봅시다 ( trainDays()
). 고양이는 쓸모가 없으며 고양이를 훈련시킬 수 없습니다 (농담 중).
b.1) trainDays()
서비스 AnimalService에 추가 하면 고양이와도 작동하며 전혀 유효하지 않습니다.
b.2) trainDays()
어떤 클래스가 사용되는지 평가 하는 조건을 추가 할 수 있습니다 . 그러나 그것은 완전히 IoC를 망칠 것입니다.
b.3) 새로운 기능을 위해 DogService 라는 새로운 서비스 클래스를 만들 수 있습니다 . 그러나 Dog에 대해 두 가지 서비스 클래스 (유사한 기능)가 있고 코드가 나쁘기 때문에 코드 유지 관리 성이 향상됩니다 .
나는 이것에 대한 많은 답변을 읽었지만 누군가가 여전히 혼란스럽고 여기에 IoC를 설명하기 위해 플러스 "레이맨 용어"가 필요하다면 여기 내 테이크입니다.
부모와 자녀가 서로 이야기한다고 상상해보십시오.
IoC없이 :
*부모의 : 질문 할 때만 말할 수 있고 허락 할 때만 행동 할 수 있습니다.
부모 : 이것은 당신이 나에게 물어 보지 않으면 먹고, 놀고, 화장실에 가거나, 심지어 잠을 잘 수 있는지 나에게 물어볼 수 없다는 것을 의미합니다.
부모 : 먹고 싶니?
아동 : 아니오
부모 : 좋아, 돌아올 게. 날 기다려.
Child : (놀이를하고 싶지만 부모로부터 의심의 여지가 없으므로 아이는 아무것도 할 수 없습니다).
1 시간 후에...
부모 : 돌아 왔어요. 당신이 연주하고 싶어?
아이 : 예.
부모 : 권한 부여.
어린이 : (마지막으로 재생할 수 있습니다).
이 간단한 시나리오는 컨트롤이 부모를 중심으로 설명합니다. 자녀의 자유는 제한되어 있으며 부모의 질문에 크게 의존합니다. 아동은 발언 요청이있을 때만 발언 할 수 있으며 허가가있을 때만 행동 할 수 있습니다 .
IoC로 :
자녀는 이제 질문을 할 수 있으며 부모는 답변과 허락으로 응답 할 수 있습니다. 간단히 컨트롤이 반전되었음을 의미합니다! 이제 자녀는 언제든지 질문을 자유롭게 할 수 있으며 허가와 관련하여 여전히 부모와의 의존 관계는 있지만 질문을하거나 말하는 방법에는 의존하지 않습니다.
기술적으로 설명하면 콘솔 / 쉘 / cmd 대 GUI 상호 작용과 매우 유사합니다. (마크 해리슨의 답변은 2 위의 최고 답변입니다). 콘솔에서, 당신은 당신에게 요청 / 표시되는 것에 의존하며, 먼저 질문에 대답하지 않고 다른 메뉴와 기능으로 이동할 수 없습니다; 엄격한 순차적 흐름을 따릅니다. (프로그래밍 방식은 메소드 / 함수 루프와 같습니다). 그러나 GUI를 사용하면 메뉴와 기능이 배치되고 사용자는 필요한 것을 선택할 수 있으므로 더 많은 제어 와 제한을받지 않아도 됩니다. 프로그래밍 방식으로 메뉴를 선택하면 콜백이 발생하고 작업이 수행됩니다.
제어의 반전은 라이브러리에서 클라이언트로 제어를 전송하는 것입니다. 함수 값 (람다 식)을 라이브러리 함수의 동작을 제어 (변경)하는 상위 함수 (라이브러리 함수)에 삽입 (전달)하는 클라이언트에 대해 이야기하는 것이 더 합리적입니다. 라이브러리 의존성 (동작을 수행하는)을 라이브러리에 주입하는 클라이언트 또는 프레임 워크도 IoC로 간주 될 수 있습니다.
이미 질문에 대한 많은 답변이 있지만 그중 어느 것도 반전 제어 용어의 고장을 보여주지 않습니다. 더 간결하고 유용한 답변을 줄 수있는 기회를 봅니다.
Inversion of Control은 DIP (Dependency Inversion Principle)를 구현하는 패턴입니다. DIP는 다음을 나타냅니다. 1. 높은 수준의 모듈은 낮은 수준의 모듈에 의존해서는 안됩니다. 둘 다 추상화 (예 : 인터페이스)에 의존해야합니다. 2. 추상화는 세부 사항에 의존해서는 안됩니다. 세부 사항 (콘크리트 구현)은 추상화에 따라 달라집니다.
Inversion of Control에는 세 가지 유형이 있습니다.
Interface Inversion Providers는 인터페이스를 정의하지 않아야합니다. 대신 소비자는 인터페이스를 정의해야하며 공급자는이를 구현해야합니다. Interface Inversion을 사용하면 새로운 공급자를 추가 할 때마다 소비자를 수정할 필요가 없습니다.
흐름 반전 흐름 제어를 변경합니다. 예를 들어, 많은 매개 변수를 입력하도록 요청한 콘솔 응용 프로그램이 있으며 입력 한 각 매개 변수 다음에 Enter 키를 눌러야합니다. 여기서 Flow Inversion을 적용하고 사용자가 매개 변수 입력 순서를 선택할 수 있고 사용자가 매개 변수를 편집 할 수 있으며 마지막 단계에서 Enter를 한 번만 눌러야하는 데스크탑 애플리케이션을 구현할 수 있습니다.
Creation Inversion 공장 패턴, 서비스 로케이터 및 종속성 주입 패턴으로 구현할 수 있습니다. Creation Inversion은 종속성 개체의 프로세스를 이러한 종속성 개체를 사용하는 형식 외부로 이동시키는 형식 간의 종속성을 제거하는 데 도움이됩니다. 종속성이 나쁜 이유는 무엇입니까? 다음은 몇 가지 예입니다. 코드에서 새 객체를 직접 작성하면 테스트가 더 어려워집니다. 재 컴파일없이 어셈블리에서 참조를 변경하는 것은 불가능합니다 (OCP 원칙 위반). 데스크탑 UI를 웹 UI로 쉽게 대체 할 수 없습니다.
위의 1 번 . 제어 역전이란 무엇입니까?
유지 보수는 나를 위해 해결하는 가장 중요한 것입니다. 두 클래스가 서로 친밀하지 않도록 인터페이스를 사용하고 있음을 보장합니다.
Castle Windsor와 같은 컨테이너를 사용하면 유지 관리 문제를 훨씬 더 잘 해결합니다. 코드 행을 변경하지 않고 파일 기반 지속성을 사용하는 구성 요소를 데이터베이스로 이동하는 구성 요소를 교체 할 수 있다는 것은 대단합니다 (구성 변경이 완료되었습니다).
그리고 일단 제네릭에 들어가면 더 좋아집니다. 레코드를 받고 메시지를 게시하는 메시지 게시자가 있다고 가정합니다. 게시하는 내용은 중요하지 않지만 레코드에서 메시지로 무언가를 가져 오려면 매퍼가 필요합니다.
public class MessagePublisher<RECORD,MESSAGE>
{
public MessagePublisher(IMapper<RECORD,MESSAGE> mapper,IRemoteEndpoint endPointToSendTo)
{
//setup
}
}
한 번 작성했지만 다른 유형의 메시지를 게시하면이 코드 세트에 여러 유형을 삽입 할 수 있습니다. 또한 같은 유형의 레코드를 가져와 다른 메시지에 매핑하는 매퍼를 작성할 수 있습니다. DI를 Generics와 함께 사용하면 많은 작업을 수행하기 위해 코드를 거의 작성할 수 없습니다.
예, 테스트 가능성 문제가 있지만 IoC / DI의 이점에 부차적입니다.
나는 IoC / DI를 확실히 좋아합니다.
삼 . 다소 규모가 더 복잡한 중간 규모의 프로젝트가있을 때 더 적합합니다. 나는 당신이 고통을 느끼기 시작하는 순간 그것이 적절 해 진다고 말할 것입니다.