제어 역전이 왜 그렇게 명명 되었습니까?


98

내가 본 정의에서 Inversion of Control을 정의하기 위해 단어 가 사용 invert되거나 control전혀 사용되지 않습니다.

정의

위키 백과

IoC (inversion of control)는 객체 지향 프로그래밍 측면에서 표현 된 프로그래밍 기법으로, 객체 결합은 런타임에 어셈블러 객체에 의해 바인딩되며 일반적으로 정적 분석을 사용하여 컴파일 타임에 알려지지 않습니다. ~ http://en.wikipedia.org/wiki/Inversion_of_control

마틴 파울러

Inversion of Control은 Java 커뮤니티에서 공통적으로 사용되는 패턴으로 경량 컨테이너를 연결하거나 다른 프로젝트의 구성 요소를 응집 된 응용 프로그램으로 조립하는 데 도움이됩니다. ~ http://www.martinfowler.com/articles/injection.html 기반 (reworded)


그렇다면 왜 Inversion of Control은 Inversion of Control입니까? 어떤 제어가 반전되고 무엇에 의해? 용어를 사용하여 제어 반전을 정의하는 방법이 있습니까 : 반전제어 ?


22
이것을 일반 영어로
Robert Harvey

2
정의에서 정의하고있는 단어를 사용하면 사전에 오류가 발생합니다. 비슷한 논리가 여기에 적용됩니다.
이즈 카타


2
@Izkata, 사전에서 문구 자체 용어 또는 동의어 용어로 문구를 정의하는 것이 매우 일반적입니다. 즉 , 자연 정의 의 힘은 정의에서 힘과 자연이라는 단어를 사용하거나 서비스 용어 정의는 규칙이 용어와 동의어 인 규칙과 서비스라는 단어를 사용합니다.
Korey Hinton

3
이러한 이유로 IoC 대신 "자동 의존성 주입"또는 ADI라는 용어를 사용하는 것이 좋습니다. 파울러 자신은 프로그래밍의 현재 대부분의 패러다임에는 일종의 "제어 역전 (inversion of control)"이 있으며, 여기서 그 용어는 일반적으로 "실행될 코드 결정의 재 요청 및 외부로 실행되어야하는 시간"으로 정의된다 그러한 결정이 전통적으로 프로그램 자체에 의해 이루어질 때, 제어 시스템 ". 하드웨어 인터럽트부터 이벤트 중심 프로그래밍, 가상 머신 및 멀티 태스킹까지 모든 것이 IoC에서 발생합니다.
KeithS

답변:


67

일종의 "리포지토리"클래스가 있고 해당 리포지토리가 데이터 소스에서 데이터를 전달하는 역할을 담당한다고 가정합니다.

저장소는 자체적으로 데이터 소스에 대한 연결을 설정할 수 있습니다. 그러나 저장소의 생성자를 통해 데이터 소스에 대한 연결을 전달할 수 있다면 어떨까요?

연결을 제공하기 위해 발신자를 허용함으로써, 당신은 수 저장소 클래스에서 데이터 소스 연결 의존성을 분리 한 모든 저장소가 지정뿐 아니라 하나의 데이터 소스가 저장소와 작업 할 수 있습니다.

당신은 제어 반전 호출자에게 저장소 클래스에서 연결을 만드는의 책임을 나눠으로.

Martin Fowler는 "Dependency Injection"이라는 용어를 사용하여 이러한 유형의 제어 역전을 설명 할 것을 제안합니다. 제어 역전은 개념으로서 생성자 메소드에 의존성을 주입하는 것보다 더 광범위하게 적용될 수 있기 때문입니다.


3
이것은 의존성 주입의 예이지만 의존성 주입은 제어 역전의 일부일뿐입니다. 제어 역전을 수행하는 의존성 주입과 완전히 관련이없는 다른 것들이 있습니다.
dsw88

1
@ mustang2009cobra : 감사합니다. 예를 들자면, 인스턴스가 발생하는 포괄적 인 카탈로그가 아니라, "제어의 반전"이라는 용어는 메시지 전달이나 다른 유사한 개념이 아니라 DI와 가장 밀접한 관련이 있습니다.
Robert Harvey

사실, 의존성 주입은 IoC의 가장 일반적인 예이므로 DI의 예가 가장 적합합니다. 아마도 이것이 가장 유명한 유형의 IoC 인 DI 예제임을 명시한 약간의 답변 변경 일 것입니다.
dsw88

1
이것이 바로 내가 찾던 것입니다! IoC의 많은 예제와 정의는 어떤 컨트롤이 반전되는지 명확하게 지정하지 않습니다. 나는 의존성 주입보다 IoC에 더 많은 것이있을 수 있다는 것을 알고 있지만 이제는 내 두뇌에서 무언가가 클릭되었습니다. 감사!
코리 힌턴

79

Martin Fowler보다 더 잘 설명 할 수있는 사람은 없다고 생각 합니다 .

이 새로운 유형의 컨테이너의 경우 반전은 플러그인 구현을 찾는 방법에 관한 것입니다. 필자의 순진한 예제에서 리스터는 파인더 구현을 직접 인스턴스화하여 검색했습니다. 이렇게하면 파인더가 플러그인이되지 않습니다. 이 컨테이너가 사용하는 접근 방식은 플러그인 사용자가 별도의 어셈블러 모듈이 구현을 리스터에 주입 할 수 있도록하는 일부 규칙을 따르도록하는 것입니다.

위의 단락에서 설명했듯이 이것은 "제어 역전"이라는 용어가 시작된 이유와는 다릅니다.

이 컨테이너들이 "Inversion of Control"을 구현하여 어떻게 유용한 지에 대해 이야기 할 때 나는 매우 당황하게됩니다. 제어 역전은 프레임 워크의 일반적인 특성이므로, 이러한 경량 컨테이너는 제어 역전을 사용하기 때문에 특별하다는 말은 내 차가 바퀴를 가지고 있기 때문에 특별하다고 말하는 것과 같습니다.

문제는 제어의 어떤 측면이 반전 되는가? 처음으로 제어 역전이 발생했을 때 사용자 인터페이스의 주요 제어 상태였습니다. 초기 사용자 인터페이스는 응용 프로그램에 의해 제어되었습니다. "이름 입력", "주소 입력"과 같은 일련의 명령이 있습니다. 프로그램은 프롬프트를 유도하고 각 프롬프트에 대한 응답을 선택합니다. 그래픽 (또는 화면 기반) UI를 사용하면 UI 프레임 워크에이 기본 루프가 포함되며 대신 프로그램이 화면의 다양한 필드에 대한 이벤트 처리기를 제공했습니다. 프로그램의 주요 제어 기능이 반전되어 프레임 워크로 이동했습니다.

그렇기 때문에 그는 이러한 Inversion of Control의 특정 구현을 다루기 위해 "종속성 주입"이라는 용어를 계속 사용합니다.

결과적으로이 패턴에 대해보다 구체적인 이름이 필요하다고 생각합니다. 제어 역전은 너무 일반적인 용어이므로 사람들은 혼동을 느낍니다. 다양한 IoC 옹호자들과 많은 논의를 통해 Dependency Injection이라는 이름을 정했습니다.

간단히 설명하자면 : 제어 반전은 고전적인 절차 설계에서 프로그램의 제어 구조를 반전시키는 모든 것을 의미합니다.

요즈음, 이것의 주요 예는 UI를 직접 생성하도록 코드를 남기지 않고 프레임 워크가 UI와 코드 간의 통신을 처리하게하는 것이 었습니다.

보다 최근에는 (이러한 프레임 워크가 거의 지배적이어서 질문이 더 이상 관련되지 않은 경우), 예는 객체의 인스턴스화에 대한 제어를 뒤집는 것이었다.

Fowler와 다른 사람들은 Inversion of Control이라는 용어가 너무 많은 기술을 다루기로 결정했으며 객체의 인스턴스화 (Dependency Injection)의 특정 예에 대한 새로운 용어가 필요하지만 계약이 성립 된 시점에서 "IoC 컨테이너 "이륙했다.

이것은 IoC 컨테이너가 특정 종류의 의존성 주입이지만, 의존성 주입은 특정 종류의 제어 역전이기 때문에 물을 많이 진흙으로 만듭니다. 이것이 어디에서 보더라도 혼란스런 대답을 얻는 이유입니다.


4
나는 보통 그다지 투표하지 않지만 이것은 큰 대답입니다. 1 표면 충분하지 않습니다. :(
RJD22

1
이 답변은 실제로 IoC 및 DI 혼란의 모든 질문에 대한 답변입니다.
Ali Umair

32

"일반적인"제어 흐름 프로그램은 다음과 같습니다.

  • 순차적으로 명령 실행
  • 프로그램의 제어 흐름을 제어합니다.

제어 반전은 해당 제어 흐름을 "반전"시킵니다.

  • 프로그램은 더 이상 흐름을 제어하지 않습니다. 적합하다고 생각되는 명령을 호출하는 대신 다른 사람이 당신을 호출하기를 기다립니다 .

마지막 줄이 중요합니다. 기분이 좋을 때 다른 사람에게 전화하는 대신 느낌이들 때 다른 사람이 전화를합니다.

이것의 일반적인 예는 Rails와 같은 웹 프레임 워크입니다. 컨트롤러를 정의하지만 실제로 언제 호출되는지는 결정하지 않습니다. 필요하다고 판단되면 Rails에서 전화합니다.


19
[필수 "소비에트"농담을 여기에 삽입]
Robert Harvey

2
제쳐두고, 당신이 생각하는 것은 메시지 전달과 비슷합니다. 수십 년 동안 OO의 필수 요소였습니다.
Robert Harvey

3
@JimmyHoffa – 이것은 전혀 잘못된 것이 아닙니다 . 여기를보십시오 . 제어 반전은 종속성을 만드는 것보다 일반적인 개념이며 종속성 주입은 IoC의 한 형태 일뿐입니다.
Lee

7
@JimmyHoffa : 동의하지 않습니다. 이것은 의존성 주입 (구두 IoC라고 부름)이라는 문구를 만들 때 Fowler가 설명하는 혼란과 정확히 같은 Inversion of Control에 대한 올바른 정의입니다.
pdr

5
나는 @pdr의이 진술에 동의한다 : "제어의 반전은 고전적인 절차 적 설계에서 프로그램의 제어 구조를 뒤집는 것을 의미한다." 그것이 제가 설명하고있는 것이 일반적인 제어 역전입니다. 의존성 주입은 IoC의 한 유형이지만 IoC를 실행하는 유일한 것은 아닙니다
dsw88

13

종속성의 인스턴스화를 제어하는 ​​사람에 관한 것입니다.

전통적으로 클래스 / 메소드가 다른 클래스 (종속성)를 사용해야하는 경우 클래스 / 메소드에 의해 직접 인스턴스화됩니다. 의존성을 제어합니다.

IoC (Inversion of Control)를 사용하면 호출자 가 종속성을 전달하여 종속성을 인스턴스화합니다. 호출자는 종속성을 제어합니다.

종속성이 인스턴스화되는 위치에 대한 제어가 반전되었습니다. 필요한 코드가있는 "하단"에있는 대신 "상단"에 인스턴스화되어 필요한 코드가 호출됩니다.


1
평범한 영어가 아닙니다. 불합격.
Robert Harvey

2
@RobertHarvey-얼마나 평범한가?
Oded

4
@RobertHarvey 허? 이것은 나에게 꽤 평범 해 보인다. "instantiation"또는 "dependencies"라는 단어?
Jimmy Hoffa

@JimmyHoffa : 구체적인 예를 제공하는 대답을 참조하십시오. IoC는 모두가 사용하지만 아무도 설명하지 않는 번거로운 용어 중 하나입니다. 사람들은 오해하기 때문에 IoC 컨테이너를 필요로하지 않는 프로그램에서 IoC 컨테이너를 사용합니다. 즉,이 답변에는 몇 가지 닌자 편집 내용이 있다고 생각합니다. :)
Robert Harvey

이 게시물은 위의 @ dsw88이어야합니다. 내가 IoC에 대해 들어 본 적이 없다면 직관적으로 "아, 누가 제어 할 수있는 곳이 한쪽에서 다른쪽으로"라고 생각합니다. 이것에 잘 했어!
Oliver Williams

2

일반적으로 상위 레벨 코드 호출 (즉, 제어) 하위 레벨 코드. Main ()은 function ()을 호출하고 function ()은 libraryFunction ()을 호출합니다.

반전 될 수 있으므로 맨 아래의 저수준 라이브러리 기능은 고수준 기능을 호출합니다.

왜 그렇게 하시겠습니까? 미들웨어. 때로는 최상위 수준과 하위 수준을 제어하고 싶지만 중간에 원하지 않는 작업이 많이 있습니다. C stdlib에서 quicksort를 구현하십시오 . 최상위 레벨에서 quicksort를 호출합니다. qsort ()는 자신이 원하는대로 비교기를 구현하는 자신의 함수에 대한 함수 포인터를 전달합니다. qsort ()가 호출되면이 비교기 함수를 호출합니다. qsort ()가 고급 기능을 제어 / 호출 / 구동하고 있습니다.


1

간단한 개요는 다음과 같습니다.

  1. 제어는 프로그램이 다음에하는 일을 나타냅니다
  2. 최상위 수준에는 일반적으로 제어를 제어하는 ​​두 가지 항목 인 응용 프로그램 자체와 사용자가 있습니다.

옛날에는 응용 프로그램이 먼저 제어하고 사용자가 두 번째로 제어권을 소유했습니다. 응용 프로그램에서 사용자의 무언가가 필요한 경우 중지하고 요청한 후 다음 작업으로 넘어갑니다. 사용자의 상호 작용은 응용 프로그램이 다음에 수행 한 작업을 제어하지 않고 주로 데이터를 제공했습니다. 우리는 이런 유형의 행동을 자주 보지 못하기 때문에 요즘 우리에게는 조금 이질적입니다.

우리가 그 주위를 전환하고 사용자에게 기본 제어 권한을 부여하면 제어권이 반전됩니다. 즉, 사용자가 응용 프로그램이 할 일을주기를 기다리는 대신 응용 프로그램이 사용자가 할 일을주기를 기다립니다. GUI는 이것의 좋은 예이며 이벤트 루프가있는 거의 모든 것이 제어를 거꾸로했습니다.

내 예제는 최상위 수준에 있으며이 제어 역전 개념은 응용 프로그램 내에서 다른 제어 계층 (예 : 종속성 주입)으로 추상화 될 수 있습니다. 이것이 바로 정답을 얻는 것이 어려운 이유 일 수 있습니다.


0

두 가지 예를 통해 이해하려고 노력하겠습니다.

실시 예 1

이전에는 앱이 사용자 입력을 하나씩 받아들이도록 명령 프롬프트를 생성하는 데 사용되었습니다. 오늘날 UI 프레임 워크는 다양한 UI 요소를 인스턴스화하고 해당 마우스 요소 (마우스 호버, 클릭 등)의 다양한 이벤트를 반복하며 사용자 / 주 프로그램은 이러한 이벤트를 청취하기위한 후크 (예 : Java의 UI 이벤트 리스너)를 제공합니다. 따라서 기본 UI 요소 흐름 "제어"는 사용자 프로그램에서 UI 프레임 워크로 이동합니다. 초기에는 사용자 프로그램에있었습니다.

실시 예 2

CustomerProcessor아래 수업을 고려하십시오 .

class CustomerProcessor
{
    SqlCustRepo custRepo = new SqlCustRepo(); 
    private void processCustomers()
    {
            Customers[] custs = custRepo.getAllCusts();
    }
}

에서 제공하는 것뿐만 아니라의 processCustomer()구현과 독립적으로 하고 싶다면 줄을 제거해야합니다. 다양한 유형의 구현을 받아 들일 수있는보다 일반적인 것으로 대체해야 합니다. 제공된 구현. 위의 코드 ( 주 프로그램 논리에 의해 필요한 클래스 를 나타냄)는 전통적인 방법이며의 구현에서 분리의 목표를 달성하지 못합니다 . 제어의 역전에서 컨테이너는 필요한 구현 클래스 (xml 구성으로 지정된대로)를 인스턴스화하고 지정된 후크마다 (예 : 스프링 프레임 워크의 주석 또는 메소드로) 바인딩되는 기본 프로그램 논리에 삽입합니다 .getAllCusts()SqlCustRepoSqlCustRepo custRepo = new SqlCustRepo()processCustomers()SqlCustRepoprocessCustomers()getAllCusts()@AutowiredgetBean()

이것이 어떻게 이루어질 수 있는지 봅시다. 아래 코드를 고려하십시오.

Config.xml

<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
    <bean id="custRepo" class="JsonCustRepo" />
</beans>

CustRepo.java

interface ICustRepo 
{ ... }

JsonCustRepo.java

class JsonCustRepo implements CustRepo
{ ... }

App.java

class App
{
    public static void main(String[] args) 
    {
        ApplicationContext context = new ClassPathXmlApplicationContext("Config.xml");
        ICustRepo custRepo = (JsonCustRepo) context.getBean("custRepo");
    }
}

우리는 또한 가질 수 있습니다

class GraphCustRepo implements ICustRepo { ... }   

<bean id="custRepo" class="GraphCustRepo">

App.java를 변경할 필요가 없습니다.

컨테이너 (스프링 프레임 워크) 위에 xml 파일을 스캔하고 특정 유형의 Bean을 인스턴스화하고 사용자 프로그램에 삽입해야 할 책임이 있습니다. 사용자 프로그램은 어떤 클래스가 인스턴스화되는지 제어 할 수 없습니다.

추신 : IoC는 일반적인 개념이며 여러 가지 방법으로 달성됩니다. 위의 예는 의존성 주입으로 달성합니다.

참조 : Martin Fowler의 기사 .

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