Delphi 심층 탐구 - CodeSite 애플리케이션 가이드
Delphi는 매우 강력한 디버깅 기능을 제공하지만 버그를 찾는 것은 여전히 힘든 작업입니다. 일반적으로 코드 작성과 코드 디버깅에 소요되는 시간은 거의 동일하며 더 많을 수도 있습니다. 불필요한 시간과 에너지 낭비를 줄이기 위해 때로는 버그 잠금 효율성을 향상시키기 위해 전문적인 디버깅 도구의 도움이 필요합니다. 이 기사에서는 유명한 디버깅 도구인 CodeSite PRo 2.0(2000년 Delphi Informant Readers' Choice Award에서 최고의 디버깅 도구로 2위를 차지함)을 소개합니다. 공식 홈페이지는 www.raize.com이다. CodeSite의 주요 기능은 개발자가 코드를 사용하여 추가 분석을 위해 런타임 세부 정보를 특수 수신기에 보낼 수 있도록 하는 것입니다. 보다 정확하게는 CodeSite에 의해 구현된 TCodeSite 클래스를 통해 런타임 정보를 패키징하여 CodeSite Dispatcher(CodeSite의 메시지 배포자)로 보낼 수 있으며, 이 Dispatcher는 이러한 메시지를 보기 위해 하나 이상의 수신자에게 라우팅할 수 있습니다. 기본 메시지 수신자는 CodeSite Viewer입니다. CodeSite의 효율성은 메시지를 표시하거나 변수를 확인하기 위해 중단점을 설정하는 간단한 대화 상자와 다르다는 점에서 나타납니다. 물론 Delphi에서 제공하는 이벤트 로그 기능과 더 유사합니다. 이벤트 로그보다 확실히 더 강력하고 메시지가 지속 가능합니다. 즉, 저장이 가능하므로 회고적 분석이 용이합니다. CodeSite의 구체적인 사용법을 소개하기 전에 먼저 세 가지 구성 요소를 살펴보겠습니다. CodeSite 객체 앞서 언급했듯이 실행 중인 애플리케이션에서 CodeSite 메시지를 보내는 것은 TCodeSite 클래스(CSIntf 유닛에 정의됨)의 인스턴스를 사용하여 수행됩니다. 메시지는 CodeSite로 전송됩니다. 디스패처. 예를 들어 개체의 SendMsg 메서드를 사용하여 간단한 문자열 메시지를 보낼 수 있습니다. TCodeSite 객체는 데이터 변환 없이 다양한 유형의 정보 전송을 지원하기 위해 많은 메소드를 구현합니다. 예를 들어 객체의 SendObject 메소드에는 두 개의 매개변수가 있습니다. 하나는 메시지 문자열이고 다른 하나는 객체 인스턴스에 대한 참조입니다. 이 메서드는 게시된 모든 속성을 얻은 다음 이러한 속성의 정보를 CodeSite 메시지로 패키지합니다. CodeSite Dispatcher 대부분의 경우 CodeSite Dispatcher는 시스템 트레이 영역에서 조용히 실행됩니다. 유일한 기능은 다양한 TCodeSite 객체에서 전송된 CodeSite 메시지를 대상으로 라우팅하는 것입니다. 기본적으로 CodeSite 메시지는 CodeSite Viewer로 전송됩니다. CodeSite Dispatcher는 TCodeSite와 같은 개체에 의해 자동으로 시작되므로 시작할 필요조차 없습니다. TCodeSite 클래스는 전송된 CodeSite 메시지가 CodeSite Dispatcher에 의해 로그 파일과 같은 다른 대상으로 라우팅되는 방식을 개발자가 구성할 수 있도록 하는 DestinationDetails 속성을 정의합니다. 그러나 일반적으로 이 속성을 수정할 필요는 없습니다. CodeSite 뷰어 CodeSite는 다양한 대상으로의 메시지 전송을 지원하지만 대부분의 경우 CodeSite 뷰어가 기본 전송 대상입니다. 로그 파일이나 다른 시스템과 같은 다른 대상으로 전송되는 경우에도 CodeSite Viewer는 여전히 메시지를 보고 분석하기 위한 기본 도구입니다. CodeSite 뷰어는 메시지 목록, 메시지 뷰어, 호출 스택 및 스크래치 패널의 네 가지 패널로 구성됩니다. CodeSite Viewer의 주요 작업 공간은 뷰어로 전송된 모든 메시지 또는 로그 파일에서 로드된 메시지를 표시하는 데 사용되는 메시지 목록입니다. 메시지 뷰어는 메시지와 관련된 추가 정보를 보는 데 사용됩니다. 예를 들어 현재 메시지가 SendObject 메서드에 의해 전송되면 메시지 뷰어는 개체의 게시된 모든 속성의 현재 값을 표시합니다. 호출 스택 패널에는 csmEnterMethod 메시지를 기반으로 스택 보기가 표시됩니다. 스크래치 패널은 지속 불가능한 정보를 표시하는 데 사용됩니다. 스크래치 패널은 마우스의 현재 위치와 같이 반복되는 많은 메시지를 보고 싶은 경우와 같이 특정 정보를 추적하고 싶지만 메시지 로그에 기록하고 싶지 않을 때 매우 유용합니다. 이때 TCodeSite 객체의 WritePoint 메서드를 사용하고 Line ID 매개변수를 지정하여 마우스 정보를 수용하는 데 사용되는 스크래치 패널 라인 수를 지정할 수 있습니다. 프로그램에서 CodeSite Viewer에 메시지를 보내는 방법을 보여주기 위해 간단한 예를 사용하겠습니다. (1) 새 프로젝트를 만든 다음 구성 요소 패널을 CodeSite 페이지로 전환합니다(CodeSite는 TCSGlobalObject 설치 후 시스템에 두 개의 구성 요소를 설치합니다) 및 TCSObject). TCSGlobalObject 구성 요소를 선택하고 양식에 배치합니다. TCSGlobalObject 구성 요소는 전역 TCodeSite 객체와의 디자인 타임 상호 작용을 제공합니다(전역 TCodeSite는 CSInft 단위에서 초기화됩니다). (2) 버튼을 추가한 후 OnClick 이벤트에 다음 코드를 작성합니다. //CodeSite는 전역 TCodeSite 개체입니다. CodeSite.SendMsg('CodeSite's first message') (3) 이 간단한 프로그램을 컴파일하고 실행합니다. 실행 후 버튼을 클릭하면 CodeSite Dispatcher와 CodeSite Viewer가 실행됩니다. 동시에 CodeSite Viewer의 메시지 목록에서 프로그램이 보낸 메시지를 볼 수 있습니다(참고: 프로그램을 실행하기 전에 CodeSite Dispatcher 및 CodeSite Viewer를 시작할 필요가 없습니다. 메시지를 보내야 합니다.) 실행 결과는 아래 그림 4.38에 나와 있습니다.
(4) 그런 다음 프로그램을 중지하고 OnClick 이벤트 처리 프로세스에 다음 코드를 추가합니다. CodeSite.SendObject('Form1', Form1) (5) 프로그램을 다시 컴파일하고 실행한 후 버튼을 다시 클릭합니다. CodeSite Viewer에서 두 개의 메시지를 보았습니다. Form1에 해당하는 메시지에는 Form1의 객체 정보가 포함되어 있습니다. (6) Form1의 관련 개체 정보를 보려면 CodeSite Viewer 메뉴 명령 View|Inspector를 선택하여 메시지 목록 오른쪽에 다음과 같이 Form1의 게시된 속성이 표시되는 새 패널을 표시합니다. 아래 그림 4.39.
(7) 프로그램을 다시 중지한 후 OnClick 프로세스의 코드를 다음과 같이 수정합니다. CodeSite.EnterMethod('Button1Click') CodeSite.SendMsg('CodeSite's first message'); ; CodeSite .ExitMethod('Button1Click' ); (8) 이번에는 프로그램을 실행하고 버튼을 클릭하면 아래 그림 4.40과 같이 "Button1Click" 메시지 사이에 "CodeSite의 첫 번째 메시지"와 "Form1" 메시지가 들여쓰기되어 있는 것을 볼 수 있습니다.
EnterMethod 및 ExitMethod 메서드에 대한 호출을 추가하면 해당 메서드가 호출될 때 기록할 로그를 생성할 수 있습니다. 예제를 살펴보면 CodeSite의 기능이 매우 강력하다는 것을 알 수 있습니다. 프로그램에 몇 가지 명령문만 추가하면 매우 상세한 정보를 생성하고 CodeSite 뷰어를 통해 생생한 차트로 표시할 수 있습니다. 다음으로 CodeSite의 앞선 응용기술에 대해 말씀드리겠습니다. 로그 파일로 메시지 보내기 모든 프로그램에는 어느 정도 버그가 있을 것입니다. 이때 발생하지 않으면 그 시점에 발생하기 마련입니다. 단시간에 발생하지 않으면 오랜 시간 후에 발생할 수 있습니다. 반복적으로 발생하는 경우도 있고 우연히 발견된 경우도 있습니다. 어떤 사람이 자신이 작성한 프로그램이 언제든지 문제 없이 실행된다고 말한다면 그는 거짓말을 하는 것입니다. 사용자가 제출한 버그를 반복하는 것이 어려운 것은 바로 버그의 우발적이고 숨겨진 특성 때문입니다. 이는 프로그램을 디버그하고 문제의 원인을 찾는 데 큰 장애물이 되며 CodeSite에서는 메시지를 보낼 수 있습니다. 이를 통해 사용자는 런타임 중에 생성된 정보 파일만 제출하면 되므로 버그를 더 쉽게 보고할 수 있습니다. 이에 따라 프로그램 디버깅 작업이 더 쉬워질 것입니다. CodeSite Viewer를 사용하면 오류의 원인과 위치를 직관적으로 분석할 수 있습니다. 메시지 전송 대상을 변경하려면 TCodeSite 개체의 DestinationDetails 속성을 설정하면 됩니다. 이 기능을 사용하려면 CodeSite의 무료 배포 부분인 CodeSite Dispatcher를 고객의 컴퓨터에 설치해야 합니다. 아래의 특정 프로세스는 여전히 이전에 언급한 예제를 기반으로 합니다. (1) 다음 코드를 형식의 OnCreate 이벤트에 추가합니다. CodeSite.DestinationDetails := 'File[Path=C:/FirstLog.csl]' (2 ) 프로그램을 컴파일하고 실행합니다. 이번에는 버튼을 클릭하면 메시지가 더 이상 CodeSite Viewer로 전송되지 않고 C 드라이브의 FirstLog.csl 파일로 전송됩니다. (3) CodeSite Viewer를 사용하여 FirstLog.csl 파일을 로드합니다. 이번에는 이전과 같이 저장된 CodeSite 메시지를 봅니다. (4) CodeSite Viewer와 로그 파일에 동시에 메시지를 보내려면 이전 코드를 다음과 같이 수정하면 됩니다. CodeSite.DestinationDetails := 'Viewer,File[Path=C:/FirstLog.csl]'; -customized Data TCodeSite 클래스는 다양한 데이터 유형을 처리하기 위한 많은 메소드를 제공하지만 때로는 특정 사용자 정의 형식으로 데이터 정보를 전송해야 할 수도 있습니다. 이를 위해 TCodeSite 클래스는 모든 데이터 유형 전송을 지원하고 CodeSite 뷰어가 데이터를 올바르게 표시할 수 있도록 사용자 정의 포맷터에 따라 데이터 형식을 지정하는 SendCustomData 메서드를 정의합니다. 먼저 TCSFormatter 개체의 하위 클래스를 만든 다음 개체의 FormatData, InspectorType 및 TypeName 메서드를 오버로드해야 합니다. 그런 다음 CodeSite 개체 관리자 개체 CSObjectManager를 호출하여 새 TCSFormatter 하위 클래스를 등록합니다. 또한 새 메시지 유형을 등록하려면 RegisterCustomFormat 메서드도 호출해야 합니다. 다음은 TCSEmployeeRecord 레코드 유형의 사용자 정의 포맷터가 CSEmployee.pas 유닛에 구현되어 있습니다. 인터페이스는 Windows, Graphics, CSIntf를 사용합니다. const csmEmployeeDetails = csmUser + 2; , Uses 섹션에서 CSIntf 유닛에 대한 참조를 추가합니다. 두 번째 단계는 각 포맷터에 대해 새로운 CodeSite 메시지 유형 상수를 정의하는 것입니다. 위에서 우리는 상수가 csmUser보다 커야 하지만 32,000보다 커서는 안 된다는 점에 유의하십시오. 유형 TCSEmployee: 문자열; 주소: 문자열; 우편번호: 문자열; 휴가일: 정수; Boolean end; 위의 레코드는 우리가 보내려는 사용자 정의 데이터 유형입니다. TCSEmployeeSummaryFormatter = class( TCSInspectorType); override; function TypeName: override; 위는 두 가지 사용자 정의 포맷터 클래스의 정의입니다. 첫 번째 포맷터는 TCSEmployee 레코드의 형식을 텍스트 형식으로 지정하고, 두 번째 포맷터는 TCSEmployee 레코드의 형식을 그리드 스타일로 지정합니다. 구현은 SysUtils를 사용합니다. {======================================} {= = TCSEmployeeSummaryFormatter 메소드 ==} {==========================================} 함수 TCSEmployeeSummaryFormatter .InspectorType: TCSInspectorType; 시작 결과 := itStockStringList; 사용자 정의 포맷터를 구현하는 첫 번째 단계는 형식화된 데이터를 보는 데 사용할 기본 제공 뷰어 유형을 결정하는 것입니다. 이 경우 문자열 목록 뷰어가 사용됩니다. 뷰어 유형은 FormatData 메서드에서 사용됩니다. 절차 TCSEmployeeSummaryFormatter.FormatData( var Data ); var EmpRec: TCSEmployee; AddLine( EmpRec.FirstName + ' ' + EmpRec.LastName ); ', ' + EmpRec.State + ' ' + EmpRec.ZipCode ); AddLine( '전화: ' + EmpRec.PhoneNumber ); AddLine( '고용 날짜: ' + DateToStr( EmpRec.HireDate ) ); m', [ EmpRec.Salary ] ) ); AddLine( '' ); ' + IntToStr( EmpRec.VacationDays ) ); AddLine( '병가: ' + IntToStr( EmpRec.SickDays ) ); if EmpRec.Manager then AddLine( 'Manager: Yes' ) else AddLine( 'Manager: No' ); ; FormatData 메소드는 핵심 부분입니다. FormatData 메소드에 전달된 Data 매개변수는 유형이 지정되지 않은 변수 매개변수입니다. 즉, 이 매개변수는 모든 데이터 유형이 될 수 있으며 형식 등록 프로세스를 통해 강제 유형이 변환 오류 없이 사용자 정의 데이터 레코드에 매핑되도록 할 수 있습니다. 데이터 유형을 변환한 후 데이터 형식을 지정할 수 있습니다. 여기서는 형식 지정을 위해 문자열 사이에 구분선을 추가하기 위해 TCSFormatter 기본 클래스의 AddLine 메서드를 사용합니다. function TCSEmployeeSummaryFormatter.TypeName: string; start Result := 'TCSEmployee'; end; TypeName 메서드의 오버로드는 선택 사항이지만 일반적으로 이를 사용하여 메시지 목록에 나타나는 문자열을 반환할 수 있습니다. {=========================================} {== TCSEmployeeDetailsFormatter 메소드 == } {=========================================} 함수 TCSEmployeeDetailsFormatter.InspectorType: TCSInspectorType ; 시작 결과 := itStockGrid; 직원 세부 정보 포맷터의 경우 명명된 그리드 뷰어가 데이터를 보는 데 사용됩니다. Procedure TCSEmployeeDetailsFormatter.FormatData( var Data ); var EmpRec: TCSEmployee; start EmpRec := TCSEmployee( Data ); AddNameValuePair( 'LastName', EmpRec .LastName ) ; AddNameValuePair( 'FirstName', EmpRec.FirstName ); AddNameValuePair( '주소', EmpRec.Address ); AddNameValuePair( '주', EmpRec.State ) AddNameValuePair( 'ZipCode', EmpRec.ZipCode ); EmpRec.PhoneNumber); AddNameValuePair( 'HireDate', EmpRec.HireDate ); AddNameValuePair( 'Salary', Format( '%m', [ EmpRec.Salary ] ) ) AddNameValuePair( 'VacationDays', EmpRec.VacationDays ); ); AddNameValuePair( '관리자', EmpRec.Manager ); end; 여기서는 그리드 뷰어에서 데이터 형식을 지정하기 위해 AddNameValuePair 메서드를 사용합니다. function TCSEmployeeDetailsFormatter.TypeName: string; start Result := 'TCSEmployee'; end; 여기서는 SendCustomData 메소드에 대한 호출을 캡슐화하는 데 사용됩니다. {===== == ==============} {== 지원 방법 ==} {=======================} 절차 CSSendEmployeeSummary ( const 메시지: 문자열; EmpRec: TCSEmployee ); 시작 CodeSite.Summary, Msg, EmpRec ); end; 절차 CSSendEmployeeDetails( const Msg: string; EmpRec: TCSEmployee ); 시작 CodeSite.SendCustomData( csmEmployeeDetails, Msg, EmpRec ); 마지막으로 CSObjectManager.RegisterCustomFormatter 메서드를 호출하여 포맷터를 CodeSite 개체 관리자에 등록하는 것을 잊지 마십시오. 초기화 CSObjectManager.RegisterCustomFormatter( csmEmployeeSummary, TCSEmployeeSummaryFormatter ); CSObjectManager.RegisterCustomFormatter( csmEmployeeDetails, TCSEmployeeDetailsFormatter );