19 juillet 2005

Classe de debug

Je suppose que la plupart des codeurs ont leur classe de debug. Voici la mienne, a peine commencée. Il s'agit uniquement d'un dump d'un objet. La méthode un objet recursivement pour afficher l'ensemble de ses propriétés. Il gère également le fait qu'on ait pu mettre le nom de la classe dans une variable statique (par défaut __className).

/**
* Debug
* @version 0.1
* @package com.lalex.utils
*
* @author <a href="http://www.lalex.com/">LAlex</a>
* @since 2005-07-19
*/

class com.lalex.utils.Debug {
        /**
        * Property used to store class names
        */

        public static var classNameProperty:String = "__className";
        /**
        * Trace an object detailled content
        * @param o Object to display
        */

        public static function dump(o) {
                _global.trace(dumpToString(o));
        }
        /**
        * Return a string containing the object content. Recursive method
        * @param o Target object
        * @param d Depth. Used to generate tabs
        */

        private static function dumpToString(o, d:Number):String {
                d = d ? d : 0;
                var dp:Number = d;
                var sp:String = "";
                while (d-- > 0) {
                        sp += "  ";
                }
                if (typeof o == "object") {
                        var ret:String = "[";
                        if ( o["__constructor__"][classNameProperty] ) {
                                ret += o["__constructor__"][classNameProperty];
                        } else if (o instanceof Array) {
                                ret += "Array";
                        } else {
                                ret += "Object";
                        }
                        ret += "
"
+ sp;
                        for (var p in o) {
                                if (typeof p != "function") {
                                        ret += p + ": " + dumpToString(o[p], dp+1) + "
"
+ sp;
                                }
                        }
                        ret += "]";
                        return ret;
                } else {
                        return o.toString();
                }
        }
}

Une suite à cette classe est prévue, avec pitet' même une petite surprise... ;)

::Télécharger Debug01.zip::

12 juillet 2005

Flash Player 8 public beta

Beaucoup de boulot, pas de temps pour un commentaire. :)
http://www.macromedia.com/software/flashplayer/public_beta/

23 juin 2005

XMath : plus de maths !

Pour mes besoins en calculs mathématiques, certaines fonctions ou optimisations m'étaient nécessaires. C'est pourquoi j'ai crée la classe XMath, qui aurait du a priori étendre la classe Math. Seulement, la classe Math étant composée uniquement de propriétes et de méthodes statiques, l'héritage se faisait mal, et m'obligeait à jongler entre les classes XMath et Math...

Mais c'était sans compter sur le __resolve que j'ai appliqué sur ma classe, me permettant ainsi de ne manipuler qu'une seule classe.

La voici. Evidemment, comme toujours, je suis ouvert à toute proposition d'amélioration! ;)
/**
 * Extended Math class
 * @class XMath
 * @version 0.1
 * @author <a href="http://www.lalex.com/">LAlex</a>
 * @since 2005-06-22
 * @about The class is dynamic to be able to use __resolve...
 */

dynamic class com.lalex.math.XMath {
        // Cosinus and sinus of round values in degree
        private static var __COS:Array = new Array();
        private static var __SIN:Array = new Array();
        // 2*PI
        // Can be used for radians modulos
        private static var __2PI:Number = 2*Math.PI;
       
        /**
        * "Simple" cosinus
        * @param n Round value in degrees
        * @return Cosinus of the degree value, with 2 decimals
        */

        public static function simpleCos(n:Number):Number {
                return __COS[n];
        }
        /**
        * "Simple" sinus
        * @param n Round value in degrees
        * @return Sinus of the degree value, with 2 decimals
        */

        public static function simpleSin(n:Number):Number {
                return __SIN[n];
        }
        /**
        * Return 2*Math.PI value
        */

        public static function get PI2():Number {
                return __2PI;
        }
        /**
        * Initilisation of the XMath static properties
        */

        private static function __init() {
                for (var i:Number = 0 ; i<360 ; i++) {
                        __COS[i] = Math.round(Math.cos(Deg2Rad(i))*100)/100;
                        __SIN[i] = Math.round(Math.sin(Deg2Rad(i))*100)/100;
                }
        }
        /**
        * Launch initialisation
        */

        private static var __initSinCos = __init();
        /**
        * Convert a degree value to radians
        * @param deg Degree value
        * @return Radian value
        */

        public static function Deg2Rad(deg:Number):Number {
                return deg*Math.PI/180;
        }
        /**
        * Convert a radian value to degrees
        * @param rad Radian value
        * @return Degree value
        */

        public static function Rad2Deg(rad:Number):Number {
                return rad*180/Math.PI;
        }
        /**
        * Return a modulo of a value
        * @param a Numeric value
        * @param mod Modulo (optional) Default 360
        * @return value >=0 and <mod
        */

        public static function modulo(a:Number, mod:Number):Number {
                if (!mod) {
                        mod = 360;
                }
                return ((a%mod+mod)%mod);
        }
        /**
        * Return a numeric value with a defined number of decimals
        * @param n Numeric value
        * @param d Number of décimals (default 0)
        * @return "Rounded" value
        */

        public static function roundTo(n:Number, d:Number):Number {
                switch(d) {
                        case 2:
                                return Math.round(n*100)/100;
                        case 1:
                                return Math.round(n*10)/10;
                        case 0:
                        case undefined:
                                return Math.round(n);
                        default:
                                var puis:Number = Math.pow(10, d);
                                return Math.round(n*puis)/puis;
                }
        }
        /**
        * Return the property or method of the Math class
        * if not found in the XMath class
        */

        private static function __resolve(p:String) {
                if (typeof Math[p] == "function")
                        return function() { return Math[p].apply(null, arguments); }
                else
                        return Math[p];
        }       
}
Utilisation :import com.lalex.math.XMath;
trace(XMath.simpleCos(120)); // 0.5
trace(XMath.cos(XMath.PI2)); //0

::Télécharger XMath01.zip::

16 juin 2005

Classe Vector : pourquoi ne pas faire la meilleure ?

De nombreux codeurs ayant besoin d'agir sur un environnement visuel ont tous à leur actif une classe Vector. De nombreuses fonctionnalité géométriques bien utiles peuvent être implémentées dans cette classe.

Mais je suis sûr que chaque codeur a implémenté quelques astuces et/ou fonctionnalités auxquelles personne n'a pensé. Ce que je propose ici, c'est que ceux qui le veulent bien nous fassent partager leur expérience à ce propos.

Voici l'interface (pas interface AS hein, juste la liste des signatures de mes méthodes) de la classe que j'utilise personnellement. Si vous avez des idées pour l'enrichir, je suis sûr que ca fera plaisir à beaucoup de monde... ;)
Vector {
        // Constructeur
        // Peut prendre deux nombres
        // ou deux points (vecteurs) qui forment un vecteur
        public function Vector(x, y);
        // Accesseurs
        public function get x():Number;
        public function set x(x:Number);
        public function get y():Number;
        public function set y(y:Number);
        // Accesseurs "virtuels"
        // Coordonnées polaires
        public function get size():Number;
        public function set size(s:Number);
        public function get angle():Number;
        public function set angle(a:Number);
        // Déplacement
        // Peut prendre deux nombres (coordonnées)
        // Ou un vecteur (utilise les coordonnées du vecteur)
        public function moveTo(x, y:Number);
        // Opérations
        public function sum(v:Vector):Void;
        public function sub(v:Vector):Void;
        public function scalar(v:Vector):Number;
        // Transformations
        public function translate(v:Vector):Void;
        public function scale(r:Number):Void;
        public function rotate(a:Number):Void;
        // Utilitaires
        // Vecteur normal (taille 1)
        public function getNormal():Vector;
        // Distance entre deux points
        public function getDistanceTo(v:Vector):Number;
        // Point d'arrivée du vecteur partant de v
        public function getEnd(v:Vector):Vector;
        // Clone
        public function clone():Vector;
        // Copie d'un autre vecteur
        public function copyFrom(v:Vector):Void;
        // Debug
        public function toString():String;
}

Ce type de classe utilise par contre une ambiguité bien pratique entre la notion de point et la notion de vecteur. En effet, un point n'est rien d'autre que l'extrémité d'un vecteur partant de l'origine... :)

Je pense créer une classe SimpleVector, qui utiliserait des angles entiers, en degrés, histoire d'optimiser les calculs... Voir un système de cache pour les coordonnées polaires...

Je pense aussi à créer une classe EventVector, qui permettrait de diffuser des évenements pour toute modification effectuée dessus...

13 juin 2005

Déménagement du devblog

Le devblog se refait une petite beauté, et en profite pour s'approprier un sous-domaine rien que pour lui : http://blog.lalex.com/. L'interêt ? Ben presque aucun, sauf que ca va faciliter le référencement en tant que site indépendant de la partie plus personnelle de mon site, et me permettre pourquoi pas de proposer autre chose sur www.lalex.com. ;)

Le plus important à noter pour les quelques uns qui continuent à lire malgré le vide qui s'est emparé de ce site reste le changement d'URL des feeds RSS :

PHP 5.1.0 beta : ca promets !

Une première version de PHP 5.1.0 beta vient d'être publiée dans les snapshots. Au programme, des fonctionnalités qui simplifient la vie, et qui sont donc les bienvenues :

  • L'intégration par défaut de la librairie PDO : en gros, un accés uniformisé à tous types de base de données. Je ne l'ai jamais utilisée, mais ca faisait partie de ce que je voulais utiliser pour un projet à venir, donc bonne nouvelle pour moi ! :p
  • Une amélioration des performances grace à un optimisation de la gestion de la mémoire
  • La librairie PCRE 5.0, histoire de s'amuser encore un peu plus avec les expressions régulières (euh... rationnelles : qwix, si tu me lis ! :mrgreen:)
  • Des améliorations au niveau des flux, des webservices (SOAP) et de SPL (librairie standard de PHP, fortement inspirée d'une partie de l'API Java)
  • Le support natif de l'Unicode, pour les "international coders" ! 8)

Par contre, toujours aucune info sur l'extension PECL php_treads, qui continue d'apparaître dans les extensions proposées au niveau des snapshots, alors que de nombreux développeurs réclament à corps et à cris une explication sur la présence de ce module... :\ Wait and see. :o

A noter qu'une branche PHP 4.4 est également ouverte pour une question de compatibilité entre le Zend Engine 1 et les extensions de PHP 4.3...

6 juin 2005

Maelstorm (Flash player 8) : Macromédia communique...

Macromedia se décide enfin à communiquer sur la prochaine version de son player autrement que par le biais de conférences : codename Maelstorm. En effet, une page lui est dédiée sur le site de l'éditeur.

On y apprend que le player gère l'upload... question a laquelle je n'avais obtenu qu'une réponse "vaguissime" de Mike Chambers lors du FlashFestival... YES ! 8) J'ai juste un peu peur, parce qu'ils parlent également de download de fichiers... En gros, j'ai bien peur qu'on ne puisse pas envoyer tout ca à PHP, et donc qu'on ne puisse avoir un traitement commun pour d'éventuelles versions Flash et HTML du même formulaire... :o

Par contre, toujours aucune annonce claire sur l'arrivée ou non d'un nouveau langage. Je dois avouer que j'ai bien du mal à concevoir que l'AS2 n'ai pas évolué... :( Enfin, l'espoir fait vivre! :P

A suivre donc... :)

1 juin 2005

FlashFestival 2005 : le retour...

J'ai tellement de choses à dire sur ce week-end que je n'en mettrai que peu :

Une organisation que j'imagine enorme, qui nous a offert un festival de vraie qualité! Bravo Guylaine! 8) Et merci pour ton invitation qui m'a réellement beaucoup touché!

Pour rester sur l'organisation, bravo également à DickRivers "The DICK", ElectroFrog et David! Votre gentillesse n'a d'égal que votre investissement dans le bon déroulement de cet évènement (et c'est pas peu dire!). :)

Des codeurs aussi cordiaux que doués. mama, ce fut un réel plaisir de te rencontrer et d'échanger avec toi ces quelques discussions sur bien des sujets. Je crois qu'on est bien restés sur le thême du festival à ce niveau ! :D JL, j'espère bien qu'on se recroisera bientôt, et que tu te seras mis à la POO ! :mrgreen:

For Jared : I think than your code is just like you : simple person, but huge feelings. It was a great moment to code at your side, but also to share a little part your world during those two days!!! I hope we'll can meet again soon, you and your so kind Laurie... ;)

Un cadavre exquis des plus géniaux!!! Ca paraît incroyable de voir ce que des codeurs peuvent avoir comme styles de programmation différents. Et pourtant, chez chacun le résultat est là, et pas qu'un peu!

Des artistes brillants, qui ont développé chez moi un autre regard à poser sur la démarche artistique en général, avec un profond désir de m'y atteler moi-même... Axé sur l'exposition de soi sur la toile, je crois que le thème me touche de trés prés... :$

Des intervenants bien trop modestes !!! :P Quand j'entend un dunun me dire qu'il "fait ce qu'il peut" et que c'est pas grand chose, je trouve ca trés touchant!

Une équipe MediaBox en force! Ravis d'avoir découvert les têtes que je ne connaissais alors qu'en avatar! Vous êtes tous des killers les gars! 8)

Un Mike CHAMBERS un peu décevant dans sa présentation de Flash 8. :( Discours commercial et préformaté, aucune réponse claire aux questions que j'ai pu lui poser, un sentiment qu'il existe plein de choses qu'il ne faut pas nous dire... M'enfin, il parait de source sûre qu'il est pas si froid que ca: je comprends parfaitement qu'il est bien obligé de suivre le discours imposé par MM... :roll:

Bref, je crois que vous aurez compris que j'ai passé un trés, trés, trés, trés bon week-end ! :P

Je n'attends plus maintenant que d'avoir les vidéos/photos/DVDs histoire de graver ca dans mon disque dur, bien qu'une grande partie soit déjà gravée dans ma mémoire! :)

Bon, c'est pas tout ça, mais ca m'a bien motivé pour re-flashouiller un peu plus tout ca! :p

13 avril 2005

Montée au Flash Festival 2005

J'ai été invité par l'oganisation du Flash Festival à participer en tant qu'invité au Cadavre Exquis de Code qui aura lieu le Dimanche 29 Mai. Autant dire que c'est pour moi un immense honneur d'y prendre au part, aux côtés de ceux que je considère comme étant des pointures de la programmation Flash en France, soit Mama de Yamago, et Jean Louis Gaujal de Flash-France... ainsi qu'un codeur que j'admire depuis bien longtemps : Jared Tarbell de Levitated. Autant vous dire que je m'y rends avec la plus grande humilité, et un trac non dissimulé en espérant être à la hauteur d'autant de talent. :$

Le FlashFestival propose également d'élire les meilleures animations dans 6 catégories, par un jury qui n'est pas en reste enb terme de talent, avec entre autre Ankama (créateurs de Dofus), Vooz (créateurs de Pucca), et bien d'autres... Vous découvrirez toutes les infos nécessaires sur le site officiel : http://www.flashfestival.net/... Si vous désirez y prendre part en tant que participant, dépêchez vous d'envoyer votre contribution, il ne reste que 7 jours avant la date de cloture, soit le 20 Avril à minuit !!! :o

Ci-dessous, la description officielle de ce qu'est le cadavre exquis de code :Le cadavre exquis de code aura lieu dimanche 29 mai de 11h à 18h au Centre Pompidou (-1). Quatre Art codeurs créeront en commun un code de programmation pour générer une oeuvre esthétique graphique. Quatre ordinateurs passent de main en main, chaque artiste poursuit l'oeuvre de son prédécesseur. Démarche d'ordinaire personnelle, la programmation échappe au développeur puis lui revient. Quatre projets communs sont ainsi créés.

Le résultat du Cadavre exquis de code sera montré lors de la soirée de clôture du festival
Voilà ! LAlex content ! :mrgreen:

25 janvier 2005

PostgreSQL 8.0 : bonne nouvelle

Pour ceux qui n'auraient pas encore eu la bonne idée de rajouter le blog de Liguorien à leurs bookmarks, je reprend une de ses infos en signalant la sortie de PostegreSQL 8.0. En plus de fonctionnalités dignes des plus grandes bases de données, PostgreSQL offre maintenant un portage natif sur Windows. Reste la possibilité de créer des triggers en C, Perl, Tcl, Python, et même en PHP grâce à plPHP ou en Java.

Pour les fanatiques de phpMyAdmin, il est à signaler que PostgreSQL offre le même type d'outil, nommé phpPgAdmin.

Pour l'avoir utilisé en remplacement d'Oracle pendant un moment, je ne peux que vanter les performances et les fonctionnalités de PostgreSQL ! :)

14 janvier 2005

mysqli : le bonheur de la POO avec MySQL 4.1

Comme beaucoup le savent, PHP5 propose une nouvelle extension pour MySQL 4.1, qui offre le gros avantage de pouvoir programmer ses requêtes soit de manière "standard" (old-style), soit en POO.

Jugez plutôt de la différence:
AVANT:<?
        $cnx = mysql_connect("localhost", "lalex", "lalex");
        mysql_select_db("lalexdb", $cnx);
        $rst = mysql_query("SELECT * FROM messages", $cnx);
        while($cur = mysql_fetch_array($rst)) {
                echo $cur["sujet"];
        }
        mysql_free_result($rst);
        mysql_close($cnx);
?>
APRES :<?
        $cnx = new mysqli("localhost", "lalex", "lalex", "lalexdb");
        $rst = $cnx->query("SELECT * FROM messages");
        while($cur = $rst->fetch_object()) {
                echo $cur->sujet;
        }
        $rst->close();
        $cnx->close();
?>

C'est-y pas mieux comme ca ? :P

13 janvier 2005

De retour sur la toile

Me voici de retour sur le net !!! 8) De nombreux changements sont intervenus dans ma vie depuis l'interruption forcée de ce ces derniers mois.

Je suis maintenant employé par une société de formation, en tant que prof d'informatique : développement, bases de données et bureautique... et également pour développer une activité création de sites Internet. Ironie du sort, j'enseigne à des BTS Informatique de Gestion, donc un niveau Bac+2, alors que je n'ai pas obtenu moi-même un Bac+2 (de manière "conventionnelle") ! :mrgreen:

Cette société me permet même de travailler en free à côté, me procurant un moyen de travailler bien pratique lorsque l'on a pas spécialement envie de subir les contraintes du statut d'indépendant ! :)

Pour l'instant en plein développement de l'Intranet de la société, j'ai eu l'occasion de choisir mes technologies serveur, et vais donc pouvoir développer une application complète avec PHP 5 et MySQL 4.1 ! 8) Donc, à venir des infos sur mes trouvailles concernant ces deux technologies récentes, difficiles à trouver ensemble dans le cadre d'un hébergement ! ;)

J'ai aussi découvert qu'il existe une vie en dehors d'Internet, dont je compte bien profiter de manière plus intense : il se peut donc que les mises à jour de ce blog soient moins fréquentes qu'auparavant, et que ma fréquentation des différentes communautés du web que j'arpentais précédemment soit moins soutenue ! :$

Pour finir, je dirais que bien qu'étant frileux au départ, je ne peut que me féliciter d'avoir choisi 9 Telecom comme provider : en effet, il a suffit de deux semaines pour que ma ligne soit ouverte et le modem reçu. Je n'en suis qu'au début de mon installation informatique (étant obligé de configurer un routeur logiciel sur un serveur), mais la connexion "simple" s'est faite en deux temps trois mouvements, et le support semble trés disponible ! :)

A plus donc ! ;)

3 novembre 2004

Misère numérique

Aprés un très long mois d'Octobre, empetré dans les cartons et la peinture jusqu'au cou, j'amènage tant bien que mal dans mon nouvel appartement niçois. Du coup, je me retrouve coupé du monde numérique jusqu'à ce que ma connexion ADSL soit mise en route. En attendant, je me contenterai de connexions trés rares avec un modem 56K, voire quelques tours dans un cyber café. :( J'ai bien failli en déprimer, mais la perspective de l'ADSL2+ de free (pdf) (15Mb/1Mb) me fait dire que ca vaut le coup d'attendre un peu ! :mrgreen:

Je devrais avoir pas mal de boulot en Flash durant ce mois-ci, ce qui devrait alimenter ce blog lors de mon retour sur la toile. A trés bientôt donc ! 8)

27 octobre 2004

MySQL 4.1 stable (production) disponible

Alors que je commencais à en désespérer, une version stable de MySQL 4.1 est enfin prête, avec le numéro de version 4.1.7 !!! Avec une tendresse toute particulière pour la possibilité de faire des sous-requêtes, et une extension objet de PHP5 optimisée pour MySQL 4.1. Sans oublier les performances revues à la hause ! ;)

Vous pouvez foncer le télécharger sur le site officiel (ou aller lire le communiqué officiel pour en savoir plus)! 8)

19 octobre 2004

Super, pas vraiment synonyme de performances

Vaut-il mieux utiliser super pour surcharger une méthode sans la modifier ? Abordant le sujet avec petepx et ekameleon, c'est bien ce que je croyais, mais piqué dans ma curiosité, j'ai entrepris de faire quelques benchs.

La question est donc : si je veux accéder à une méthode héritée, vaut-il mieux la surcharger, et appeler explicitement la méthode de la classe mère avec super, ou laisser faire la parcours de la chaine de prototypes ? J'ai tout d'abord cru que lui dire où aller était bien plus rapide, étant donné que la langage n'a alors pas besoin de le chercher par lui-même ...

Mais trève de discussions, voici les classes qui m'ont servi a faire mes benchs. J'ai bien fait attention à utiliser le même nombre de lettres pour les différentes classes de même niveau, car pour ceux qui ne le savent pas encore, dans Flash, plus les noms de variables sont courts, plus ils sont efficaces en terme de performances :/** Classe mère */
class CClass {
        private static var myProp:Number = 0;
        public function testMethod() {
                myProp++;
        }
}
/** Classe fille sans surcharge */
class CChild extends CClass {
}
/** Classe fille avec surcharge */
class SChild extends CClass {
        public function testMethod() {
                super.testMethod();
        }
}
/** Lancement des benchs */
var loop:Number = 50000;
var tim:Number;
// Sans super
trace("Sans super");
var o1:CChild = new CChild();
tim = getTimer();
for (var i=0 ; i<loop ; i++) {
        o1.testMethod();
}
trace("Temps : " + (getTimer()-tim) + "ms.");
// Avec super
var o2:SChild = new SChild();
trace("Avec super");
tim = getTimer();
for (var i=0 ; i<loop ; i++) {
        o2.testMethod();
}
trace("Temps : " + (getTimer()-tim) + "ms.");
La sortie de ce code n'a pas manqué de m'étonnerSans super Temps : 1204ms. (en moyenne entre 1175 et 1225) Avec super Temps : 1535ms. (en moyenne entre 1525 et 1550) Avec une génération supplémentaire, c'est encore plus prononcé. Alors que les performances sans super ne semblent pas très affectées, celle avec super se dégradent considérablement :/** 3ème génération sans super */
class CGrandChild extends CChild {
}
/** 3ème génération avec super */
class SGrandChild extends SChild {
        public function testMethod() {
                super.testMethod();
        }
}
/** Lancement des benchs */
var loop:Number = 50000;
var tim:Number;
// Sans super
trace("Sans super");
var o1:CGrandChild = new CGrandChild();
tim = getTimer();
for (var i=0 ; i<loop ; i++) {
        o1.testMethod();
}
trace("Temps : " + (getTimer()-tim) + "ms.");
// Avec super
var o2:SGrandChild = new SGrandChild();
trace("Avec super");
tim = getTimer();
for (var i=0 ; i<loop ; i++) {
        o2.testMethod();
}
trace("Temps : " + (getTimer()-tim) + "ms.");

La sortie est plus qu'éloquente :Sans super
Temps : 1285ms. (en moyenne entre 1275 et 1305)

Avec super
Temps : 1947ms. (en moyenne entre 1925 et 1950)

Donc, il vaut mieux laisser le soin à Flash de trouver la bonne méthode plutôt que de le lui indiquer clairement. Quel manque de reconnaissance !!! :mrgreen:

PS : Par la même occasion, j'ai découvert que super.super.testMethod() n'est pas autorisé ! Encore un des mystères de super ! ;)

12 octobre 2004

Fonctions globales et ciblage

Depuis quelques temps, j'ai décidé de ne plus utiliser le this pour le ciblage de mes méthodes et propriétés à l'intérieur d'une classe. Ca paraît plutôt logique, et c'est une pratique tout à fait répandue dans d'autres langages OO. Seulement, lors du codage de mes classe d'intervalles, je me suis rendu compte que le ciblage posait quelques problèmes sur des noms de méhodes globales, renseignées dans le fichier toplevel.as ... C'est d'ailleurs pour cela qu'on retrouve des this.stop() dans ces classes.

En effet, si ma classe contient une méthode stop(), et que je l'appelle sans le this, il semble que ce soit la fonction globale qui soit appellée (en tout cas, pas celle de la classe) ... Pourtant, si je compare stop (sans ciblage) à this.stop, il me retourne bien une égalité ! 8O. Voyez plutôt :class TestStop {
        function TestStop() {
                trace("TestStop instance created");
                trace("--------------------");
        }
        function stop() {
                trace("stop method called");
        }
        function testScope() {
                stop();
                trace("Global stop ? " + (stop == _global.stop));
                trace("--------------------");
                stop.call();
                trace("Class' stop ? " + (stop == this.stop));
        }
}
/** Code de test */
var tst:TestStop = new TestStop();
tst.testScope();
/* Sortie
************
TestStop instance created
--------------------
Global stop ? false
--------------------
stop method called
Class' stop ? true
*/

Bizarre non ? :o

Job raté ... le mieux est l'ennemi du temps ?

Cette boîte était la boîte de rêve. Jeune, des réalisations superbes, un niveau technique trés avancé, une déco classe et moderne, qui fait penser que l'ambiance de travail est toute aussi agréable.Une société qui avait su se tourner vers l'Internet avant les autres, et avait ainsi réussi à tirer son épingle du jeu. Pas trés dur pour eux, quand on voit ce que fait la concurrence dans la région comparé à la grande qualité de leur travail. Bref, pour moi, un des rares sociétés du département dans laquelle j'avais une chance de trouver un boulot de Flasheur qui en vaille vraiment la peine.
Ce poste, il était pour moi. 8) Par excés de confiance, je n'ai jamais imaginé une seule seconde passer à côté.

Entretien trés cordial, face à trois des responsables, d'ailleurs forts sympathiques. On me dit que mes compétences ne sont même pas à mettre en cause, car elles se voient au travers de mon blog. Mon ego serre les dents pour ne pas trop se faire entendre. Je me vois déjà intégrer l'équipe, avec un supérieur qui semble vraiment trés symap.

C'est alors que la principale inquiétude de mes interlocuteurs m'est annoncée : je veux trop bien faire !!! Ben oui, les Design Patterns, la POO ciselée au scapel, c'est pas le genre de la maison : ca prend trop de temps, et les impératifs de production et de livraison sont là. Il faut alors expliquer que non seulement, à force de pratique, faire un design OO bien clean ne prend pas vraiment plus de temps, car les habitudes de conception deviennent quasi-instinctives et également qu'il faut parfois savoir perdre un peu de temps sur une design, pour nous faire gagner ensuite une quantité phénoménale de temps sur les prochains développements. La POO lorsqu'elle veut être des plus abouties a de nombreux avantages, mais fait encore peur aux agences. :o

Ja n'ai pas du convaincre. Ils ne m'ont jamais rappelé, pas même pour me dire ce qui n'allait pas. Et moi, j'ai les boules. :(

TimeInterval : gestion des intervalles de temps

Comme je le précisais dans mon précédent post, je suis en train de m'attaquer au redéveloppement de certaines classes fournies par Macromedia. Cela commence par la fameuse OnEnterFrameBeacon, fournissant un point d'accés central à l'évenement onEnterFrame de MovieClip. La seule différence entre ma version et celle de MM est son nom, (devenue pour l'occasion FrameBeacon, c'est bien suffisant :P), l'utilisation de EventDispatcher, et la création d'un constructeur privé, histoire d'être bien sûr qu'on ne puisse pas l'instancier. ;)

Viennent ensuite les classe de type ITimeInterval que sont MSInterval et FrameInterval.

Ces deux classes servent à gérer des intervalles de temps, soit en millisecondes, soit en nombre de frames. Elle diffuse régulièrement un évenement onTime à ses écouteurs. Le but est ici d'uniformiser l'execution d'instructions à intervalles réguliers, comme cela peut exister avec un setInterval. L'utilité de ces classes réside dans plusieurs points :

  • Une interface commune, permettant de modifier facilement à l'execution le type d'intervalle.
  • La possibilité d'executer un évenement toutes les n frames, comme c'est le cas en millisecondes avec setInterval.
  • La possiblité de définir un nombre maximum d'itérations de l'intervalle
  • La possiblité d'arrêter un intervalle en cours de route, et de le reprendre où il en était
  • La possibilité de synchroniser plusieurs instructions en leur attribuant la même instance d'un intervalle

Voici un exemple d'utilisation :import com.lalex.transitions.*;
class Diaporama {
   private var _itv:ITimeInterval;
   // Constructeur et méthodes ...
   // Si un intervalle existait déjà, on l'arrete et on le désabonne
   public function setInterval(itv:ITimeInterval) {
      if (_itv != null) {
         _itv.stop();
         _itv.removeListenerEvent("onTime", this);
      }
      _itv = itv;
      _itv.addListenerEvent("onTime", this);
   }
   public function onTime() {
      nextImage();
   }
   public function start() {
      _itv.start();
   }
}

/** Utilisation */
var diapo:Diaporama = new Diaporama();
diapo.addImage("image1.jpg");
diapo.addImage("image2.jpg");
// On crée un intervalle de 500 ms.
var ms:ITimeInterval = new MSInterval(500);
// La même instruciton pour changer d'image toutes les 20 frames
// var ms:ITimeInterval = new FrameInterval(20);
diapo.setInterval(ms);
diapo.start();

A noter que pour obtenir l'équivalent d'un onEnterFrame, il suffit de créer un FrameInterval sans paramètre (ou avec 1 en premier paramètre).

Le seul probleme important vient du fait que les destructeurs ne sont pas gérés, et qu'un delete d'une instance non stopée peut laisser tourner un processus orphelin ... :\

La classe Tween utilisant les intervalles de temps viendra prochainement ... ;)

::Télécharger TimeInterval.zip::

11 octobre 2004

BroadcasterMX : une hérésie !

Actuellement en train de recoder "maison" certaines classe fournies par Macromédia (principalement mx.transitions.Tween et mx.transitions.OnEnterFrameBeacon), j'ai encore du mal à comprendre pourquoi la classe BroadcasterMX est utilisée ... :\

En effet, il existe toujours son ancêtre historique du nom de AsBroadcaster (attention aux majuscules :P). Cette classe, présente depuis Flash 5, a l'immense avantage d'être native au player, codée en C (ou autre langage compilé), et donc bien plus performante !!! Son successeur est quant-à lui codé en AS2 (donc en bytecode interprété). Etant donné qu'il n'existe strictement aucune différence de fonctionnalité, pourquoi faire le sacrifice de l'éfficacité ??? :o

Quoi qu'il en soit, depuis pas si longtemps que ça, je suis devenu bien plus adepte du modèle EventDispatcher, dont je me sers dans les nouvelles classes que je publierai ici-même dans trés peu de temps ... 8)

9 octobre 2004

Strucutures de données : Grid et HashTable

J'entame un petit package 'data' qui contiendra différentes structures de données parfois bien utiles. L'idée m'est venue du besoin d'une HashTable, que j'avais eu l'occasion de manipuler durant mes quelques aventures avec Java. J'en ai ainsi profité pour refaire la classe Grid que vous connaissez déjà peut-être ...

Pour ceux qui n'ont pas la chance de la connaitre, la classe HashTable correspond à l'utilisation d'un tableau, sauf que les clés n'ont pas de contrainte et peuvent être de n'importe quel type, contrairement au tableau qui a besoin de clés numériques, ou au tableau associatif qui a besoin de clés alphanumériques. Il s'agit donc d'un "simple" système d'association clés/valeurs.
import com.lalex.data.*;
var ht:HashTable = new HashTable();
var k1 = new Date();
var k2 = ["un", "tableau", "comme", "clé"];
ht.put("clé", "valeur");
ht.put(k1, "date");
ht.put(k2, ["un", "tableau", "comme", "valeur"]);
trace(ht);
/** Sortie
[ clé => valeur
  Sat Oct 9 14:14:53 GMT+0200 2004 => date
  un,tableau,comme,clé => un,tableau,comme,valeur ]
*/

// Récupère un élément
trace("k2 : " + ht.get(k2));
/** Sortie
k2 : un,tableau,comme,valeur
*/

// Supprime un élément
ht.remove(k2);
trace(ht);
/** Sortie
[ clé => valeur
  Sat Oct 9 14:14:53 GMT+0200 2004 => date ]
*/
La classe Grid, quant à elle, est un simple tableau à deux dimensions, agrémenté de quelques méthodes assez pratiques. ;)import com.lalex.data.*;
var gr:Grid = new Grid(2,3);
gr.fill(1,2,3,4,5,6);
trace(gr);
/** Sortie
[[1 , 2]
 [3 , 4]
 [5 , 6]]
*/

// Inverse la grille
gr.reverse();
trace(gr);
/** Sortie
[[1 , 3 , 5]
 [2 , 4 , 6]]
*/

// Met tous les éléments de la grille au carré
gr.map(function(n) { return n*n; });
trace(gr);
/** Sortie
[[1 , 9 , 25]
 [4 , 16 , 36]]
*/

::Télecharger data.zip::

- page 5 de 15 -