소매 게임은“제어의 반전”과“의존성 주입”을 사용합니까?


30

내가 아는 많은 부지런한 소프트웨어 개발자들은 개체에 대한 참조를 처리하기 위해 제어종속성 주입의 반전으로 이동 하고 있습니다. 플래시 게임의 관점에서봤을 때 AAA 스튜디오의 모든 기능을 알지 못하므로 소매 게임 세계에서 사용됩니까?


나는 그 세계 성능이 무엇보다 중요하다고 생각합니다. 더 많은 사용자가 나쁜 코드에 의해 프로그래머보다 성능이 낮을 것입니다.
바트 반 Heukelom

의존성 주입은 컴포넌트 기반 시스템처럼 들리지만 제어 반전을 해제하는 방법에 대한 예가 있습니까?
ADB

이 스레드의 대부분은 IoC가 무엇인지, 무엇이 해결되는지에 대해 잘못 알고있는 것처럼 보이며 OP는 실제로 미래의 방문자를 위해 여기에서 지적 할 것입니다 : sebaslab.com/ioc-container-unity-part-1
보리스 칼 렌스

예, 그렇습니다. 실제로 Rare는 Sea of ​​Thieves ( youtube.com/watch?v=KmaGxprTUfI&t=1s) 에서 테스트를 구현하는 방법에 대해 이야기했습니다 . 불행히도 언리얼 엔진의 Inversion of Control에 대해 말할 것도 많지 않았지만 작동 방식을 보여주는 프로젝트를 작성했습니다 : github.com/jimmyt1988/UE-Testing
Jimmyt1988

답변:


45

당신은 그것을 '부지런한 소프트웨어 개발'이라고 부릅니다. 제어의 역전이 나쁘다는 것은 아닙니다. 사실, 기본 정의는 훌륭합니다. 그러나 모든 것을 달성하기 위해 노력하는 전체 프레임 워크와 방법의 확산은 특히 사람들이 쓰레기를 버리는 방식과 결합되어 미쳤습니다. 상호 교환이 불가능한 99 %의 교체 가능한 구성 요소를 주입 할 수 있도록 완벽하고 깔끔한 인터페이스. 그것은 Java 엔터프라이즈 환경에서만 시작될 수있는 종류의 일이며 다른 곳에서 발판이 많지 않아서 기쁩니다.

구성 요소를 서로 바꾸지 않더라도 모의 객체 등과 분리하여 테스트 할 수 있기를 원한다는 주장이 종종 있습니다. 그러나 나는 그것을 더 잘 테스트하기 위해 팽만감과 인터페이스를 복잡하게 할 가치가 있다는 주장을 결코 사지 않을 것이라고 두려워한다. 테스트는 한 가지만 증명합니다. 테스트가 작동한다는 것입니다. 반면에 깨끗하고 최소한의 인터페이스는 코드 작동 을 입증 하는 데 먼 길을갑니다 .

그래서 짧은 대답 : 예, 그러나 당신이 생각하는 방식이 아닙니다. 때때로, 상호 교환 가능한 행동이 필요할 때, 새로운 객체의 행동의 일부를 지시하는 생성자에게 객체를 전달할 수 있습니다. 그게 다야.


5
+1-Java 커뮤니티가 매우 간단한 아이디어로 보이는 것을 지나치게 복잡하게 만든 것 같습니다.
Chris Howe

4
아이디어는 프로덕션 환경에서 서로 다른 구현을 교체해야 할 필요는 없지만 자동화 된 테스트를 용이하게하기 위해 특별한 구현을 주입 할 수 있습니다. 그런 점에서 DI / IoC는 게임에서 확실히 유용 할 수 있지만, 합리적으로 범위를 유지하고자합니다. 높은 수준에서 몇 번의 일회성 서비스 해상도가 필요하지 않아야합니다. 게임의 모든 작은 개체에 대한 서비스를 해결하고 싶지는 않으며, 모든 프레임이나 그와 같은 것은 아닙니다.
Mike Strobel

2
@Thomas Dufour : 테스트의 개념은 아무 것도 증명할 수 없습니다. 데이터 포인트 일뿐입니다. 100001 실행시 테스트 통과없이 100000 회 테스트를 통과 할 수 있습니다. 증거는 주제의 논리적 분석에서 비롯됩니다. 나는 이러한 IoC 컨테이너 등이 정확성을 증명하기 어렵게하여 테스트를 더 쉽게 만든다고 주장하며 이는 나쁜 일이라고 생각합니다.
Kylotan

13
@Kylotan 테스트 개념은 아무것도 증명 하지 않습니다 . 주어진 입력에 대한 동작이 예상대로 작동 함을 보여줍니다. 동작이 정확할수록 전체 기능은 정확하지만 100 %는 아니라는 믿음이 커집니다. 최소한의 인터페이스가 무언가를 증명한다는 진술은 어리 석습니다.
dash-tom-bang

5
@Alex Schearer : 공식화 된 IoC 컨테이너 시스템을 사용해야하고 일반적으로 테스트를 용이하게하기 위해 추가 생성자 인수 또는 팩토리 클래스를 생성해야한다는 점이 어떤 식 으로든 코드를 더 잘 팩토링하고 확실하게 만들지 않을까 걱정됩니다 느슨하게 결합되었습니다. 실제로 OOP의 주요 측면 인 캡슐화에 많은 영향을 미칩니다. 설계를 추진하기 위해 TDD에 의존하고 좋은 결과가 나오기를 희망하는 대신, 사람들은 우선 SOLID 원칙을 따를 수 있습니다.
Kylotan

17

전략 패턴 , 구성 , 의존성 주입 은 모두 매우 밀접한 관련이 있습니다.

전략 패턴은 Dependency Injection의 한 형태이므로 Unity와 같은 엔진을 살펴보면이 원칙을 완전히 기반으로합니다. 구성 요소 (전략 패턴) 사용은 전체 엔진에 깊이 포함되어 있습니다.

구성 요소 재사용을 제외하고 주요 이점 중 하나는 끔찍한 딥 클래스 계층 구조를 피하는 것입니다.

Mick West 의 기사는 Neversoft 의 Tony Hawk 시리즈 게임에 이러한 유형의 시스템을 어떻게 도입했는지에 대해 설명합니다 .

계층을 발전 시키십시오

상당히 최근까지 게임 프로그래머는 게임 개체를 나타 내기 위해 지속적으로 딥 클래스 계층 구조를 사용했습니다. 조류는 이러한 딥 계층 구조의 사용에서 구성 요소의 집합으로 게임 개체 개체를 구성하는 다양한 방법으로 전환하기 시작했습니다 ...


2
+1, Evolve Your Hierarchy는 내가 완전히 잊어 버린 훌륭한 링크입니다. Scott Bilas 슬라이드도 좋습니다. 올바른 링크는 ( scottbilas.com/files/2002/gdc_san_jose/game_objects_slides.pdf )입니다. 관련 슬라이드 세트가 하나 더 있지만 어디에서 잊어
버렸는가

Bjarne Rene의 Games Gems 5 (내 생각에)에있는 기사도 있습니다.
Chris Howe

13

IoC (Inversion of Control) 패턴에 대해 많은 혼동이있는 것 같습니다. 많은 사람들이 전략 패턴이나 구성 요소 모델을 사용했지만이를 비교한다고해서 실제로 IoC가 무엇인지 파악할 수는 없습니다. IoC는 실제로 의존성을 얻는 방법에 관한 것입니다. 예를 들어 보겠습니다.

class Game {
    void Load() {
        this.Sprite.Load(); // loads resource for drawing later
    }
}

class Sprite {
    void Load() {
        FileReader reader = new FileReader("path/to/resource.gif");
        // load image from file
    }
}

위에서 Sprite.Load는에 의존하는 것이 분명합니다 FileReader. 분석법을 테스트하려면 다음이 필요합니다.

  1. 적절한 파일 시스템
  2. 파일 시스템에서로드 할 테스트 파일
  3. 일반적인 파일 시스템 오류를 트리거하는 기능

처음 두 개는 분명하지만 오류 처리가 예상대로 작동하도록하려면 실제로 # 3도 필요합니다. 두 경우 모두 이제 디스크로 이동해야하기 때문에 테스트 속도가 상당히 느려졌으며 테스트 환경이 더 복잡해졌습니다.

IoC의 목표는 동작 사용을 구성에서 분리하는 것입니다. 이것이 전략 패턴과 어떻게 다른지 주목하십시오. 전략 패턴의 목표는 재사용 가능한 행동 덩어리를 캡슐화하여 나중에 쉽게 확장 할 수 있도록하는 것입니다. 전략이 어떻게 구성되는지에 대해서는 말할 것도 없습니다.

Sprite.Load위 의 방법 을 다시 작성하면 다음과 같이 끝날 것입니다.

class Sprite {
    void Load(IReader reader) {
        // load image through reader
    }
}

이제 독자의 구성을 사용에서 분리했습니다. 따라서 테스트 중에 테스트 리더를 교체 할 수 있습니다. 이는 테스트 환경에 더 이상 파일 시스템, 테스트 파일이 필요하지 않으며 오류 이벤트를 쉽게 시뮬레이션 할 수 있음을 의미합니다.

다시 쓰기에서 두 가지 작업을 수행했습니다. IReader전략을 구현 하는 인터페이스 를 만들었습니다. 즉, 전략 패턴을 구현했습니다. 또한 올바른 독자를 만드는 책임을 다른 수업으로 옮겼습니다.

위의 내용을 설명하기 위해 새로운 패턴 이름이 필요하지 않을 수도 있습니다. 전략과 팩토리 패턴 (IoC 컨테이너의 경우)이 혼합되어 있습니다. 즉, 실제 문제를 해결한다는 것이 확실하기 때문에 사람들 이이 패턴에 반대하는 근거가 무엇인지 확실하지 않으며 확실히 Java와 관련이 있는지 분명하지 않습니다.


2
Alex : 아무도 이미 생성 된 객체를 전달하여 필요한 경우 사용자 정의 기능을 추진하는 것에 반대하지 않습니다. 여러분의 모범 에서처럼 모두가 그렇게합니다. 문제는 사람들이 순전히 존재하는 전체 프레임 워크를 사용 하여이 물건을 처리 하고이 기능에 의존하도록 기능의 모든 측면을 종교적으로 코딩하는 곳입니다. 먼저 Sprite 구성에 매개 변수로 IReader를 추가 한 다음이를 촉진하기 위해 특수 SpriteWithFileReaderFactory 객체가 필요하게됩니다. 이러한 태도는 Java 및 Spring IoC 컨테이너 등과 같은 항목에서 비롯됩니다.
Kylotan

2
그러나 우리는 IoC 컨테이너에 대해 이야기하고 있지 않습니다. 적어도 원래 게시물에서는 볼 수 없습니다. 우리는 패턴 자체에 대해서만 이야기하고 있습니다. 내가 알 수 있듯이 당신은 "야생 도구는 나쁘기 때문에 기본 개념을 사용해서는 안된다"고 주장합니다. 그것은 목욕물로 아기를 쫓아내는 것으로 저를 때립니다. 단순성, 작업 완료 및 유지 관리 성 / 테스트 가능성 사이의 적절한 균형을 맞추는 것은 프로젝트별로 프로젝트에서 가장 잘 처리되는 어려운 문제입니다.
Alex Schearer

나는 많은 사람들이 IoC를 반대한다고 생각한다. 왜냐하면
phtrivier

4

나는 그것이 많은 도구 중 하나라고 말하고 때로는 사용됩니다. tenpn이 말했듯이 vtable을 도입하는 모든 메소드 (및 일반적으로 추가 간접 처리)는 성능 저하가 발생할 수 있지만 이는 저수준 코드에 대해서만 걱정해야 할 사항입니다. 실제로 문제가되지 않는 고급 구조 코드의 경우 IoC는 긍정적 인 이점을 가질 수 있습니다. 클래스 간의 종속성을 줄이고 코드를 더 유연하게 만드는 것.


2
정확히 말하면 한 프레임에 여러 번 호출되는 모든 코드에 대한 vtable 처벌에 대해 걱정할 것입니다. 낮은 수준 일 수도 있고 아닐 수도 있습니다.
tenpn

4

Kylotan에 동의해야합니다. "종속성 주입 (dependency injection)"은 못생긴 Java 개념 결함에 대한 못생긴 Java 솔루션이며, 다른 언어로 다른 사람이 그것을보고있는 유일한 이유는 Java가 실제로는 말아야 할 때 많은 사람들에게 첫 언어가되기 때문 입니다.

반면에 제어 반전은 오랫동안 사용되어 왔으며 올바르게 수행하면 매우 유용합니다. (Java / Dependency Injection 방식은 아닙니다.) 사실, 제정신의 프로그래밍 언어로 작업한다면 항상 그렇게 할 것입니다. 모두가 윙윙 거리는이 "IOC"전체를 처음 읽었을 때, 나는 완전히 압도당했습니다. Inversion of Control은 그 동작을 커스터마이즈하기 위해 함수 포인터 (또는 메소드 포인터)를 루틴이나 객체에 전달하는 것 이상입니다.

이것은 1950 년대부터 존재 해 온 아이디어입니다. C 표준 라이브러리 (qsort가 떠오를 것입니다)에 있으며 Delphi 및 .NET (이벤트 핸들러 / 대의원) 의 모든 곳에 있습니다. 이전 코드는 기존 코드를 다시 컴파일 할 필요없이 새 코드를 호출 할 수있게 해주 며 게임 엔진에서 항상 사용됩니다.


2
나는 또한 있었다의 "그래서 사람에 대해 흥분 무엇입니까?" DI에 대해 읽을 때 대부분의 게임 프로그래머는 DI에 대해 배우고 그것이 우리의 작업에 어떻게 적용되는지에 대해 설 수 있습니다.
dash-tom-bang

2

내 경험이 아닙니다. 게임 코드는 매우 적응력이 뛰어나야하며 이러한 접근 방식이 도움이 될 수 있으므로 부끄러운 일입니다.

그러나 C ++에서 두 방법 모두 이전에 없었던 가상 테이블을 도입하여 적절한 성능 저하를 가져올 수 있다고 말해야합니다.


1

나는 전문 게임 개발자가 아니며 C ++에서 IoC를 한 번만 구현하려고 시도했기 때문에 추측하고 있습니다.

그러나 나는 게임 개발자가 다음을 의미하기 때문에 IoC에 대해 의심 스러울 것이라고 생각합니다.

1 / 많은 인터페이스와 많은 작은 클래스 디자인

2 / 거의 모든 함수 호출이 최근에 바인딩됩니다.

이제 우연의 일치 일지 모르지만 둘 다 IoC가 널리 보급 된 Java보다 C + + (게임에서 널리 사용되지는 않습니까?)의 성능에 대해 조금 더 복잡하거나 문제가되는 경향이 있습니다. 비교적 쉬운 작업을 수행하여 사람들이 더 안전한 객체 계층 구조를 설계하도록 돕고 일부는 Java로 응용 프로그램을 작성하여 XML로 응용 프로그램을 작성할 수 있다고 믿었 기 때문에 또 다른 논쟁입니다 : P)

의견이 전혀 이해가되지 않으면 의견에 관심이 있습니다.)

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