TAF 다이어그램

지난 번 포스팅에서 사용된 비행기 게임을 이용해 계속 진행하겠습니다. 이전 포스트를 보지 못하신 분들은 먼저 아래 포스트를 보시면 더욱 도움이 되실 거라 생각합니다.

TAF로 프로그래밍하기

간단히 생각해보기

TAF로 개발하려면 복잡한 OOP패러다임을 전부 버리는 것부터 출발합니다. 이게 또 OOP에 익숙해지면 또 다른 어려움이 될 수 있겠습니다만, 아직 OOP자체가 어려운 개발자들에겐 편안한 일입니다. 비행기 게임을 아주 기본적으로 생각해보면 다음과 같은 순서로 진행되는 것을 알 수 있습니다.

Continue reading ‘TAF 다이어그램’ »

Developer Book review 10.06.28

IMG_8173

어쩌다보니 아이폰 아이패드 개발을 하게 될지도 모르겠습니다.

원래 아이폰 관련 하여 가진 책이 2권 밖에 안되어서 두 권정도 더 영풍에서 업어왔습니다.

iPhone Advanced Projects

약간 식상한 감은 있지만 부분별로 참고가 될만한 내용이 있습니다. Advanced까지는 아니지만 나름 쿼츠 이상을 다루는 부분도 있더라는 정도로 만족

OpenGL ES 2.0 프로그래밍 가이드

사실 저희 회사는 아예 쿼츠와 코코아베이스로 개발할 생각이 없습니다. 기저 윈도우만 만들고 노티피 중계 클래스만 하나 둔 상태에서 전부 ESrender만 만질 생각이죠.

따라서 아이폰 책은 그닥 흥미도 쓸모도 크게 없긴 합니다. 원래 가진 짱 두꺼운 sams의 openGL책에서는 ES를 다루는 부분이 작아서 한 권 더 마련했습니다.

TAF로 프로그래밍하기

일단 TAF를 완성하긴 했습니다. 이제 남은 건 API개선과 기능 고도화 뿐입니다.
하지만 Tree와 Flow로 개발한다는 의미부터 정립하고 가야 TAF가 쓸모 있을 것 같아 입문자를 위한 튜토리얼을 만들어 보기로 했습니다.

현재 사내에서는 ‘역할모델에 기반한 OOP프로그래밍’ 또는 ‘흐름제어에 중심을 두는 구조적 함수 프로그래밍’ 모델만 사용합니다. 첫번째 모델은 복잡한 어플리케이션을 작성할 때 사용하는 방법론이고 두번째는 배너나 단순한 작업을 진행할 때 사용합니다. 하지만 TAF의 개발방법론은 전혀 다른 스타일입니다. 그래서 하나의 예를 들어 TAF스타일로 어떻게 달라지는 지 연습해보겠습니다.

Continue reading ‘TAF로 프로그래밍하기’ »

class정의 시 순환참조 오류 #2

class 정의 시의 순환참조 오류란?

class 정의 구문을 이용하여 하나의 클래스를 정의할 때 만약 그 정의 내부에서 해당 클래스를 참조한다면 닭이 먼저냐 알이 먼저냐의 문제에 봉착하여 클래스 정의가 실패하는 현상입니다. 말로 하면 어려우니 코드로 보겠습니다.

class Test{

	private var instance:Test = new Test;

	public function Test(){}

}

위의 코드를 보시면 Test라는 클래스가 정의되려면 instance에 기본값으로 Test의 인스턴스를 할당한다라는 행위가 성립되어야 합니다. 하지만 아직 Test라는 클래스가 정의되지 않았으므로 인스턴스를 할당할 수 없고 인스턴스를 할당한다는 행위를 성공시킬 수 없으니 Test라는 클래스는 정의될 수 없습니다. 그야말로 닭이 먼저냐 알이 먼저냐의 상황입니다. 이러한 경우 해답은 외부에서 instance를 초기화해야 한다는 것입니다. 즉 아래와 같이 바꿔도 여전히 동일한 문제가 됩니다.

class Test{

	private var instance:Test;

	public function Test(){}

	public function init():void{
		instance = new Test;
	}
}

왜냐면 Test 클래스가 성립하려면 반드시 init를 파싱하는데 성공해야하는데 init를 파싱하려면 instance = new Test를 파싱할 수 있어야 하고 저걸 파싱하려면 Test의 정의가 로드 되어 있어야 하기 때문입니다. 따라서 유일한 해답은 instance의 할당을 외부에서 하는 것 밖에 없습니다.

class Test{

	public var instance:Test;

	public function Test(){}

}

var t:Test = new Test;

//외부에서 할당한다.
t.instance = new Test;

해서 간단히 말해 클래스 내부에서 자기 자신을 new 하려는 행위를 하면 순환참조 오류에 빠지게 된다는 것입니다. class 정의 시 일어나는 순환참조 오류는 사실 매우 어려운 오류입니다. 처음 당하시는 분은 당췌 이게 왜 발생한 건지 이해하는데도 오래 걸립니다. 클래스 정의 순환참조가 어려운 이유를 간단히 정리해볼까요.

1. 일단 컴파일에러가 아닌 런타임 에러로 발생합니다. 특히 아래와 같은 생소한 메세지를 받게 됩니다.

Error: Error #2136: SWF 파일 file:///Main.swf 에 유효하지 않은 데이터가 포함되어 있습니다.
at Test()[F:Test.as:23]

2. 따라서 순환참조라는 관점을 갖지 않고 그 코드를 쳐다봐도 전혀 알 수 없고 유효하지 않은 데이터라는 에러 메세지도 의미를 알 수 없습니다.

3. 결국 위에 설명한대로 해결 방법은 설계를 바꾸는 것만이 유일한 해결책인데 스스로를 초기화해야 할 경우도 있긴 합니다.

Vector와 순환참조

Vector의 경우 Vector.<type>을 통해 순환참조 가능성을 볼 수 있습니다. 즉 아래와 같은 경우입니다.

class Test{

private var tests:Vector.<Test> = new Vector.<Test>();

public function Test(){}

}

하지만 이 경우엔 문제없이 잘 굴러갑니다. 왜냐면 Vector는 new 되는 시점에는 Test를 생성하지 않기 때문이죠.

static을 이용한 순환참조 해소

static을 사용해도 class의 정의 내에서 해당 static 함수를 호출하는 이상 안에 new가 있어서는 안됩니다. 즉 아래와 같이 해도 동일하게 에러상황입니다.

class Test{

	static public function init( test:Test ):void{
		test.instance = new Test;
	}

	private var instance:Test;

	public function Test(){
		init();
	}
}

왜냐면 init를 호출하여 new Test가 일어나는 과정이 Test의 정의 시 일어나 순환참조에 빠지기 때문이죠. 그렇다고 static으로 빠진 init함수가 의미가 없는건 아닙니다. 만약 생성자에서 init()를 호출하지만 않는다면 정상적으로 컴파일 됩니다. static의 경우 해당 클래스의 인스턴스에 있는 private에도 전부 접근이 가능합니다. 따라서 클래스가 구지 자신의 private를 노출하는  세터함수를 제공하지 않아도 됩니다. 즉 static을 사용하지 않는 경우 instance를 설정하게 하는 방법은 아래와 같은 세터입니다.

class Test{

	private var instance:Test;

	public function setInstance( $t:Test ):void{
		instance = $t;
	}

	public function Test(){}

}

하지만 이 경우 반드시 Test의 인스턴스를 받아와야합니다. 즉 아래와 같은 호스트 코드가 됩니다.

var t:Test = new Test;
t.setInstance( new Test ); //호스트에서 new를 해서 넘겨준다.

하지만 static은 내부에서 new를 정의할 수 있으니까 상관없습니다.

class Test{

	static public function setInstance( $t:Test ):void{
		$t.instance = new Test;
	}

	private var instance:Test;

	public function setInstance( $t:Test ):void{
		instance = $t;
	}

	public function Test(){}
}

var t:Test = new Test;
Test.setInstance( t );

as3의 봉인된 클래스의 구조가 Tca를 따로 잡아주는걸 생각해보면 static구문 안에는 왜 new를 이용한 자기 자신 생성이 허용되는지 쉽게 이해할 수 있습니다.

결론

클래스 순환참조 정의는 설계를 복잡하게 해야 하는 큰 어플리케이션에서 종종 만나볼 수 있는 문제입니다. 정말 이해할 수 없는 에러가 나오거나 분명히 컴파일 에러가 없는데 해당 클래스의 정의를 찾을 수 없습니다 따위의 에러를 만나시면 이 문제를 한 번쯤 떠오실 필요가 있을지 모릅니다.

Stage의 Activate와 Focus의 관계

알 것도 같지만 정확하게 알지 못하면 사용할 수 없는 게 바로 프로그래밍인 듯 합니다. 저는 얼마 전까지 Stage의 focus에 대한 이해가 생각보다 얕았다는 것을 알아차리고 몇 가지 실험을 통해 확실하게 이해했습니다. 간단히 정리하고 공유해 봅니다.

Activate, Deactivate Event

이 두 개의 이벤트는 Stage를 통해 청취할 수 있는 이벤트이긴 합니다만, 정확한 의미를 생각해보면 Player라는 눈에 보이지 않는 전역객체에게 걸어야 마땅한 속성입니다.

애시당초 Stage가 중의적인 의미를 담고 있는 객체이긴 합니다. Stage는 다음과 같은 역할을 대변합니다.

  • 플래시플레이어가 최초 swf를 로딩하여 화면에 표시할 때 가장 기저에 깔리는 화면베이스객체
  • 플래시플레이어 자체를 대변하는 객체

보통 처음 의미만 생각하지만 두 번째도 매우 중요합니다(대표적으로 Activate와 Deactivate가 그렇습니다^^)

Continue reading ‘Stage의 Activate와 Focus의 관계’ »