Guide d'application Delphi pour l'exploration approfondie-CodeSite
Bien que Delphi nous offre des fonctions de débogage extrêmement puissantes, la recherche de bogues reste une tâche ardue. Habituellement, le temps que nous passons à écrire du code et à déboguer du code est à peu près le même, et peut même être plus. Afin de réduire les pertes inutiles de temps et d'énergie, nous avons parfois encore besoin de l'aide d'outils de débogage professionnels pour améliorer l'efficacité du verrouillage des bogues. Dans cet article, nous présenterons le célèbre outil de débogage CodeSite PRo 2.0 (il a remporté la deuxième place au Delphi Informant Readers' Choice Award 2000 pour le meilleur outil de débogage). Son site officiel est www.raize.com. La fonction principale de CodeSite est de permettre aux développeurs d'utiliser du code pour envoyer les détails d'exécution à des récepteurs spéciaux pour une analyse plus approfondie. Plus précisément, grâce à la classe TCodeSite implémentée par CodeSite, nous pouvons regrouper et envoyer des informations d'exécution au CodeSite Dispatcher (le distributeur de messages de CodeSite), qui peut acheminer ces messages vers un ou plusieurs récepteurs pour les visualiser. Le récepteur de messages par défaut est CodeSite Viewer. L'efficacité de CodeSite se reflète dans le fait qu'il est différent d'une simple boîte de dialogue qui affiche des messages ou définit des points d'arrêt pour vérifier les variables. Il est plus similaire à la fonction de journal des événements (Event Log) fournie avec Delphi. est sans doute plus puissant que Event Log. Il en existe beaucoup, et ses messages sont durables, c'est-à-dire qu'ils peuvent être sauvegardés, ce qui facilite l'analyse rétrospective. Avant de présenter l'utilisation spécifique de CodeSite, examinons d'abord ses trois composants. Objet CodeSite Comme mentionné précédemment, l'envoi de messages CodeSite à partir d'une application en cours d'exécution s'effectue en utilisant une instance de la classe TCodeSite (définie dans l'unité CSIntf). Nous pouvons simplement appeler la méthode de la classe TCodeSite. Répartiteur. Par exemple, vous pouvez utiliser la méthode SendMsg de l'objet pour envoyer un simple message sous forme de chaîne. L'objet TCodeSite implémente un grand nombre de méthodes pour prendre en charge différents types d'envoi d'informations sans aucune conversion de données. Par exemple, la méthode SendObject de l'objet a deux paramètres : l'un est la chaîne du message et l'autre est une référence à l'instance de l'objet. . Cette méthode obtiendra l'objet. Tous les attributs publiés, puis regroupera les informations de ces attributs dans les messages CodeSite. CodeSite Dispatcher Dans la plupart des cas, CodeSite Dispatcher s'exécutera silencieusement dans la zone de la barre d'état système. Sa seule fonction est d'acheminer les messages CodeSite envoyés depuis divers objets TCodeSite vers leurs destinations. Par défaut, les messages CodeSite sont envoyés à CodeSite Viewer. Nous n'avons même pas besoin de démarrer CodeSite Dispatcher car il sera automatiquement démarré par des objets tels que TCodeSite. La classe TCodeSite définit une propriété DestinationDetails qui permet aux développeurs de configurer la manière dont les messages CodeSite envoyés sont acheminés par CodeSite Dispatcher vers différentes destinations, telles que les fichiers journaux. Mais il n’est généralement pas nécessaire de modifier cette propriété. CodeSite Viewer Bien que CodeSite prenne en charge l'envoi de messages à différentes cibles, dans la plupart des cas, CodeSite Viewer est la cible d'envoi principale. Même lorsqu'il est envoyé vers d'autres destinations, telles que des fichiers journaux ou une autre machine, CodeSite Viewer reste le principal outil d'affichage et d'analyse des messages. CodeSite Viewer se compose des quatre panneaux suivants : liste de messages, visualiseur de messages, pile d'appels et panneau Scratch. L'espace de travail principal de CodeSite Viewer est la liste des messages, qui est utilisée pour afficher tous les messages envoyés à la visionneuse ou les messages chargés à partir des fichiers journaux. Les visualiseurs de messages sont utilisés pour afficher des informations supplémentaires associées aux messages. Par exemple, si le message actuel est envoyé par la méthode SendObject, la visionneuse de messages affichera les valeurs actuelles de toutes les propriétés publiées de l'objet. Le panneau de pile d'appels affiche une vue de pile basée sur les messages csmEnterMethod. Les panneaux à gratter sont utilisés pour afficher des informations non durables. Le panneau Scratch est très utile lorsque nous voulons suivre certaines informations mais ne voulons pas les enregistrer dans le journal des messages, comme lorsque nous voulons visualiser un grand nombre de messages répétés comme la position actuelle de la souris. À ce stade, nous pouvons utiliser la méthode WritePoint de l'objet TCodeSite et spécifier le paramètre Line ID pour spécifier le nombre de lignes du panneau de travail utilisées pour accueillir les informations de la souris. Utilisons un exemple simple pour montrer comment envoyer un message à CodeSite Viewer à partir du programme : (1) Créez un nouveau projet, puis basculez le panneau des composants vers la page CodeSite (CodeSite installera deux composants dans le système après l'installation de TCSGlobalObject. et TCSObject). Sélectionnez le composant TCSGlobalObject et placez-le sur le formulaire. Le composant TCSGlobalObject fournit une interaction au moment de la conception avec l'objet TCodeSite global (le TCodeSite global est initialisé dans l'unité CSInft). (2) Ajoutez un bouton, puis écrivez le code suivant dans son événement OnClick : //CodeSite est l'objet global TCodeSite CodeSite.SendMsg('Premier message de CodeSite'); (3) Compilez et exécutez ce programme simple. Cliquez sur le bouton après l'exécution et CodeSite Dispatcher et CodeSite Viewer s'exécuteront. En même temps, vous verrez les messages envoyés par le programme dans la liste des messages de CodeSite Viewer (remarque : nous n'avons pas besoin de démarrer CodeSite Dispatcher et CodeSite Viewer avant d'exécuter le programme, car l'objet TCodeSite les démarrera automatiquement lorsqu'il doit envoyer des messages). Les résultats d'exécution sont présentés dans la figure 4.38 ci-dessous :
(4) Ensuite, arrêtez le programme et ajoutez le code suivant dans le processus de gestion des événements OnClick : CodeSite.SendObject('Form1', Form1); (5) Recompilez et exécutez le programme, cliquez à nouveau sur le bouton, cette fois vous serez dans CodeSite Viewer, j'ai vu deux messages. Le message correspondant à Form1 inclut les informations d'objet de Form1. (6) Afin de voir les informations sur l'objet associé de Form1, sélectionnez la commande de menu CodeSite Viewer View|Inspector pour afficher un nouveau panneau sur le côté droit de la liste de messages, dans lequel les attributs publiés de Form1 sont affichés, comme indiqué dans Figure 4.39 ci-dessous :
(7) Arrêtez à nouveau le programme, puis modifiez le code dans le processus OnClick comme suit : CodeSite.EnterMethod('Button1Click'); CodeSite.SendMsg('Premier message de CodeSite'); ; CodeSite .ExitMethod('Button1Click' ); (8) Cette fois, lorsque nous exécutons le programme et cliquons sur le bouton, nous verrons que les messages « CodeSite's first message » et « Form1 » sont indentés entre les messages « Button1Click », comme le montre la figure 4.40 ci-dessous :
En ajoutant des appels aux méthodes EnterMethod et ExitMethod, nous pouvons générer un journal pour enregistrer lorsque les méthodes sont appelées. Après avoir examiné les exemples, nous constaterons que la fonction de CodeSite est très puissante. Nous pouvons générer des informations très détaillées en ajoutant simplement quelques instructions au programme et les afficher sous forme de graphiques éclatants via la visionneuse CodeSite. Parlons ensuite de la technologie d’application avancée de CodeSite. Envoi de messages aux fichiers journaux Chaque programme aura plus ou moins de bugs. Si cela ne se produit pas à ce moment-là, cela se produira à ce moment-là. Si cela ne se produit pas dans un court laps de temps, cela peut se produire après un long moment. apparaît à plusieurs reprises, et parfois cela arrive très accidentellement. Si une personne vous dit que les programmes qu’elle écrit fonctionnent sans aucun problème à tout moment, elle ment. C'est précisément à cause de la nature accidentelle et cachée des bugs qu'il nous est souvent difficile de répéter les bugs soumis par les utilisateurs, ce qui crée un énorme obstacle pour nous de déboguer le programme et de trouver la cause du problème, et CodeSite peut envoyer des messages. pour enregistrer les fichiers. Cela permet aux utilisateurs de signaler plus facilement les bogues, car ils n'ont qu'à soumettre le fichier d'informations généré pendant l'exécution. En conséquence, notre travail de débogage du programme deviendra plus facile. Nous pouvons utiliser CodeSite Viewer pour analyser intuitivement la cause et l'emplacement de l'erreur. Pour modifier la destination de l'envoi du message, nous pouvons le faire en définissant la propriété DestinationDetails de l'objet TCodeSite. Cette fonctionnalité nécessite que CodeSite Dispatcher soit installé sur la machine du client, qui est une partie librement distribuable de CodeSite. Le processus spécifique suivant est toujours basé sur l'exemple mentionné précédemment : (1) Ajoutez le code suivant dans l'événement OnCreate du formulaire : CodeSite.DestinationDetails := 'File[Path=C:/FirstLog.csl]' (2 ) compilez et exécutez le programme. Cette fois, après avoir cliqué sur le bouton, le message n'est plus envoyé au CodeSite Viewer mais au fichier FirstLog.csl sur le lecteur C. (3) Utilisez CodeSite Viewer pour charger le fichier FirstLog.csl. Cette fois, nous visualisons les messages CodeSite enregistrés comme auparavant. (4) Si nous voulons envoyer des messages à CodeSite Viewer et des fichiers journaux en même temps, modifiez simplement le code précédent comme suit : CodeSite.DestinationDetails := 'Viewer,File[Path=C:/FirstLog.csl]'; -Données personnalisées Bien que la classe TCodeSite fournisse un grand nombre de méthodes pour traiter différents types de données, nous pouvons parfois avoir besoin d'envoyer des informations sur les données dans un certain format personnalisé. À cette fin, la classe TCodeSite définit la méthode SendCustomData, qui prend en charge l'envoi de tout type de données et formate les données selon un formateur personnalisé afin que CodeSite Viewer puisse afficher les données correctement. Nous devons d’abord créer une sous-classe de l’objet TCSFormatter, puis surcharger les méthodes FormatData, InspectorType et TypeName de l’objet. Appelez ensuite l'objet du gestionnaire d'objets CodeSite CSObjectManager pour enregistrer la nouvelle sous-classe TCSFormatter. De plus, nous devons également appeler la méthode RegisterCustomFormat pour enregistrer un nouveau type de message. Voici un exemple d'application pratique. Un formateur personnalisé du type d'enregistrement TCSEmployeeRecord est implémenté dans l'unité CSEmployee.pas : l'unité CSEmployee ; l'interface utilise Windows, Graphics, CSIntf ; , dans la section Utilisations, ajoute une référence à l'unité CSIntf. La deuxième étape consiste à définir de nouvelles constantes de type de message CodeSite pour chaque formateur. Ci-dessus, nous avons défini deux constantes. Notez que les constantes doivent être supérieures à csmUser, mais pas supérieures à 32 000. tapez TCSEmployee = enregistrement Nom : chaîne ; Prénom : chaîne ; Adresse : chaîne ; Code postal : chaîne ; Date d'embauche : TDateTime ; Boolean; end; L'enregistrement ci-dessus est le type de données personnalisé que nous voulons envoyer. TCSEmployeeSummaryFormatter = class( TCSFormatter ) public function InspectorType : TCSInspectorType ; procédure FormatData( var Data ); Ci-dessus se trouvent les définitions de deux classes de formateur personnalisées. Le premier formateur formatera l'enregistrement TCSEmployee dans un format texte, et le deuxième formateur formatera l'enregistrement TCSEmployee dans un style de grille. l'implémentation utilise SysUtils ; {=========================================} {= = Méthodes TCSEmployeeSummaryFormatter ==} {============================================} fonction TCSEmployeeSummaryFormatter .InspectorType : TCSInspectorType ; début Résultat := itStockStringList end ; La première étape de la mise en œuvre d'un formateur personnalisé consiste à déterminer quel type de visionneuse intégrée sera utilisée pour afficher les données formatées. Dans ce cas, une visionneuse de liste de chaînes est utilisée. Le type de visionneuse sera utilisé par la méthode FormatData. procédure TCSEmployeeSummaryFormatter.FormatData( var Data ); var EmpRec: TCSEmployee; start EmpRec := TCSEmployee( Data ); ', ' + EmpRec.State + ' ' + EmpRec.ZipCode ); AddLine( '' ); AddLine( 'Téléphone : ' + EmpRec.PhoneNumber ); AddLine( 'Date d'embauche : ' + DateToStr( EmpRec.HireDate ) ); m', [ EmpRec.Salary ] ) ); AddLine( '' ); AddLine( 'Jours de vacances : ' + IntToStr( EmpRec.VacationDays ) ); AddLine( 'Jours de maladie : ' + IntToStr( EmpRec.SickDays ) ); si EmpRec.Manager then AddLine( 'Manager : Oui' ) else AddLine( 'Manager : Non' ); ; La méthode FormatData est la partie principale. Notez que le paramètre Data transmis à la méthode FormatData est un paramètre variable non typé. Cela signifie que ce paramètre peut être de n'importe quel type de données. Grâce au processus d'enregistrement du format, nous pouvons garantir que le type forcé est mappé à un enregistrement de données personnalisé sans erreurs de conversion. Après avoir converti le type de données, nous pouvons formater les données. Ici, nous utilisons la méthode AddLine de la classe de base TCSFormatter pour ajouter des lignes de séparation entre les chaînes pour le formatage. function TCSEmployeeSummaryFormatter.TypeName: string; begin Résultat := 'TCSEmployee'; La surcharge de la méthode TypeName est facultative, mais nous pouvons généralement l'utiliser pour renvoyer la chaîne qui apparaît dans la liste des messages. {=========================================} {== Méthodes TCSEmployeeDetailsFormatter == } {==========================================} fonction TCSEmployeeDetailsFormatter.InspectorType : TCSInspectorType ; début Résultat := itStockGrid end; Pour le formateur de détails des employés, la visionneuse de grille nommée sera utilisée pour afficher les données : procédure TCSEmployeeDetailsFormatter.FormatData( var Data ); var EmpRec: TCSEmployee; begin EmpRec := TCSEmployee( Data ); ; AddNameValuePair( 'FirstName', EmpRec.FirstName ); AddNameValuePair( 'Adresse', EmpRec.Address ); AddNameValuePair( 'Ville', EmpRec.City ); AddNameValuePair( 'State', EmpRec.State ); EmpRec.PhoneNumber ); AddNameValuePair( 'HireDate', EmpRec.HireDate ); AddNameValuePair( 'Salaire', Format( '%m', [ EmpRec.Salary ] ) ); AddNameValuePair( 'VacationDays', EmpRec.VacationDays ); ); AddNameValuePair( 'Gestionnaire', EmpRec.Manager ); end; Ici, afin de formater les données dans la visionneuse de grille, nous utilisons la méthode AddNameValuePair. function TCSEmployeeDetailsFormatter.TypeName: string; start Résultat := 'TCSEmployee'; end Les deux procédures suivantes sont utilisées pour encapsuler les appels à la méthode SendCustomData Ici, l'instance d'objet TCodeSite globale est appelée : {===== ==. =============} {== Méthodes de support ==} {======================} procédure CSSendEmployeeSummary ( const Message : chaîne ; EmpRec : TCSEmployee ); commencer CodeSite.SendCustomData( csmEmployeeSummary, Msg, EmpRec ); fin; procédure CSSendEmployeeDetails( const Msg: string; EmpRec: TCSEmployee ); Enfin, n'oubliez pas d'appeler la méthode CSObjectManager.RegisterCustomFormatter pour enregistrer le formateur auprès du gestionnaire d'objets CodeSite. initialisation CSObjectManager.RegisterCustomFormatter( csmEmployeeSummary, TCSEmployeeSummaryFormatter ); CSObjectManager.RegisterCustomFormatter( csmEmployeeDetails, TCSEmployeeDetailsFormatter end );