Forums Développement Multimédia

Les formations Mediabox
Les formations Mediabox

Débugger avec l'IDE Flash CS4 et +

Compatible ActionScript 3. Cliquer pour en savoir plus sur les compatibilités.Compatible Flash CS4. Cliquer pour en savoir plus sur les compatibilités.Par frangois (frangois), le 19 mai 2011

L’objet de ce tutoriel est l’utilisation des techniques de débuggage. Le débuggage est un terme relativement vague qui regroupe un domaine assez vaste, tout au long des différentes phases d’un projet :

  • en phase de développement : assurer au développeur une vision claire de ce qui se passe en arrière-plan, dans l’environnement de développement.
  • en phase de production : assurer au développeur un diagnostic rapide des problèmes pouvant survenir lors du déploiement, et assurer à l’usager une gestion des erreurs correctes dans des circonstances exceptionnelles, le tout dans l’environnement de production.

Mettre en place un environnement de développement

Les versions de debug du Flash Player

Pour bosser correctement, le premier geste indispensable est l’installation d’un Flash Player en version debug. Adobe fournit ces versions réservées aux développeurs ici : http://www.adobe.com/support/flashplayer/downloads.html

On installe le plugin qui va bien pour le browser qu’on préfère utiliser.

Attention si vous utilisez Chrome, il a son propre Flash Player intégré. Il faut passer par about:plugins et le désactiver :

On désactive le plug-in intégré pour utiliser celui qu’on vient d’installer en cliquant simplement sur Activer/Désactiver.

L’application de test

Réalisons une petite application de test simple qu’on utilisera tout au long du tutoriel. Ce n’est pas le sujet de cet article que d’en expliquer le fonctionnement, donc on restera sur quelque chose de très simple. On affiche un bouton Play, et un MP3 est loadé en externe :

package
{
	import flash.display.Sprite;
	import flash.events.Event;
	import flash.events.IOErrorEvent;
	import flash.events.MouseEvent;
	import flash.events.ProgressEvent;
	import flash.media.Sound;
	import flash.media.SoundChannel;
	import flash.net.URLRequest;
 
	public class TutorielDebug extends Sprite
	{
		private var _s: Sound;
		private var _sc: SoundChannel;
		private var _isPlaying: Boolean = true;
 
		public function TutorielDebug()
		{
			addEventListener(Event.ADDED_TO_STAGE, onAdded);
		}
 
		private function onAdded(e: Event): void
		{
			removeEventListener(Event.ADDED_TO_STAGE, onAdded);
 
			// création de l'U.I.
			var btPlay: ButtonPlay_skin = new ButtonPlay_skin();
			btPlay.x = btPlay.y = 10;
			btPlay.alpha = .5;
			btPlay.buttonMode = true;
			btPlay.mouseChildren = false;
			btPlay.addEventListener(MouseEvent.CLICK, onTogglePlay);
			addChild(btPlay);
 
			// lancement de l'audio
			_s = new Sound();
			_s.addEventListener(Event.ID3, onID3);
			_s.addEventListener(Event.COMPLETE, onComplete);
			_s.addEventListener(ProgressEvent.PROGRESS, onProgress);
			_s.addEventListener(IOErrorEvent.IO_ERROR, onIOError);
			_s.load(new URLRequest('calavera.mp3'));
			_sc = _s.play();
		}
 
		private function onTogglePlay(e: MouseEvent): void
		{
			if(_isPlaying) {
				_sc.stop();
			} else {
				_sc = _s.play();
			}
 
			(e.target as ButtonPlay_skin).alpha = _isPlaying ? 1 : .5;
			_isPlaying = !_isPlaying;
		}
 
		private function onID3(e: Event): void
		{
			trace('onID3: ' + _s.id3.artist + '/' + _s.id3.songName + '/' + _s.id3.album);
		}
 
		private function onComplete(e: Event): void
		{
			trace('onComplete');
		}
 
		private function onProgress(e: ProgressEvent): void
		{
			trace('onProgressEvent: ' + e.bytesLoaded + '/' + e.bytesTotal);
		}
	}
}
Voici les fichiers à télécharger
On trouve dans cette archive un projet Flash Builder et un .fla destiné à la version Flash IDE du tutoriel. Les 2 versions cohabitent dans le même dossier.

2) Le débugging lors de la phase de développement

2.1) l’usage de trace()

Commençons par les bases. On ouvre TutorielDebug.fla, qui est notre point d’entrée principal pour l’application lorsqu’elle est compilée via Flash CS4. On ouvre aussi dans Flash CS4 la classe src/TutorielDebug.as, qui en est le code source principal.

On note la présence de la bien connue instruction trace(), dont l’usage est probablement déjà familier. Elle sert à afficher un texte quelconque dans la fenêtre de sortie. C’est le degré zéro du débuggage : en plaçant des instructions trace() judicieusement, le développeur peut suivre à son gré le déroulement de l’application. trace() prend en paramètre un type quelconque.

Il assez pénible d’afficher les propriétés d’un objet complexe avec trace(), par exemple cet objet :

package
{
	public class ComplexObject
	{
		public var foo: String = 'fooValue';
		public var bar: String = 'barValue';
		public var baz: Number = 42;
	}
}

Si on essaie simplement :

trace(instance);

On obtient :

[Object] // pas très intéressant

On utilise donc la platrée de code suivante :

trace(‘instance.foo: ’ + instance.foo);
trace(‘instance.bar: ’ + instance.bar);
trace(‘instance.baz: ’ + String(instance.baz));

C’est bien mais pas top. En réalité lorsqu’on passe un objet à trace(), il cherche la méthode toString() de l’objet. Si elle n’existe pas, il utilise Object.toString(), et affiche donc [Object] - ce qui n’est pas très utile. Mais si nous ajoutons une méthode toString() retournant une String à notre objet :

package
{
	public class ComplexObject
	{
		public var foo: String = 'fooValue';
		public var bar: String = 'barValue';
		public var baz: Number = 42;
 
		public function toString(): String
		{
			return '[ComplexObject foo=' + foo + ', bar=' + bar + ', baz=' + String(baz) + ']';
		}
	}
}

Le résultat d’un trace(instance) est plus intéressant :

[ComplexObject foo=fooValue, bar=barValue, baz=42] // drôlement plus clair

Voilà tout ce qu’il y a à savoir sur trace(). On oubliera pas avant de livrer l’application au client de désactiver les trace(). Ca se fait dans Fichier > Paramètres de publication > Flash

Pourquoi omettre les trace() à la publication finale ? Ces instructions sont présentes dans le .swf final. C’est une nanoseconde de gagnée, un bytecode en moins, autant dire presque rien, mais c’est plus propre.

Utiliser le debugger

Breakpoints & pas à pas

On a vu que trace() existe, est simple et efficace, mais peut vite devenir verbeux et constitue une vraie instruction qui est publiée dans le .swf. C’est du debugging intrusif dans un certain sens.

L’IDE Flash CS4 est pourtant doté d’un débugger, un vrai. Qui permet d’afficher en un clic le contenu de la mémoire à un instant donné.

Ouvrons un fichier en mode éditeur de code, par exemple TutorielDebug.as. Un clic droit, et sélectionnons “basculer le point d’arrêt”, par exemple à la ligne 54. Un petit point rouge apparaît. C’est un point d’arrêt, ou “breakpoint” qui est le nom d’usage courant.

Maintenant on oubliera à l’avenir la combinaison ctrl+entrée, pour ne plus utiliser que ctrl+shift+entrée. Lançons le debuggage par ctrl+shift+entrée.

Ô miracle, l’IDE affiche le debbuger, le vrai. Mais les fenêtres sont vides. Notre breakpoint est dans le handler de clic, cliquons donc sur play :

Ô deuxième miracle :

  • le Flash Player se met en carafe, en réalité il est en pause,
  • la fenêtre “Console de débogage” affiche le nom de la fonction dans laquelle nous sommes arrêtés,
  • la fenêtre “Variables” se peuple des variables locales et globales courantes.
  • notre breakpoint s’orne d’une petite flêche jaune qui signifie “t’es là mon coco, j’attends la suite”.

Nous venons de quitter le monde de l’artisanat (instruction trace()) pour celui du vrai débuggage.

Pour l’instant, tout semble planté. Pour naviguer dans ce mode une fois que l’application est arrétée sur un breakpoint, on utilise les icônes de navigation de la console de débogage :

On a 5 icônes :

  • Continuer: passe le breakpoint, sort l’application de sa pause et continue l’éxecution.
  • Arrêter: arrête le débogage. On doit toujours cliquer là, et jamais fermer brutalement le Flash Player. C’est une habitude à prendre.
  • pas à pas normal: va mettre en évidence chaque ligne de code exécutée à partir de ce breakpoint, mais sans rentrer dans le code des fonctions appelées,
  • pas à pas détaillée: va mettre en évidence chaque ligne de code exécutée à partir de ce breakpoint, en rentrant/ouvrant le code des fonctions appelées,
  • quitter le pas à pas: bugge totalement…

A ce stade, on clique sur Continuer, l’exécution normale reprendre. On reclique sur le bouton Play, l’application s’arrête à nouveau - on clique cette fois-ci sur un des pas-à-pas au choix :

On voit que la petite flêche a avancé. On continue à cliquer ainsi, et la petite flêche continue d’avancer, un clic = une ligne de code exécutée.

Arrivé à la fin de la fonction, ligne 56, l’application sort de son état de pause pour reprendre son fonctionnement normal.

Le panneau Variables

C’est l’outil le plus puissant, puisqu’il affiche directement lors d’un breakpoint/pas à pas tout le contenu de la mémoire. C’est en réalité ce qu’on cherche à faire usuellement à grands coups de trace(). Lançons l’appli et observons son contenu lors de l’arrivée sur le breakpoint déclenché par le clic.

On voit que tous les objets en cours d’existence sont listés :

  • this: notre application,
  • e: l’Event passé au clic, qui est donc une variable locale.

Nous pouvons plonger dans l’arborescence et afficher chaque propriété de ces objets :

Voilà qui remplace de manière très avantageuse l’usage que nous faisions de trace(). Un breakpoint, un coup d’oeil dans le débugger, et voilà le travail. Et en plus, en cliquant sur une valeur…

… on peut la modifier à la volée. Avec un outil aussi puissant, nous voilà paré pour toute notre phase de développement, reste à assurer nos arrières lorsque l’application sera online.

Gérer les bugs lors de la phase de production

On a omitté les trace(), qu’on utilise presque plus maintenant qu’on a (re?)découvert l’usage du débugger, le projet est online. Malheureusement notre poupin stagiaire qui a effectué le déploiement a oublié le fichier .mp3, c’est le drame.

Lorsqu’on clique sur play, l’application freeze, chez le client, l’application est figée, sans aucun message. Chez nous, nous voyons clairement l’erreur grâce au Flash Player Debug, mais faisons comme si non on la voyait pas :

  • recompilons de suite une application en cochant la case “Autoriser le debug” et décochons ”Omettre les trace()”,
  • on place ceci sur le serveur distant,
  • on clique sur “Commencer la session à distance” dans le menu “Déboguer”, le débugger apparaît et se place en attente
  • dans un navigateur dûment équipé du Flash Player Debug, on lance le site
  • miracle, une session de debug tout à fait classique se lance correctement, bien que le fichier soit distant.
  • nous pouvons réparer cette erreur grossière, haha, sacré stagiaire.

Pour aller plus loin...

Ce tutoriel n’a pas pour objet les techniques avancées, de toute façon dans l’IDE Flash CS4 les outils sont maigres. Néanmoins le debugger se comporte correctement et mérite d’être utilisé. Ses principes d’usages (breakpoints/pas à pas/panneau Variables) sont ceux qu’on retrouve dans toutes les plate-formes de développement existantes et constituent donc un savoir transverse qu’il est bon d’acquérir vite.

Il existe de très bons débugger externes à Flash, ou plutôt de bons utilitaires de logging (Arthropod http://arthropod.stopp.se/, Monster Debugger http://demonsterdebugger.com/, etc).

Sous Flash Builder, le debugger est autrement plus sophistiqué.