Month: October 2007

Merci Google de m’avoir fait économiser de l’argent

Posted by – October 29, 2007

Je prends 4 points d’un coup (sic) :

PageRank Actuel

malgré un très faible nombre de backlinks.

Je suis donc heureux de ne pas avoir eu à dépenser mes sous (je ne l’aurais de toute façon jamais fait) pour être référencé sur des blogs ou sites à fortes audiences, bien que je comprenne la motivation de ces derniers.

Valtech days 2007 : agilité, RIA, Web 2.0

Posted by – October 28, 2007

J’ai assisté mardi 23 octobre à la 1ère1 journée des Valtech days 2007 sur le thème de l’agilité (méthodes [XP, Scrum], outils). Un résumé des sessions auxquelles j’ai pu assister.

Test Driven Requirements: Introduction et perspectives (Gilles Mantel)

Le principe de base fût tiré du Toyota Production System ou le lean. Dans ce système, la satisfaction client est mis en avant, chaque employé est dans l’absolu responsabilisé, il se doit d’alerter et d’arrêter la ligne de production dès qu’une anomalie est détectée afin de la corriger, et de ne commander que ce qui est utile, autrement dit s’il existe un besoin réel. Ces principes ont été adaptés au développement logiciel (lean software development).

Tout le long du développement, la chasse aux gâchis est le leitmotiv de toute conduite de projet et développements : tout ce qui n’apporte pas de valeur ajoutée au client est considéré comme un gâchis. Pour cela, dès le début du cycle de développement du logiciel, toute anomalie est corrigée. Cette dernière peut-être détectée très tôt grâce au développement ou les exigences pilotés par les tests.

Exemples de gâchis :

  • cycles de corrections/livraisons successifs
  • signature des exigences
  • tests manuels de non-régression
  • informations provenant de la discussion initiale avec la MOA (des exemples concrets aboutissent à des tests).

Dans un cycle itératif normal ou conventionnel (dans le sens ce qu’applique tout le monde à 80 %), on trouve : exigences (CDC) -> spécifications -> conception/développement -> tests unitaires -> tests fonctionnels -> recette et validation de la version.

Dans la logique lean, le test est introduit dès les exigences, et dans toutes les phases du cycle du projet. Pour la conception et développement, des outils sont nécessaires pour améliorer le processus (Wiki, usine logicielle), et automatiser notamment tout ou partie les tests : FIT apporte une solution2 aux tests fonctionnels. fitnesse, quant à lui intègre FIT et un Wiki (équipe = collaboratif). On parlera aussi de greenpaper

Conclusion

Tout cela apporte des bénéfices sur la qualité du code , la diminution du risque de bugs et que le développement effectué colle bien au besoin exprimé. Il est très conseillé de se faire accompagner pour la mise en place d’une approche agile, ces méthodes formant un tout. Des mutations organisationnelles et professionnelles seront également à prévoir, autrement dit, changer ses habitudes pour en acquérir de nouvelles. L’équipe (un terme fort) prend toute sa place ici, sous réserve que chaque membre ait une forte compétence en conception et une assez bonne expérience en développement objet.

Le Refactoring : la solution agile pour conserver un code évolutif (Régis Médina)

Un mot que j’aime bien : le refactoring (ou appelé également revamping). Session présentée sous forme de démonstration, par Régis MEDINA, ou comment à partir d’un code existant (Java, Swing), le refactorer proprement (IDE Java utilisé : IntelliJIDEA).

Le refactoring n’est qu’une brique d’XP, l’ensemble des briques forment un tout. Le refactoring sert à réduire la complexité du logiciel sur le long terme. Lors de la production de code, on assiste à un phénomène inhérent à tout produit qui croit : la difficulté de maintenance, et surtout la question d’évolutivité du logiciel : rendre plus simple le développement de toute évolution dans le logiciel, que cela soit par l’auteur ou part toute personne susceptible de toucher au code.

Les différentes phases du refactoring d’un code :

  • safe delete
  • rename
  • extract
  • inline
  • move
  • change signatures
  • factory

Principes pour la suppression des duplications :

  • identifier ce qui est commun (on trouve souvent l’acronyme : DRY : éviter la redondance de code).
  • identifier ce qui change
  • concevoir l’interface

Conclusion

la conception est centrée sur l’existant, des compétences en conception sont demandées au développeur, le travail en équipe reste primordial.

Agilité: à monter soi-même… (Laurent Bossavit)

Le conférencier est ouvertement opposé à UML, trop compliqué à son goût3.

L’adoption d’une méthode agile peut s’effectuer de 2 manières :

  • en sous-marin, sans soutien des instances dirigeantes : cas le plus difficile et le moins propice à son adoption
  • adoption sous forme de projet pilote : le scénario idéal, on se fera dans ce cas accompagner par un professionnel.

Plusieurs risques à l’adoption d’une méthode agile :

  • adoption en bloc : difficultés d’apprentissage, logique de performance, choc culturel
  • adoption “une pratique à la fois” : pas forcément optimale, car une pratique est compréhensible dans son ensemble (XP, Scrum forment un ensemble de pratiques, qui rendues indépendantes deviennent moins pertinentes).

Introduire une notion de délais reste très mauvais psychologiquement (“stress”), on parlera plus volontiers de vélocité d’un projet (compréhension, refactoring, tests).

Comme dans la session TDD / TDR, les tests sont primordiaux dès le début, et automatisés, ainsi que la notion de travail en équipe.

Quelques livres4 :

  • “La 5ème discipline”, Peter Senge
  • “The logic of failure”, Dietrich Droner

Conclusion

le bon sens, tiré de mon expérience, veut que l’on s’oriente sur ces méthodes. Introduire des tests [automatisés] s’avère une très bonne chose. Cela nécessite une relation moins MOE/MOA au sens fournisseur/utilisateurs (avec le mur des spécifications signées très tôt) mais plus une relation de partenaires, client et maîtrise d’oeuvre ont le même objectif : sortir un logiciel qui rendra service aux utilisateurs et répondra au service attendu. Se faire accompagner reste la seule solution à mon sens, la mise en oeuvre requière énormément de bouleversement du point de vue technique (conception, outils) que organisationnelle (changement des habitudes et des processus).

Web 8.3 ou l’avenir du web (Xavier Paradon)

Après un résumé des technologies mises en oeuvre dans le cadre de projet Web 2, et une critique toute justifiée sur l’abus de langage souvent employé lorsque l’on parle de site Web 2.0, l’orateur a fini sur une conclusion intéressante mais discutable.

Conclusion5

La tendance pour l’avenir du RIA serait d’extraire les applications du navigateur pour les faire fonctionner sur le poste de travail, on en reviendrait à des clients Adobe AIR, Silverlight, ou autre JavaFX. La concurrence est rude, et Adobe a une avance non négligeable sur ce domaine.

Intégrer les APIs Google Maps dans une application WinForm .NET (Jean-Louis Vidal)

Objectif : sous forme de démonstration, coder une application fenêtrée (winform .NET), qui appelle Google Maps, afin détablir des chemins de parcours à la Défense.

Le contrôle WebBrower est utilisé pour embarqué le navigateur dans l’application. La clé Google Maps est utile dès lors qu’on commence à utiliser des recherches d’adresses par exemple. Cette clé gratuite permet 50 000 hits / jour, dans le cas d’un plus grand besoin, il devient nécessaire d’obtenir une licence commerciale de Google Maps (à titre d’exemple, pour 1,5 M hits, la licence tourne autour de 195 k€).

Astuce pour une communication entre .NET et le JS : utilisation de webbrowser.Document.InvokeScript(“fctJS”,args).

Conclusion

La démonstration fut très intéressante, car les objets Javascript manipulés restent simples et accessibles, l’API fournie par Google est riche et permet un grand nombre de fonctionnalités.

Apports de la journée

Cette journée pose les bases des bonnes pratiques pour la mise en oeuvre de projets, et de leur développement. Dans mon organisation, le travail s’effectue en équipe, afin d’entretenir la plateforme (au sens “maintenabilité” et “évolutabilité”), car nous sommes proche du travail d’un éditeur de solution, ou le projet se déroule sur du long terme. Dans ce cas, le quick & dirty est à proscrire, et l’application de bonnes pratiques reste primordiale (voir le billet sur la notion de projet “maintenable” et évolutif).

[EDIT] d’autres blogs qui en parlent, notes, photos, un site vient d’ouvrir dédié à l’événement : Wiki des journées

1 je n’ai pu assister aux 2 journées, la 2ème étant baptisée Openspace, qui se voulait ouverte, les thèmes étant élaborés par les participants.

2 framework opensource, disponible dans différents langages.

3 on ne peut le blâmer. Personnellement, UML se résume souvent aux use cases et quelques schémas de classes pour parler la même langue que l’équipe.

4 J’en rajoute un : “Le mythe du mois-homme”, Frederick P. Brooks

5 à l’heure où j’écris ces lignes, un 4ème concurrent vient d’entrer en lice : Prism de Mozilla

Paris on Rails édition 2007 : inscriptions ouvertes

Posted by – October 23, 2007

C’est ici, 70 € au lieu de 100 € si inscription avant le 15 novembre.

J’avais bien aimé l’édition 2006, mais il faudra que j’achète un MacBook pour cette édition ;)

smtp, dns, listes : des communautés d’experts

Posted by – October 16, 2007

Depuis de nombreuses années, je suis abonné à une multitude de listes de diffusion sur le serveur du CRU qui aborde un tas de sujets passionnants.

3 listes retiennent mon attention, par leur contenu techniquement élevé et riche d’expertise, je ne peux que conseiller, si le sujet vous intéresse, de vous y abonner ou au moins de parcourir les archives :

  • smtp (archives)
  • dns (archives)
  • sympa (archives) : un coup de coeur pour ce moteur de listes ;) : le CRU distribue environ de 600 000 à 1 million de mails par jour, rien que pour ça, ça mérite d’être cité.

Bonne lecture.

^([Rr]ege(x)+[^X]p{0,1}|Regexxxxp?)$

Posted by – October 15, 2007

Un ex-collègue se posait des questions concernant la meilleure manière de rédiger une expression régulière, pour une utilisation avec des règles de ré-écritures d’URL1. Une regexp2 est tout sauf générique, une regexp du type

~/.*/.*/(.+)$ 

n’est pas suffisamment précise pour répondre sans ambiguité aux URLs suivantes :

  • http://localhost:3431/protection-solaire/capital-soleil/LPPM0001 redirection vers http://localhost:3431/product.aspx?codeProduct=LPPM0001
  • http://localhost:3431/nav/about/about.aspx sera redirigée vers l’URL précédente, mais il ne le faudrait pas.

En dehors de tout contexte, on se doit d’introduire un motif discriminant dans une regexp, afin de rendre le résultat déterministe et sans ambiguité.

Quelques exemples, regex => redirection :

  • /?espaces/([\\w\\-_\\.]+)/?$ => /reseau/accueil/default.aspx?res=[resid[$1]] (ex. d’URL à rediriger : http://localhost/espaces/web)
  • /?e/a/(\\d+)(/([\\w\\d\\-\\.]+)?)?$ => /reseau/accueil/default.aspx?res=$1&ccinettoken=$3 (ex. d’URL appelée à rediriger : http://localhost/e/a/34)
  • /?e/c/(\\d+)(/([\\w\\d\\-]+)?)?$ => /cciemploi/PresentationOffres/AfficheOffre.aspx?OffreId=$1&ccinettoken=$3 (ex. d’URL appelée à rediriger : http://localhost/e/c/12928/c35-hg89-kj356)
  • /?e/r/(\\d+)/(\\d+)(/([\\w\\d\\-]+)? )?$ => /reseau/ressources/AfficheRessource.aspx?res=$1&ressId=$2&ccinettoken=$4 (ex. d’URL appelée à rediriger : http://localhost/e/r/34/154674)
  • /?e/f/(\\d+)/(\\d+)(/([\\w\\d\\-]+)?)?$ => /reseau/fic_action/consult.aspx?res=$1&id=$2&ccinettoken=$4

Les motifs qui rendent unique la redirection sont :

  • /e ou /espaces : on va dire la racine pour ce type d’URL
  • /a, /c, /r, … : la sous-catégorie pour ce type d’URL
  • la suite, càd la regexp, représente une règle métier, autrement dit, la page de redirection avec ses paramètres pour cette catégorie et sous-catégorie de pages.

Parce qu’une regexp mal écrite peut s’avérer catastrophique, on la testera avec une liste exhaustive de cas d’utilisation.

Ok, c’est bien, mais quel est l’intérêt ? J’en vois principalement 3 :

  • dans le cas d’un site indexé, permettre d’indexer les mots contenus dans l’URL plutôt que des chiffres (id bien souvent).
  • avoir des URLs qui sont faciles à retenir par l’humain (http://monsite/espaces/web reste mieux que http://monsite/reseau/accueil/default.aspx?res=7887)
  • avoir des URLs courtes pour réduire le risque de coupure dans les mails (URLs contenus dans une newsletter par exemple), certains lecteurs font la césure à 76 caractères.

Quelques ressources : http://del.icio.us/zorky/regex

[EDIT] coupure Noos (Numéricable) toute la journée (blog & co inaccessible). Conclusion : changer de FAI, direction Free.

1 avec des modules (HttpModules) du type UrlRewriter ou celui-ci. Sous Apache, le module mod_rewrite permet également de faire de belles choses.

2 les expressions régulières sont bien la seule chose à ma connaissance qui soit à peu près standard et que l’on peut retrouver dans n’importe quel langage [sérieux] : Perl, Ruby, .NET, Java, …

Evolutions d’un logiciel ou d’un produit : votes en ligne

Posted by – October 14, 2007

Intéressé par phpmyvisites1, j’ai pu voir que les auteurs avaient mis en place un site dédié aux demandes d’évolutions, et plus spécifiquement, orienté feedback. J’avais déjà vu cette méthode sur CodePlex : soumettre les demandes d’évolutions aux votes des utilisateurs.

Ce type de solution peut être clairement bénéfique, lorsque l’on voit la difficulté de décider de telle ou telle évolution sur un produit : laquelle sera la plus légitime, cohérente, utile, pertinente…

On rend ainsi la responsabilité aux utilisateurs de décider, et d’arbitrer les choix. Cela les implique aussi, se sentant plus concernés par le produit.

Vive la démocratie, produit à essayer, une bonne idée à tester.

1 la version 2.3b4 intégre un plugin d’analyse de zones chaudes. Fonction qui peut être utile pour l’analyse des clics des visiteurs, afin d’optimiser au mieux sa disposition de page.

Communautés photos (Canon)

Posted by – October 13, 2007

Deux communautés que je visite souvent, pour des échanges (objectifs, techniques, appareils, commentaires photos). La photo étant un domaine tout aussi large que l’informatique, c’est toujours un réel plaisir d’avoir les conseils et points de vue d’experts :

Concernant les communautés en ligne, Flickr est sans conteste l’idéal pour l’hébergement photos, pour les raisons suivantes :

  • rapport qualité/prix (24,95 $ /an !) pour du illimité
  • communautés
  • API : permet notamment d’avoir ce type de site ou tout autre jouet pour mettre en avant vos photos
  • l’ergonomie et l’offre Flickr pour gérer vos photos

Vu sur blogasty, un comparatif Flickr vs. Picasa Web . Pour avoir testé Picasa Web, il est loin derrière Flickr, pour le prix déjà, mais aussi pour l’absence Web 2.0 (communautés & co).

C’est d’actualité (<sarcasme>faut s’y préparer…</sarcasme>) : ma carte ADN pour Flickr…et il y a même une partie “égo surf”, pour ceux qui seraient intéressés ;)

C# : Sérialisation Xml et Hashtable

Posted by – October 11, 2007

La sérialisation est un merveilleux mécanisme qui permet notamment :

  • de conserver l’état d’un objet (persistance) à l’instant T.
  • de transférer des données (par services web [Ajax, SOAP, REST, ...], ou des transferts de bas niveau (Remoting, …))

La sérialisation peut revêtir plusieurs formats : XML, JSON, YAML, binaire, …selon la technologie utilisée (.NET, Java, Ruby, Prototype, …).

.NET supporte en natif la sérialisation (XML notamment), ce qui permet de prendre une photo de ses objets et de les conserver en base (ou dans un fichier selon), pour peu que vos classes soient marquées par l’attribut [Serializable].

Imaginons maintenant que vous utilisiez dans une classe une Hashtable pour stocker une suite de noms / valeurs, la sérialisation XML de cette classe devient impossible en raison de l’implémentation de IDictionary de la classe Hashtable.

Classe qu’on aimerait avoir :

 [Serializable] public class ServiceParams { #region IServiceParams Members private string _action; public string Action { get { return _action; } set { _action = value; } } private Hashtable _dico = new Hashtable(); public Hashtable ParamsService { get { return _dico; } set { _dico = value; } } #endregion }  

La sérialisation d’un objet de ce type provoquera une erreur : “The type System.Collections.Hashtable is not supported because it implements IDictionary”.

Afin d’éviter cela, une technique, si l’on souhaite utiliser une Hashtable avec la sérialisation en XML (XmlSerializer) : introduire une classe qu’on nommera SerializableHashtable qui implémente l’interface IXmlSerializable et qui utilise un objet intermédiaire (mapp la Hash sur celui-ci) sérialisable (List<Node>).

L’interface IXmlSerializable permet d’avoir des méthodes ad-hoc pour spécifier comment sérialiser (WriteXml) ou désérialiser (ReadXml) l’objet.

Ce qui donne :

 using System.Collections; using System.Collections.Generic; using System.Xml; using System.Xml.Serialization; [Serializable] public class ServiceParams : IServiceParams { #region IServiceParams Members private string _action; public string Action { get { return _action; } set { _action = value; } } private SerializableHashtable _dico = new SerializableHashtable(); public SerializableHashtable ParamsService { get { return _dico; } set { _dico = value; } } #endregion } // optionnel, une interface toute personnelle public interface IServiceParams { /// <summary> ///     Le discriminant si besoin /// </summary> string Action { get;set;} /// <summary> ///     Paramètres /// </summary> SerializableHashtable ParamsService { get; set;} } /// <summary> ///     Classe qui permet de sérialiser une hashtable grâce à une List<Node> /// </summary> [Serializable] public class SerializableHashtable : Hashtable,    IXmlSerializable { private XmlSerializer xs = new XmlSerializer(typeof(List<Node>)); public SerializableHashtable() { } /// <summary> ///   La classe qui mappera la Hashtable /// </summary> [Serializable] public class Node { public Node() { } public Node(string k, object v) { key = k; val = v; } public string key; public object val; } #region IXmlSerializable Members /// <summary> ///     Sérialisation ///     on parcourt le Hashtable pour stocker clé+valeur dans List<Node> ///     on sérialise List<Node> /// </summary> /// <param name="writer"></param> void IXmlSerializable.WriteXml(System.Xml.XmlWriter writer) { List<Node> list = new List<Node>(); foreach(string key in this.Keys) list.Add(new Node(key, this[key])); xs.Serialize(writer,list); } public System.Xml.Schema.XmlSchema GetSchema() { // TODO:  Add SerializableHashtable.GetSchema implementation return null; } /// <summary> ///     Désérialisation ///     on déséralise List<Node> ///     on parcours List<Node> et on construit le Hashtable /// </summary> /// <param name="reader"></param> void IXmlSerializable.ReadXml(System.Xml.XmlReader reader) { reader.Read(); List<Node> list = xs.Deserialize(reader) as List<Node>; if(list == null) return; for (int i = 0; i < list.Count; i++) { Node node = list[i] as Node; this.Add(node.key, node.val); } } #endregion }  

On est maintenant prêt à gérer ses Hashtable sérialisables.

 using System.IO; using System.Xml; using System.Xml.Serialization; //... public void maSuperMethod() { XmlSerializer _serializer = new XmlSerializer(typeof(ServiceParams)); ServiceParams myParams = new ServiceParams(); myParams.Action = "DoIt"; myParams.ParamsService.Add("id","10"); myParams.ParamsService.Add("libelle","mon objet"); // sérialisation StringWriter strw = new StringWriter(); XmlTextWriter sw = new XmlTextWriter(strw); sw.Formatting = Formatting.Indented; _serializer.Serialize(sw, myParams); sw.Close(); string xml = strw.ToString(); // désérialisation ServiceParams _params = (ServiceParams)_serializer.Deserialize(new StringReader(xml)); }  

L’objet sérializé myParams, stocké dans xml donnera le résultat suivant :

 <?xml version="1.0" encoding="utf-16"?> <ServiceParams xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"> <Action>DoIt</Action> <ParamsService> <ArrayOfNode> <Node> <key>libelle</key> <val xsi:type="xsd:string">mon objet</val> </Node> <Node> <key>id</key> <val xsi:type="xsd:string">10</val> </Node> </ArrayOfNode> </ParamsService> </ServiceParams>  

Dans l’absolu, on pourrait sérialiser la Hashtable en utilisant le BinaryFormatter. Dans ce cas, le résultat ne donnerait pas du XML, et donc, il deviendrait difficile (à la main) de modifier les valeurs…cela peut bien évidemment arriver. XmlSerializer reste un bon compromis pour ce type d’utilisation.

Livre PDF gratuit… : “Build your own Ruby on Rails Web applications”

Posted by – October 11, 2007

ici

Il vous reste…50 jours pour le télécharger.

UTF-8 : linux, windows, mac, everything, everywhere

Posted by – October 9, 2007

Hier, un ami m’a demandé un coup de pouce pour déboguer un problème d’appel Ajax qui ne fonctionnait pas sous IE (alors que sur la page de démo cela marchait, et sur FF également, damned !) : champ de saisie, propositions de mots, autrement dit de l’autocomplétion.

Voyant les caractères renvoyés par la requête Ajax, c’est à dire des ”?” ou tout autre caractère ésotérique, ni une ni deux, l’origine fut trouvée : l’ISO-8859-1. A défaut, l’usage de la fonction utf8_encode a été la parade pour convertir la donnée à la volée.

La majorité des librairies Ajax (Prototype par exemple) ont un encodage par défaut à UTF-8 (et c’est bien !).

Une parade c’est bien, prendre l’habitude d’utiliser l’UTF c’est mieux. C’est la norme actuelle et future, fini les codespages à n’en plus finir. Tout logiciel sérieux devrait le gérer, on trouve encore trop souvent l’usage de l’encodage ISO-8859-1 (ou 8859-15 pour les windowsistes). Autant que faire se peut (un lourd existant peut l’empêcher par ex.), l’usage de l’UTF devrait être naturel.

Quelques trucs et astuces afin d’obtenir sur la majeure partie de la chaine de production une compatibilité UTF-8 :

  • pour le Web, cela passe par un document enregistré en utf-8, et un charset à utf-8 :
 <meta http-equiv="Content-type" content="text/html; charset=utf-8" />  
  • sous Apache, la directive AddDefaultCharset utf-8 peut s’avérer utile
  • un équivalent en ASP.NET pour forcer l’encodage de sortie, ou d’entrée, dans la section du web.config, la directive globalization :
 <globalization requestEncoding="utf-8" responseEncoding="utf-8"/>  
  • accès SSH : fixer sous puTTY l’UTF-8 (Windows / translation)
  • Debian : installer les locales qui vont bien et les positionner à UTF-8 (un excellent article pour Unix) :
 $ locale : affiche les locales pour le terminal $ dpkg-reconfigure locales : pour installer et fixer la locale par défaut $ export LC_ALL=fr_FR.UTF-8 pour fixer manuellement  
  • vim : un :set fileencoding vous indiquera si vous enregistrez en UTF, ou vous permettra de fixer l’encodage du fichier.
  • iconv sera votre compagnon pour la convertion de fichiers ISO-8859-1 en UTF-8
  • mysql >= 4.1 gère l’UTF en natif. Un “SET NAMES utf-8” indique l’encodage d’échange entre le client et le serveur. MySQL 5.0 charsets et collations (MySQL 4.1)
  • SQL Server : ntype (nvarchar, ntext, …) est ton ami

Quelques ressources que j’ai pu glaner sur le Net.

Ami PHPiste, Rubyiste, Javaiste, .NETiste, Perliste, kayakiste (euh non), à bon entendeur…