Eric's Complete Guide To Type Signatures Of Scriptable Object Models
: 이 글은 마지막에 링크된 주소의 글을 번역한 것이다. 번역이 미숙하더라도 이해바람.
내가 수년 동안 받은 많은 질문들에 대해서 소개한다.
"VBScript 와 JScript 둘 다에서 쉽게 호출될 수 있도록 하기 위해서는 어떻게 객체를 디자인 하는가?"
COM 은 매우 복잡한 타입 시스템을 정의하고 스크립트 엔진은 그 타입 시스템의 하위 집합만을 지원한다. C++ 에서 쉽게 호출될 수 있는 객체를 생성하는 것은 가능하지만 VB6, VBScript, 그리고 특별히 JScript 와 같은 다른 언어에서 쉽게 호출되지 않을 수 있다.
나는 여러번 개인적인 이슈에 대하여 블로그에 글을 올렸다; 지난달에 그에 관해 설명하는 문서를 요청 받았다. 뒤에 좀더 자세한 설명을 위한 메인 기사에 관한 링크를 제공할 것이다.
이것은 기본적으로 "해야할 것 들"에 대해서가 아니라 "하지 말아야 하는 것"에 대한 목록이다. 또한 직관적이고, 발견될 수 있는, 테스트 가능한, 문서화할 수 있는, 확장할 수 있는, 등등의 객체 모델을 디자인 하는 것에 관해 언급해야 할 것들이 굉장히 많이 더 존재한 다는 것을 기억하라. 언젠가 그것에 관해 이야기 할지도 모르지만, 오늘은 메소드 타입 원형의 구현자(the implementor of method type signatures) 가 반드시 피해야 하는 매우 기초적인 질문에 관해서만 언급할 것이다.
Numeric types
VBScript 는 VT_I2(short signed integer), VT_I4(long signed integer), VT_R4(single float), VT_R8(double float), VT_CY(currency), 그리고 VT_UI1(unsigned bye) 데이터에 대한 산술연산을 할 수 있다. 8-바이트 정수, unsigned integers, signed bytes 그리고 fixed-point decimals 는 지원되지 않는다.
대조적으로, Jscript 는 bytes, shorts, singles, currencies 그리고 unsigned integers 를 즉시 VT_I4 또는 VT_R8 중 하나로 (알맞은 것으로) 즉시 변환한다, 그리고 그것들을 가지고 연산을 수행한다.
일반적으로, 스크립트 엔진이 비록 특정 타입에 대한 연산을 지원하지 않더라고, 여전히 그 값을 저장하고 그것을 파라미터로 전달할 수 있다. (?: you can still store the value and pass it around.) 한 객체에서 VT_DECIMAL 값을 얻기 위한 “접착제(glue)”로서 스크립트를 사용할 수 있고 그것을 다른 객체에 전달한다.
만약 당신의 객체 모델이 fixed-point decimals(VT_DECIMAL)을 사용한다면, 스크립트에서 객체를 사용하는 것은 어려울 것이다. 거의 모든 floating point 산술 연산은 에러가 생긴다는 것을 기억하라. 당신의 객체 모델이 currencies 의 의존적이라면 Jscript 는 원하는 목적을 실패하게끔 할 수 있다. 원칙적으로는, double 과 long 만 지원한다.
좀더 많은 정보를 위해서는 아래 링크를 보라.
http://blogs.msdn.com/ericlippert/archive/2003/09/15/53000.aspx
Dates
VBScript 와 Jscript 는 날짜를 다룸에 있어 완전히 다른 코드를 사용한다. 두 시스템은 “좋았어(gotchas)”로 가득하다. 코드가 COM 에서 사용되는 표준 VT_DATE를 사용하여 date를 조작한다면, Jscript 는 그것들을 자동적으로 내부 date 포맷으로 변환할 것이다. 일반적으로 그것을 다루는 방법이 있긴 하지만, 그 코드는 약간 트릭키 할 수 있다.
자세한 정보는 아래를 보라.
http://blogs.msdn.com/ericlippert/archive/2003/09/16/53013.aspx
http://blogs.msdn.com/ericlippert/archive/2003/10/06/53150.aspx
Object Types
IDispatch 가 아닌 인터페이스를 노출하는 객체는 VBScript 나 Jscript 에서 사용될 수 없다. VT_UNKNOWN 을 넘긴다면, 즉시 그것을 VT_DISPATCH 로 변환하려고 시도한다. Scriptable 객체 모델은 전적으로 dispatchable 해야 한다.
비-디폴트(non-default) 디스패치 인터페이스는 나쁘다. Jscript 는 비-디폴트 디스패치를 지원하지 않는다. VBScript 는 하나가 주어진다면 비-디폴트 디스패치를 사용하긴 하지만, 디폴트 디스패치로부터 디스패치를 얻기 위한 어떠한 방법도 제공하지 않는다. 다중으로 분리된 디스패치 인터페이스를 지원하는 객체를 작성하지 말라.
자세한 정보는 아래를 보라.
http://blogs.msdn.com/ericlippert/archive/2003/10/10/53188.aspx
빠뜨린 인자, 빠뜨린 정보
VBScript 는 빠뜨린 인자를 지원한다. 메소드를 아래와 같이 호출 할 수 있다.
x = foo.bar(123, , 456)
그러면 VBScript 는 PARAMNOTFOUND 가 설정된 에러 필드를 가진 파라미터 VT_ERROR 를 넘길것이다. 그러고 나서는 Callee 가 그 문제를 다루는 책임이 있고, 그 인자를 알맞은 디폴트 값으로 채운다.
Jscript 는 빠뜨린 인자를 지원하지 않는다. 12개의 인자를 가지고 그들 중 일부는 빠뜨릴 수 있다고 예상하는 객체 모델은 Jscript 에서는 사용하기가 어렵다. (그리고 그들은 아마도 매우 나쁘게 설계된 메소드이다.)
Jscript 와 VBScript 모두 이름지어진 인수(named arguments)를 지원하지 않는다.
빠뜨린 인자를 전달하는 일반적인 대안은 VBScript 에서는 Nothing, Null, 또는 Empty 를 넘기는 것이고, Jscript 에서는 null 또는 undefined 를 넘기는 것이다. Null 과 null 은 VT_NULL 을 전달하고, Empty 와 undefined 는 VT_EMPTY 를 전달한다, 그리고 Nothing 은 디스패치 객체 포인터 값이 없는 VT_DISPATCH 를 전달한다. Jscript 에서 “null” 객체를 전달하는 쉬운 방법은 없다. 이것은 Jscript 의 디자인 결함이라고 생각한다, 하지만 우리는 현재 그것에서 벗어날 수 없다. 좋은 Scriptable 객체 모델의 설계자는 Jscript 에서 사용하는 것을 쉽게 하기 위해 Null 과 Nothing 을 동일하게 다루는 것을 고려할 수도 있다.
또 다른 관련 이슈는 “empty/null 문자열” 문제이다. C에서, 빈 문자열과 널 문자열은 다르게 처리된다. VB6, VBScript, 그리고 Jscript 는 그렇지 않다. 널 문자열과 빈 문자열은 동일하다는 규약을 사용한다. 하지만 VB는 이 규약을 사용하지 않는 Win32 API 를 호춣랄 수 있다, 그래서 VB6 과 VBScript 는 실행시에 빈 문자열 또는 널 문자열을 넘기는 것을 허용한다. Jscript 는 이 기능을 가지고 있지 않다.
널과 빈 문자열을 구분하는 Dispatchable COM 객체 모델은 거의 확실히 버그가 있다. 그렇게 하지 마라.
자세한 정보는 아래를 보라.
http://blogs.msdn.com/ericlippert/archive/2003/09/12/52976.aspx
http://blogs.msdn.com/ericlippert/archive/2003/09/30/53120.aspx
http://blogs.msdn.com/ericlippert/archive/2003/10/01/53128.aspx
More On Parameter Passing
“Out” 파라미터는 나쁘다. – 스크립트가능한 객체 모델에서는 out 파라미터를 가지는 메소드는 작성하지 마라. Jscript 는 out 파라미터를 전혀 지원하지 않는다. VBScript 경우에도 메모리 릭이 일어나는 시나리오가 있을 수 있다.
“In-out” 파라미터 역시 나쁘다.” – Jscript 는 in-out 파라미터를 전혀 지원하지 않는다. VBScript 는 항상 VT_VARIANT | VT_BYREF 를 넘긴다, 그리고 IDispatch::Invok 의 디폴트 구현은 만일 메소드가 hard-typed byref 파라미터를 예상하고 있다면 타입 불일치(type mismatch)를 일으킬 것이다. 고유한 강제적인 로직을 작성하거나 인자를 variant 로 만들수 있지만, 둘 다 트릭키 하다. 전적츠로 그것을 피하는 가장 좋은 방법은 – out 또는 in-out 파라미터를 사용하지 않는 것이다.
“Out-retval” 값은 사실상 파라미터가 아니다 – 그것은 반환값이다 – 그래서 out-retval 은 괜찮다.
자세한 정보는 아래를 보라.
http://blogs.msdn.com/ericlippert/archive/2003/09/15/52996.aspx
http://blogs.msdn.com/ericlippert/archive/2003/09/15/53005.aspx
http://blogs.msdn.com/ericlippert/archive/2003/09/15/53006.aspx
http://blogs.msdn.com/ericlippert/archive/2003/09/29/53117.aspx
Arrays
배열은 나쁘다. Jscript 는 VB-스타일의 배열에 대해 매우 빈약하게 지원한다. 다차원 vb스타일 배열은 Jscript 에서 처리하기가 특히 어렵다. 파라미터로 배열을 가지는 객체 모델을 작성하지 않으려고 노력하거나 배열을 반환하기만 하는 객체 모델을 작성하라. (이것은 큰 배열을 복사하는데 드는 성능 비용을 피할 수 잇기 때문에 역시 좋은 생각이다.)
VB6 는 foo(10 to 20, 4 to 6) 과 같은 임의의 인덱스 범위를 가진 배열을 생성할 수 있다. VBScript 는 그러한 배열을 사용할 수는 있지만 그것들을 생성할 수는 없다 – 모든 VBScript 는 0 에서 시작하는 배열을 생성한다.
스크립트 엔진은 variant 배열만 지원한다. 바이트의 배열은 underlying OS 에 의해 문자열로 변환될 수 있지만, 그것은 아주 엉망으로 만드는 것이다.
좀더 자세한 정보는 아래를 보라.
http://blogs.msdn.com/ericlippert/archive/2003/09/22/53061.aspx
http://blogs.msdn.com/ericlippert/archive/2003/09/22/53069.aspx
http://blogs.msdn.com/ericlippert/archive/2004/05/25/141525.aspx
Collections
VBScript 와 Jscript 모두 IEumVARIANT 를 구현한 컬렉션을 지원한다. 다른 열거자는 지원하지 않는다.
자세한 정보는 아래를 보라.
http://blogs.msdn.com/ericlippert/archive/2003/09/22/53063.aspx
Method names
객체 모델 이름에 A~Z 와 0~9 문자만 사용하라. Unerbar 를 가진 이름은 나쁘다. VB 에서는 라인 결합자(line continuation, _ ) 와 아주 쉽게 혼될 되고, 보기가 흉하다. 피하라.
Jscript 또는 VBScript 예약어 또는 내장(built-in) 객체 모델 엘리먼트와 충돌하는 이름은 역시 나쁜 생각이다.
자세한 정보는 아래를 보라.
http://weblogs.asp.net/ericlippert/archive/2004/06/10/152831.aspx
빠뜨린 점이 분명 있다고 확신한다. 나중에 그 목록에 대해 다시 업데이트할 것을 약속한다.
원문 : http://blogs.msdn.com/ericlippert/archive/2004/07/14/183241.aspx