반응형
나에게 GUI 애플리케이션 디버깅이란 디버깅 스테이트먼트를 대개 대화 상자 형태로 보여주는 것이다.이 테크닉은 소규모부터 중규모의 애플리케이션에서는 유효하다.하지만 대규모 애플리케이션의 경우 스테이트먼트마다 대화상자가 팝업되는 것은 비생산적이다.실행 시에 디버깅 스테이트먼트를 표시하는 더 좋은 방법은 없을까 생각한 결과, 눈에 띈 것이 C#이다.C#은 내가 편리하고 확장 가능한 디버깅 시스템을 설계하던 중 부딪친 3가지 문제를 해결해 주었다.나는 보통 자바, C/C++를 주로 사용하는데, 이들 프로그래밍 언어에서는 다음과 같은 문제가 있었다.행 번호, 메서드 이름 등의 메타 정보를 충분히 얻을 수 없다
디버깅의 초점이 이동할 때마다 디버깅 스테이트먼트의 추가와 삭제를 실시할 필요가 있다
디버깅 스테이트먼트를 프로그램 내에 컴파일 하면 퍼포먼스에 악영향을 미치는 3가지 문제의 해결책에서는 이들 문제에 대한 해결책을 순서대로 살펴보자.첫 번째 문제이다.이 문제는 기본적으로 System.Reflection 및 System.Diagnostics 이름 공간의 몇 가지 클래스로 해결할 수 있다.System.Diagnostics.StackFrame 클래스를 사용하면 콜스택을 조사하여 현재 수준보다 위 단계에 무엇이 있는지, 어느 행에서 함수가 호출되었는지 등의 자세한 내용을 알 수 있다.또한 System.Reflection 클래스를 사용하면 함수, 이름공간, 변수형 등의 이름을 확인할 수 있다.이들 클래스를 이용한 것이 다음 코드이다.이 코드에서는 그것을 호출한 함수의 파일명, 행 번호, 메서드 이름을 취득했다.// create the stack frame for the function that
// called this function
StackFrame sf = new StackFrame ( 1 , true ) ;
// save the method name
string methodName = sf . GetMethod ( ) . ToString ( ) ;
// save the file name
string fileName = sf . GetFileName ( ) ;
// save the line number
int line Number = sf.Get File Line Number(); 다음은 두 번째 문제, 실행 시 프로그램 내의 다양한 섹션을 선택하고 디버깅 하려면 어떻게 해야 할까이다.이 문제는 첫 번째 문제와 관련이 있다.첫 번째 문제를 해결해야 얻을 수 있는 정보가 디버깅 스테이트먼트의 표시를 필터링하는 데 도움이 되기 때문이다.다음의 예에서는 이름 공간에 근거해 필터링을 실시하기로 한다.예를 들면, 프로그램 내에 15이름 공간이 있고 그 중 1개의 이름 공간의 디버깅 발표만 표시하겠다는.이 경우 디버깅 클래스에 그 이름 공간만이 디버깅 스테이트먼트를 표시하도록 지시하기만 하면 된다.코드 예는 다음과 같다//create the namespaces hashtable
namespaces = new Hashtable ( ) ;
// get the assembly of this class
Assembly a = Assembly . GetAssembly ( new Debug ( ) . GetType ( ) ) ;
// now cycle through each type and gather up all the namespaces
foreach ( Type type in a . GetTypes ( ) )
{
// check if the namespace is already in our table
if ( ! namespaces . Contains ( type . Namespace ) )
namespaces . Add ( type . Namespace , true ) ;
}} 위 코드에서는 이 코드를 포함하고 있는 Debug 클래스와 같은 어셈블리 내에 있는 모든 이름 공간을 저장할 Hashtable 객체를 작성한다.그러나 이렇게 되면 문제의 절반만 해결됐을 뿐이다.나머지 절반, 즉 실제 필터링 코드는 다음과 같다.// only proceed if the namespace in question is being debugged
if ( ( bool ) namespaces [ method . DeclaringType . Namespace ] )
// this is where the debug statement display code would be 여기까지는 잘했어.남는 문제는 프로그램의 최종 릴리스를 작성할 때 귀찮은 디버깅 스테이트먼트를 일일이 수작업으로 코멘트 아웃하거나 삭제하는 수고를 들이지 않고 삭제하는 것이다.여기서 도움이 되는 것이′속성′이다.여기에서는 여러분이 이미 C#에서의 속성의 동작을 알고 있을 것으로 상정하고 개념적인 설명을 생략하고, 전술한 System.Diagnostics 이름 공간에 포함되어 있는 Conditional Attribute의 설명으로 넘어가도록 한다.다음으로 Conditional Attribute 클래스의 사용 예를 제시한다. [Conditional (′DEBUG′)]
public void Debug ( string msg )
{
// this is where the debug statement
// display code would be
}}이와 같이 기술하면 프로그램 컴파일 시에 #defined에서 ′DEBUG′가 지정되어 있는지 여부가 체크되고, 정의되어 있는 경우에는 이 함수가 그대로 남겨진다.그러나 #defined에서 ′DEBUG′가 지정되어 있지 않을 경우에는 이 함수에 대한 모든 호출이 컴파일로 부터 제외되어 퍼포먼스에 영향을 주는 일이 없어진다.요약해서 여기서 다룬 문제들 중 몇몇은 C/C++나 Java로도 해결할 수 있다고 주장하는 사람이 있을 수 있지만, 두 언어 모두 모든 문제를 해결할 수는 없다.예를 들어 C/C++에서는 #define과 #ifdef를 사용하여 C#의 Conditional Attribute 클래스와 같은 것을 실현한다.그러나, C/C++로 유익한 메타데이터 정보를 입수하는 데는 한계가 있다.또, Java 에서는 메타데이터 정보를 입수하는 것은 가능하지만, 내가 아는 한, 모든 코드가 반드시 컴파일 되어 버린다(즉, 조건 컴파일의 기능은 없다). C# 면, 상기의 문제를 모두(게다가 세련된 방법으로) 해결해, 게다가 그 이상의 것이 가능하다.이상의 테크닉의 구체적인 예를 나타내기 위해서, 작은 Windows 애플리케이션을 작성해 보았다.이 Debug 클래스는 다른 프로젝트에도 삽입 가능하다.꼭 시험해 봤으면 좋겠다.
디버깅의 초점이 이동할 때마다 디버깅 스테이트먼트의 추가와 삭제를 실시할 필요가 있다
디버깅 스테이트먼트를 프로그램 내에 컴파일 하면 퍼포먼스에 악영향을 미치는 3가지 문제의 해결책에서는 이들 문제에 대한 해결책을 순서대로 살펴보자.첫 번째 문제이다.이 문제는 기본적으로 System.Reflection 및 System.Diagnostics 이름 공간의 몇 가지 클래스로 해결할 수 있다.System.Diagnostics.StackFrame 클래스를 사용하면 콜스택을 조사하여 현재 수준보다 위 단계에 무엇이 있는지, 어느 행에서 함수가 호출되었는지 등의 자세한 내용을 알 수 있다.또한 System.Reflection 클래스를 사용하면 함수, 이름공간, 변수형 등의 이름을 확인할 수 있다.이들 클래스를 이용한 것이 다음 코드이다.이 코드에서는 그것을 호출한 함수의 파일명, 행 번호, 메서드 이름을 취득했다.// create the stack frame for the function that
// called this function
StackFrame sf = new StackFrame ( 1 , true ) ;
// save the method name
string methodName = sf . GetMethod ( ) . ToString ( ) ;
// save the file name
string fileName = sf . GetFileName ( ) ;
// save the line number
int line Number = sf.Get File Line Number(); 다음은 두 번째 문제, 실행 시 프로그램 내의 다양한 섹션을 선택하고 디버깅 하려면 어떻게 해야 할까이다.이 문제는 첫 번째 문제와 관련이 있다.첫 번째 문제를 해결해야 얻을 수 있는 정보가 디버깅 스테이트먼트의 표시를 필터링하는 데 도움이 되기 때문이다.다음의 예에서는 이름 공간에 근거해 필터링을 실시하기로 한다.예를 들면, 프로그램 내에 15이름 공간이 있고 그 중 1개의 이름 공간의 디버깅 발표만 표시하겠다는.이 경우 디버깅 클래스에 그 이름 공간만이 디버깅 스테이트먼트를 표시하도록 지시하기만 하면 된다.코드 예는 다음과 같다//create the namespaces hashtable
namespaces = new Hashtable ( ) ;
// get the assembly of this class
Assembly a = Assembly . GetAssembly ( new Debug ( ) . GetType ( ) ) ;
// now cycle through each type and gather up all the namespaces
foreach ( Type type in a . GetTypes ( ) )
{
// check if the namespace is already in our table
if ( ! namespaces . Contains ( type . Namespace ) )
namespaces . Add ( type . Namespace , true ) ;
}} 위 코드에서는 이 코드를 포함하고 있는 Debug 클래스와 같은 어셈블리 내에 있는 모든 이름 공간을 저장할 Hashtable 객체를 작성한다.그러나 이렇게 되면 문제의 절반만 해결됐을 뿐이다.나머지 절반, 즉 실제 필터링 코드는 다음과 같다.// only proceed if the namespace in question is being debugged
if ( ( bool ) namespaces [ method . DeclaringType . Namespace ] )
// this is where the debug statement display code would be 여기까지는 잘했어.남는 문제는 프로그램의 최종 릴리스를 작성할 때 귀찮은 디버깅 스테이트먼트를 일일이 수작업으로 코멘트 아웃하거나 삭제하는 수고를 들이지 않고 삭제하는 것이다.여기서 도움이 되는 것이′속성′이다.여기에서는 여러분이 이미 C#에서의 속성의 동작을 알고 있을 것으로 상정하고 개념적인 설명을 생략하고, 전술한 System.Diagnostics 이름 공간에 포함되어 있는 Conditional Attribute의 설명으로 넘어가도록 한다.다음으로 Conditional Attribute 클래스의 사용 예를 제시한다. [Conditional (′DEBUG′)]
public void Debug ( string msg )
{
// this is where the debug statement
// display code would be
}}이와 같이 기술하면 프로그램 컴파일 시에 #defined에서 ′DEBUG′가 지정되어 있는지 여부가 체크되고, 정의되어 있는 경우에는 이 함수가 그대로 남겨진다.그러나 #defined에서 ′DEBUG′가 지정되어 있지 않을 경우에는 이 함수에 대한 모든 호출이 컴파일로 부터 제외되어 퍼포먼스에 영향을 주는 일이 없어진다.요약해서 여기서 다룬 문제들 중 몇몇은 C/C++나 Java로도 해결할 수 있다고 주장하는 사람이 있을 수 있지만, 두 언어 모두 모든 문제를 해결할 수는 없다.예를 들어 C/C++에서는 #define과 #ifdef를 사용하여 C#의 Conditional Attribute 클래스와 같은 것을 실현한다.그러나, C/C++로 유익한 메타데이터 정보를 입수하는 데는 한계가 있다.또, Java 에서는 메타데이터 정보를 입수하는 것은 가능하지만, 내가 아는 한, 모든 코드가 반드시 컴파일 되어 버린다(즉, 조건 컴파일의 기능은 없다). C# 면, 상기의 문제를 모두(게다가 세련된 방법으로) 해결해, 게다가 그 이상의 것이 가능하다.이상의 테크닉의 구체적인 예를 나타내기 위해서, 작은 Windows 애플리케이션을 작성해 보았다.이 Debug 클래스는 다른 프로젝트에도 삽입 가능하다.꼭 시험해 봤으면 좋겠다.
반응형