Подробное исследование Delphi — руководство по применению CodeSite
Хотя Delphi предоставляет нам чрезвычайно мощные функции отладки, поиск ошибок по-прежнему остается трудной задачей. Обычно время, которое мы тратим на написание кода и на его отладку, примерно одинаково, а может быть даже больше. Чтобы сократить ненужную трату времени и энергии, иногда нам все же нужна помощь профессиональных инструментов отладки для повышения эффективности блокировки ошибок. В этой статье мы представим знаменитый инструмент отладки CodeSite PRO 2.0 (он занял второе место в номинации «Выбор читателей Delphi Informant Readers» 2000 года как лучший инструмент отладки). Официальный сайт — www.raize.com. Основная функция CodeSite — позволить разработчикам использовать код для отправки деталей времени выполнения специальным получателям для дальнейшего анализа. Точнее, с помощью класса TCodeSite, реализованного CodeSite, мы можем упаковывать и отправлять информацию времени выполнения диспетчеру CodeSite (распределителю сообщений CodeSite), который может направлять эти сообщения одному или нескольким получателям для просмотра. Получателем сообщений по умолчанию является CodeSite Viewer. Эффективность CodeSite проявляется в том, что он отличается от простого диалогового окна, отображающего сообщения или устанавливающего точки останова для проверки переменных. Он больше похож на функцию журнала событий (Event Log), которая поставляется с Delphi. несомненно, более мощный, чем журнал событий. Их много, и его сообщения устойчивы, то есть их можно сохранить, что облегчает ретроспективный анализ. Прежде чем рассказать о конкретном использовании CodeSite, давайте сначала рассмотрим три его компонента. Объект CodeSite Как упоминалось ранее, отправка сообщений CodeSite из работающего приложения осуществляется с помощью экземпляра класса TCodeSite (определенного в модуле CSIntf). Мы можем просто вызвать метод класса TCodeSite. Сообщение отправляется в CodeSite. Диспетчер. Например, вы можете использовать метод SendMsg объекта для отправки простого строкового сообщения. Объект TCodeSite реализует большое количество методов для поддержки различных типов отправки информации без какого-либо преобразования данных. Например, метод объекта SendObject имеет два параметра: один — строка сообщения, а другой — ссылка на экземпляр объекта. Этот метод получит объект Все опубликованные атрибуты, а затем упакует информацию об этих атрибутах в сообщения CodeSite. CodeSite Dispatcher В большинстве случаев CodeSite Dispatcher будет тихо работать в области панели задач. Его единственная функция — маршрутизировать сообщения CodeSite, отправленные от различных объектов TCodeSite, к местам назначения. По умолчанию сообщения CodeSite отправляются в CodeSite Viewer. Нам даже не нужно запускать диспетчер CodeSite, поскольку он будет автоматически запускаться такими объектами, как TCodeSite. Класс TCodeSite определяет свойство DestinationDetails, которое позволяет разработчикам настраивать способ маршрутизации отправленных сообщений CodeSite диспетчером CodeSite в различные места назначения, например в файлы журналов. Но обычно нет необходимости изменять это свойство. CodeSite Viewer Хотя CodeSite поддерживает отправку сообщений различным целям, в большинстве случаев CodeSite Viewer является основной целью отправки. Даже при отправке в другие места назначения, например в файлы журналов или на другой компьютер, CodeSite Viewer по-прежнему остается основным инструментом для просмотра и анализа сообщений. CodeSite Viewer состоит из следующих четырех панелей: список сообщений, средство просмотра сообщений, стек вызовов и панель Scratch. Основной рабочей областью CodeSite Viewer является список сообщений, который используется для отображения всех сообщений, отправленных в Viewer, или сообщений, загруженных из файлов журналов. Программы просмотра сообщений используются для просмотра дополнительной информации, связанной с сообщениями. Например, если текущее сообщение отправлено методом SendObject, средство просмотра сообщений отобразит текущие значения всех опубликованных свойств объекта. На панели стека вызовов отображается представление стека на основе сообщений csmEnterMethod. Скретч-панели используются для отображения неустойчивой информации. Панель «Скретч» очень полезна, когда мы хотим отслеживать определенную информацию, но не хотим записывать ее в журнал сообщений, например, когда мы хотим просмотреть большое количество повторяющихся сообщений, например текущее положение мыши. На данный момент мы можем использовать метод WritePoint объекта TCodeSite и указать параметр Line ID, чтобы указать количество строк рабочей панели, используемых для размещения информации о мыши. Давайте на простом примере продемонстрируем, как отправить сообщение в CodeSite Viewer из программы: (1) Создайте новый проект, а затем переключите панель компонентов на страницу CodeSite (CodeSite установит в систему два компонента после установки TCSGlobalObject и TCSObject). Выберите компонент TCSGlobalObject и поместите его в форму. Компонент TCSGlobalObject обеспечивает взаимодействие во время разработки с глобальным объектом TCodeSite (глобальный TCodeSite инициализируется в модуле CSInft). (2) Добавьте кнопку, а затем напишите следующий код в ее событии OnClick: //CodeSite — это глобальный объект TCodeSite CodeSite.SendMsg('Первое сообщение CodeSite'); (3) Скомпилируйте и запустите эту простую программу. Нажмите кнопку после запуска, и заработают CodeSite Dispatcher и CodeSite Viewer. При этом вы увидите сообщения, отправленные программой, в списке сообщений CodeSite Viewer (примечание: нам не нужно запускать CodeSite Dispatcher и CodeSite Viewer перед запуском программы, поскольку объект TCodeSite автоматически запустит их при нужно отправить сообщение). Результаты запуска показаны на рисунке 4.38 ниже:
(4) Затем остановите программу и добавьте следующий код в процесс обработки события OnClick: CodeSite.SendObject('Form1', Form1 (5) Перекомпилируйте и запустите программу, нажмите кнопку еще раз, на этот раз вы будете); в CodeSite Viewer я увидел два сообщения. Сообщение, соответствующее Форме1, включает в себя информацию об объекте Формы1. (6) Чтобы просмотреть информацию о связанном объекте Form1, выберите команду меню CodeSite Viewer View|Inspector, чтобы отобразить новую панель в правой части списка сообщений, в которой отображаются опубликованные атрибуты Form1, как показано на рисунке. Рисунок 4.39 ниже:
(7) Снова остановите программу, а затем измените код в процессе OnClick следующим образом: CodeSite.EnterMethod('Button1Click'); CodeSite.SendMsg('Первое сообщение CodeSite'); CodeSite.SendObject('Form1', Form1 ) ; CodeSite.ExitMethod('Button1Click'); (8) На этот раз, когда мы запустим программу и нажмем кнопку, мы увидим, что сообщения «Первое сообщение CodeSite» и «Form1» расположены между сообщениями «Button1Click», как показано на рисунке 4.40 ниже:
Добавив вызовы методов EnterMethod и ExitMethod, мы можем создать журнал для записи случаев вызова этих методов. Посмотрев примеры, мы обнаружим, что функция CodeSite очень мощная. Мы можем генерировать очень подробную информацию, просто добавив несколько операторов в программу, и отображать ее в ярких диаграммах с помощью CodeSite Viewer. Далее давайте поговорим о передовой технологии приложений CodeSite. Отправка сообщений в файлы журналов В каждой программе будет больше или меньше ошибок. Если этого не произойдет в данный момент, это произойдет в это время. Если этого не произойдет в течение короткого времени, это может произойти через долгое время. Иногда это происходит неоднократно, а иногда обнаруживается совершенно случайно. Если человек говорит вам, что написанные им программы запускаются без проблем в любое время, он лжет. Именно из-за случайного и скрытого характера ошибок нам часто сложно повторить ошибки, присланные пользователями, что создает для нас огромное препятствие для отладки программы и поиска причины проблемы, а CodeSite может отправлять сообщения для регистрации файлов. Это облегчает пользователям сообщение об ошибках, поскольку им нужно только отправить информационный файл, созданный во время выполнения. Соответственно, наша работа по отладке программы станет проще. Мы можем использовать CodeSite Viewer для интуитивного анализа причины и места ошибки. Чтобы изменить пункт назначения отправки сообщения, мы можем сделать это, установив свойство DestinationDetails объекта TCodeSite. Для использования этой функции на компьютере клиента должен быть установлен CodeSite Dispatcher, который является свободно распространяемой частью CodeSite. Конкретный процесс, приведенный ниже, по-прежнему основан на упомянутом выше примере: (1) Добавьте следующий код в событие OnCreate в форме: CodeSite.DestinationDetails := 'File[Path=C:/FirstLog.csl]' (2 ); скомпилируйте и запустите программу. На этот раз после нажатия кнопки сообщение больше не отправляется в CodeSite Viewer, а в файл FirstLog.csl на диске C. (3) Используйте CodeSite Viewer для загрузки файла FirstLog.csl. На этот раз мы просматриваем сохраненные сообщения CodeSite, как и раньше. (4) Если мы хотим одновременно отправлять сообщения в CodeSite Viewer и файлы журналов, просто измените предыдущий код на: CodeSite.DestinationDetails := 'Viewer,File[Path=C:/FirstLog.csl]'; -настраиваемые данные Хотя класс TCodeSite предоставляет большое количество методов для обработки различных типов данных, иногда нам может потребоваться отправить информацию о данных в определенном пользовательском формате. С этой целью класс TCodeSite определяет метод SendCustomData, который поддерживает отправку данных любого типа и форматирует данные в соответствии с пользовательским форматером, чтобы средство просмотра CodeSite могло правильно отображать данные. Сначала нам нужно создать подкласс объекта TCSFormatter, а затем перегрузить методы FormatData, InspectorType и TypeName объекта. Затем вызовите объект диспетчера объектов CodeSite CSObjectManager, чтобы зарегистрировать новый подкласс TCSFormatter. Кроме того, нам также необходимо вызвать метод RegisterCustomFormat, чтобы зарегистрировать новый тип сообщения. Ниже приведен пример пользовательского форматирования типа записи TCSEmployeeRecord: unit CSEmployee; интерфейс использует Windows, Graphics, CSIntf; const csmEmployeeSummary = csmUser + 1; csmEmployeeDetails = csmUser + 2; , в разделе «Использование» добавляется ссылка на модуль CSIntf. Второй шаг — определить новые константы типа сообщения CodeSite для каждого средства форматирования. Выше мы определили две константы. Обратите внимание, что константы должны быть больше, чем csmUser, но не больше 32 000. тип TCSEmployee = запись Фамилия: строка; Адрес: строка; Город: строка; Номер телефона: строка; Дата найма: Валюта; Дни отпуска: Целое число; Boolean; end; Вышеупомянутая запись — это пользовательский тип данных, который мы хотим отправить. TCSEmployeeSummaryFormatter = класс (TCSFormatter) общественная функция InspectorType: TCSInspectorType; процедура FormatData (var Data); функция TypeName: строка; переопределение; Data); Выше приведены определения двух пользовательских классов форматирования. Первое средство форматирования отформатирует запись TCSEmployee в текстовый формат, а второе средство форматирования отформатирует запись TCSEmployee в виде сетки. реализация использует SysUtils {=======================================} {= = Методы TCSEmployeeSummaryFormatter ==} {=======================================} функция TCSEmployeeSummaryFormatter .InspectorType: TCSInspectorType начать результат: = itStockStringList конец; Первым шагом в реализации пользовательского средства форматирования является определение типа встроенного средства просмотра, которое будет использоваться для просмотра форматированных данных. В этом случае используется средство просмотра списка строк. Тип средства просмотра будет использоваться методом FormatData. процедура TCSEmployeeSummaryFormatter.FormatData(var Data); var EmpRec: TCSEmployee; start EmpRec := TCSEmployee(Data); AddLine(EmpRec.FirstName + ' ' + EmpRec.LastName ); AddLine( EmpRec.City +); ', ' + EmpRec.State + ' ' + EmpRec.ZipCode ); AddLine( '' Телефон: ' + EmpRec.PhoneNumber ); AddLine( 'Дата приема на работу: ' + DateToStr( EmpRec.HireDate ) ); m', [EmpRec.Salary] ) ); AddLine( '' ); ' + IntToStr( EmpRec.VacationDays ) ); AddLine( 'Sick Days: ' + IntToStr( EmpRec.SickDays ) ); if EmpRec.Manager then AddLine( 'Manager: Yes' ) else AddLine( 'Manager: No' ); ; Метод FormatData является основной частью. Обратите внимание, что параметр Data, передаваемый методу FormatData, является нетипизированным переменным параметром. Это означает, что этот параметр может иметь любой тип данных. В процессе регистрации формата мы можем гарантировать, что принудительный тип будет сопоставлен с пользовательской записью данных без ошибок преобразования. После преобразования типа данных мы можем форматировать данные. Здесь мы используем метод AddLine базового класса TCSFormatter, чтобы добавить разделительные линии между строками для форматирования. function TCSEmployeeSummaryFormatter.TypeName: string; Begin Result := 'TCSEmployee end; Перегрузка метода TypeName необязательна, но обычно мы можем использовать ее для возврата строки, которая появляется в списке сообщений. {========================================} {== TCSEmployeeDetailsFormatter Methods == } {=========================================} функция TCSEmployeeDetailsFormatter.InspectorType: TCSInspectorType ; начало результата: = itStockGrid конец; Для средства форматирования сведений о сотрудниках для просмотра данных будет использоваться указанное средство просмотра сетки: ; AddNameValuePair('FirstName', EmpRec.FirstName); AddNameValuePair( 'Адрес', EmpRec.Address ); AddNameValuePair( 'Город', EmpRec.City ); AddNameValuePair( 'State', EmpRec.State ); AddNameValuePair( 'ZipCode', EmpRec.ZipCode ); AddNameValuePair('PhoneNumber', Эмпрек.НомерТелефона ); ДобавитьИмяЗначенияПара( 'HireDate', EmpRec.HireDate ); AddNameValuePair( 'Salary', Format( '%m', [EmpRec.Salary] ) ); AddNameValuePair( 'VacationDays', EmpRec.VacationDays ); AddNameValuePair( 'SickDays', EmpRec.SickDays ); ); AddNameValuePair('Менеджер', EmpRec.Manager ); end; Здесь для форматирования данных в средстве просмотра сетки мы используем метод AddNameValuePair. function TCSEmployeeDetailsFormatter.TypeName: string; Begin Result := 'TCSEmployee' end; Следующие две процедуры используются для инкапсуляции вызовов метода SendCustomData. Здесь вызывается глобальный экземпляр объекта TCodeSite CodeSite: {===== ==. =============} {== Методы поддержки ==} {=====================} процедура CSSendEmployeeSummary ( const Сообщение: строка; EmpRec: TCSEmployee); начало CodeSite.SendCustomData( csmEmployeeSummary, Msg, EmpRec); конец; процедура CSSendEmployeeDetails (const Msg: string; EmpRec: TCSEmployee); начало CodeSite.SendCustomData( csmEmployeeDetails, Msg, EmpRec); ; Наконец, не забудьте вызвать метод CSObjectManager.RegisterCustomFormatter, чтобы зарегистрировать форматировщик в диспетчере объектов CodeSite. инициализация CSObjectManager.RegisterCustomFormatter( csmEmployeeSummary, TCSEmployeeSummaryFormatter ); CSObjectManager.RegisterCustomFormatter( csmEmployeeDetails, TCSEmployeeDetailsFormatter end);