Désinformation journalistique ou comment mal faire son travail

Je vous parlais récemment de la venue de Richard Stallman à Toulouse.

Un gentil journaliste vient de publier cet article dans l’équivalent toulousain du 20 minutes parisien (un journal gratuit) :

Le papa de Linux en visite

Le Culte, club des utilisateurs du libre à Toulouse et environs, va inaugurer le 10 juillet sa nouvelle salle des machines en présence de Richard Stallman, considéré comme le père des logiciels libres. Ce dernier a commencé à s’intéresser au sujet lorsqu’il travaillait au laboratoire d’intelligence artificielle du MIT, avant de mettre au point une alternative au système d’exploitation payant comme Windows, et de créer un système gratuit : Linux. Une conférence publique aura lieu à 15 heures à l’université Paul-Sabatier.

Avant de publier des articles lus par autant de monde, ne pouvait-il pas se donner la peine de vérifier ou au moins de faire relire ces 4 (!) lignes par des gens qui auraient pû immédiatement lui expliquer que RMS n’avait nullement écrit Linux, mais que c’était Linus Torvalds ? Ça lui aurait évité d’avoir l’air idiot devant un certain nombre de personnes…

RMS a eu un rôle certes non négligeable, il a lancé le projet gnu, écrit gdb, emacs, est bien le père des logiciels libres, mais n’a pas écrit Linux.

Le C++ c'est facile, mais...

Quand on a des gros plantages en C++ on cherche toujours du coté des pointeurs mal initialisés ou des dépassements d’espaces mémoire. Or voila une petite liste d’erreur qui saute moins au yeux (donc plus difficiles à debugger) mais dont l’effet est tout aussi destructeur:

  • Utiliser le constructeur par copie pour copier un objet de classe Polymorphe:
Object* y=new ObjectDeriv;
...
Object* x=new Object(*y);

=> l’appel au constructeur par copie n’est pas le bon Pour éviter de tomber dans ce piège ou que d’autres y tombent en utilisant votre code, mettez le constructeur par copie privé.

  • Faire un tableau d’objets d’une classe dérivée et l’utiliser comme tableau d’objet de la classe de base:
void f(Object *tab,int size){
 int i;
 for(i=0;i<size;++i)
 // manipulation de tab[i];
}
...
ObjectDeriv tab[10];
f(tab,10);

Dans ce cas, le décalage effectué lors de l’accès à tab[i] est eronné.

Plus classique : oublier de surcharger le constructeurs par copie, l’opérateur operateur= et du destructeur dans une classe contenant des pointeurs.

  • Oublier de mettre virtuel le destructeur dans une classe qui peut être dérivée.
  • Dans les classes contenant des pointeurs : oublier de vérifier les auto-affectations dans l’operateur=.
const Object& operator= ( const Object& o){
    delete pt;
    pt=new PtType;
    pt=o.Pt;
}

Dans le cas d’une auto-affectation (o==*this), le pt=o.pt va échouer car o.pt est déjà libéré. Dans ce cas 2 solutions :

  • Vérifier l’auto affectation :
if( this==&o )
  return o;
  • Sauvegarder le pointeur:
  PtType* tmp=pt;
  pt=new PtType;
  pt=o.Pt;
  delete tmp;

Si vous avez d’autres erreurs du style, que vous avez planché dessus pendant des heures et que vous voulez faire par de votre expérience n’hésitez pas…

RMS à Toulouse

Oui, oui, vous ne rêvez pas, Richard M. Stallman vient à Toulouse dans 10 jours. Il est invité par le Club des Utilisateurs du Libre de Toulouse et des environs.

Le programme de sa venue est indiqué plus en détail sur le site en lien ci-dessus. Je vais tout faire pour essayer d’y aller et je ferai des photos :-).

Pour ceux qui ne savent pas qui est RMS, eh bien en gros c’est monsieur GNU et FSF. Le concept même de logiciel libre, c’est lui. Il fait des conférences dans le monde entier sur le sujet. Et le samedi 10 juillet, il va en faire une à 5km de chez moi…

Geek, moi ?

Bonnes pratiques de programmation en Java

Aujourd’hui, on va parler de best practices (ou bonnes pratiques en bon françois) de programmation en Java. On parlera entre autre des quelques classes de l’API fonctionnellement dépréciées, on parlera aussi d’évolutivité et d’héritages abusifs, le tout encadré de design patterns.

Les classes interdites

Je rencontre encore sur le net certains projets qui utilisent encore les 2 classes suivantes (cette liste n’est certainement pas exhaustive, mais ces deux là sont les plus courantes) :

  • Hashtable
  • Vector

Vous ne devez pas utiliser ces classes. Elles ne sont toujours présentes que pour assurer une compatibilité ascendante : la jvm 1.4 doit pouvoir faire tourner un programme écrit en 1.0 qui peut contenir des objets de ce type puisque leur alternative n’est apparue que pour la version 1.2.

Depuis la 1.2 donc, il ne faut plus les utiliser. Mais alors pourquoi, vous allez me dire, est-ce qu’ils n’ont pas déprécié ces classes à partir de la 1.2 ? C’est très simple : hashtable est une table de hâchage (une liste de clé-valeur) et Vector une classe qui gère une liste d’objets… C’est à dire des objets extrêmement courants et utilisés. Sun a donc décidé de ne pas les déprécier pour éviter plusieurs centaines voire milliers de lignes de warning à la compilation de projets développés à l’époque du jdk 1.2.

pourquoi ne pas les utiliser ?

Ces classes sont synchronisées, elles sont ce qu’on appelle thread-safe. Cela signifie que dans un environnement contenant plusieurs fils de processus, si vous utilisez ces objets, vous vous garantissez une cohérence de leurs données, ce qui ne serait pas le cas si elles n’étaient pas synchronisées.

Le problème c’est que cette fonctionnalité est loin d’être utilisée dans tous les projets, on n’utilise pas forcément ses objets dans un contexte concurrentiel partout (encore heureux). En terme de performances, cette synchronisation n’est pas gratuite, on peut même dire qu’elle est plutôt chère (on parle communément d’un rapport de 1 à 5). Vous vous rendez alors bien compte qu’utiliser un Vector pour stocker vos listes est le plus souvent une perte totalement inutile de performances.

Les alternatives

Mais alors donc quelles classes utiliser en remplacement ? Celles-ci, leurs équivalents non thread-safe :

  • ArrayList pour Vector
  • HashMap pour Hashtable
Et si je veux un conteneur thread-safe ?

Si vous avez pensé à poser cette question, bravo. Dans un environnement concurrentiel, il faut toujours synchroniser les objets d’une façon ou d’une autre… Il y a deux solutions pour ce faire :

Synchronisation aux endroits où c’est nécessaire en utilisant un conteneur non synchronisé

  • Avantage : Gain possible en performances car vous maîtrisez parfaitement la synchronisation de votre code ;
  • Inconvénient : Plus difficile parce que vous devez faire très attention de ne pas faire d’oubli dans cette synchro si vous ne voulez pas obtenir des résultats au mieux bizarres, au pire catastrophiques.

Utilisation de conteneur synchronisé :

  • Avantage : Il suffit de se concentrer une bonne fois sur le codage du conteneur et ensuite on peut l’utiliser sans crainte de créer des inconsistences à l’exécution ;
  • Inconvénient : Perte possible de performance parce qu’il va peut-être y avoir des synchronisation à des endroits où ce n’est pas nécessaire.

Heureusement, vous vous dites, il existe donc Vector pour les cas où on veut utiliser un conteneur _thread-safe_. Et bien non, vous pouvez jeter cette classe, vous-n’en-aurez-plus-besoin :-). À la place, utilisez la méthode statique Collections.synchronizedList. Vous obtiendrez ainsi une liste synchronisée à partir d’une qui ne l’est pas, en appliquant de plus l’important principe qui consiste à cacher les implémentations dont je vais maintenant parler.

Améliorer l’évolutivité du code

Masquer l’implémentation

Ce qui fait que beaucoup (trop) d’utilisations de Vector subsistent encore aujourd’hui, c’est que cette classe était utilisée partout sans être masquée par une classe ou une interface.

Depuis la version 1.2, Vector implémente l’interface List comme le font ArrayList et LinkedList. Lorsqu’on utilise une liste, il ne faut donc plus indiquer à l’extérieur qu’on utilise telle ou telle implémentation mais il faut simplement indiquer qu’on utilise une classe qui implémente l’interface List. En faisant systématiquement comme ça, vous vous laissez la possibilité de changer d’implémentation ultérieurement. S’il vous prend par exemple l’envie de ne plus utiliser une ArrayList mais une implémentation personnelle de List pour telle ou telle raison, personne ne le saura et tout le reste du code restera inchangé (et ça, c’est très important).

Les factory

Utilisez des factory pour créer vos objets. Vous pourrez ainsi facilement cacher une implémentation.

Exemple : Pouet doit pouvoir dire bonjour

public interface Pouet
{
  /**
   * Affiche bonjour à l'écran
   */
  public void sayBonjour();
}

Très bien, la première chose à faire est donc d’écrire une implémentation de Pouet :

public class PouetImpl implements Pouet
{
  public void sayBonjour()
  {
     System.out.println("Bonjour");
  }
}

Si vous ne faites que ça, les utilisateurs de votre classe n’auront pas d’autre choix que d’écrire

PouetImpl pouet = new PouetImpl();

Et s’ils sont un petit peu plus expérimentés

Pouet pouet = new PouetImpl();

Et ils utiliseront Pouet et non PouetImpl partout dans leur code, mais ce n’est pas forcément bon parce que vous laissez d’autres que vous faire des choix de méthode d’utilisation de votre code. Autant que faire se peut, il doit toujours y avoir un minimum de possibilité pour faire quelque chose, sinon vous vous exposez à de gros problèmes de maintenance…

Et s’ils le sont encore plus, ils pourront avoir envie d’utiliser un framework de découplage, communément appelé conteneur léger en opposition avec les conteneurs d’EJB beaucoup plus intrusifs et lourds à mettre en oeuvre, comme spring, PicoContainer ou Avalon qui permettent d’utiliser de simples POJOs.

Ou alors, il écriront eux-mêmes la factory que vous auriez dû fournir :

public final class PouetFactory
{
  public Pouet createPouet()
  {
     return new PouetImpl();
  }
  /**
   * Singleton pour cette factory.
   */
  public static PouetFactory getFactory()
  {
     if(pouetFactory==null)
     {
        pouetFactory = new PouetFactory();
     }
     return pouetFactory;
  }
  private static final pouetFactory;

  private PouetFactory()
  {
  }
}

Ici, on aura pris soin de faire 3 choses :

  • fournir une méthode statique getFactory() ou getInstance() ;
  • mettre un constructeur private pour interdire l’instanciation de la factory par du code extérieur ;
  • mettre la classe final pour empêcher sa dérivation.

Vous voyez bien ici que si j’ai envie d’utiliser autre chose que PouetImpl, personne ne le saura si j’ai bien contraint à utiliser correctement mon code (en mettant par exemple la classe PouetImpl protected si c’est possible afin d’éviter qu’elle soit instanciable par un autre objet que ceux du package). Je pourrai librement changer d’implémentation en impactant le moins de code possible.

Héritage abusif

Dans la série du code anti-évolutif, mettons au top les dérivations excessives. Qui n’a jamais dérivé une JFrame pour afficher une pauvre fenêtre qui n’a rien de plus que la JFrame d’origine ? Et bien non, vous devez déléguer dans la plupart des cas. C’est à dire encapsuler l’objet que vous utilisez et fournir une méthode getComponent() renvoyant un Component par exemple pour le fournir à l’extérieur.

On ne décide pas de faire une dérivation à la légère, ce choix de conception doit être motivé par le fait que l’objet que vous voulez est une variante de la classe dont vous souhaitez hériter. Si ce n’est pas le cas, il y a de fortes chances pour que vous ne deviez pas hériter mais plutôt déléguer.

Ça ira pour aujourd’hui

Voilà, ce sera tout pour aujourd’hui. J’ai encore d’autres trucs dont je veux parler. Il faudra que j’en trouve le temps, ce qui n’est pas gagné. J’ai envie de vous parler de DAO, de commons-logging, de JNI … Bref, encore de quoi dire pleins de choses :-).

Si vous n’êtes pas d’accord avec certains points ou que vous souhaitez des éclaircissements, les commentaires sont là pour ça :-).

L'orthographe, eh j'men fous chui en vacances

Cette phrase, je l’ai tant entendu qu’elle me donne des nausées… J’ai l’impression que c’est un peu l’excuse bidon qu’on donne quand on est un peu jeune. C’est aussi celle que je m’attends à recevoir de ceux qui osent poster des sentences du genre de celle qui va suivre.

Quand je parlais de l’orthographe et que je vous disais que rien ne va plus… Sans aller jusqu’à l’extrême suffisance dont fit preuve notre étudiant modèle en trackbackant cybercodeur (je vous laisse retrouver le fil, j’ai pas envie de linker vers ce pauvre type, François pour vous aider), suscitant ainsi un torrent de critiques bien méritées, je dois avouer que j’ai véritablement eu mal aux yeux en voyant ça :

“que ce ne soit pas qu’un effet d’anonce destiné à faire un appel du pier à une certaine sociétée américaine”

Je vous laisse trouver où cette phrase a été écrite …

Je trouve regrettable de faire aussi peu d’effort quant à l’utilisation du français. Je veux bien admettre que ce n’est peut-être pas aussi facile pour tout le monde. Toutefois, à moins d’être hautement dyslexique, il n’aurait pas été si difficile d’écrire la phrase ci-dessus sans fautes. Même Syl y parviendrait :-) !

J’ai un petit frère comme ça, il a toujours un surnom MSN à se tirer une balle. Tout à l’heure, il s’appelait XXX qui ai crevé (non, il n’a pas crevé un pneu de sa voiture, il n’en a pas, il est fatigué quoi :-)). Pourtant dès que je lui signale, il dit “Ah oui ! Merci !”… Il s’en fout, c’est tout, il s’en contrefout et c’est bien dommage parce qu’il ne pourra jamais se débrouiller seul, comme beaucoup, pour écrire des lettres officielles sans se faire relire par ses proches…

Alors pensez y, faites un petit effort tous les jours pour vous mêmes mais aussi dans le respect de ceux qui vous lisent.

La petite souris... Ken Brown vs le reste du monde

Malgré l’effort de mat de chez totalementcrétin pour m’aider dans ma tâche de traduction, personne ne s’est proposé…

C’est pas grave, j’ai donc continué tout seul. Le blog me semblait quelque peu inapproprié pour ce travail, j’ai donc choisi de mirrorer complètement les pages concernant Ken Brown du site de Tanenbaum et de les traduire toutes…

Mais où donc les ai-je mises ? Ben sur mon site, ici quoi.

Comme vous le verrez, ces pages ont donc la même charte graphique que la version anglaise (normal, c’est la même CSS). La différence, c’est ce que c’est maintenant du XHTML 1.0 (fallait au moins ça :-D).

Il y a 4 articles, les 3 premiers sont entièrement traduits :

  • Le premier a déjà été publié sur ce billet, il a donc été relu quelques fois ;
  • Les deux suivants sont bruts de décoffrage. Comme j’ai pas mal de travail en dehors de ces traductions et que je n’ai pas trop le courage de relire tout de suite, je vous laisse le soin de m’indiquer les éventuelles fautes de tout type qui peuvent subsister afin d’améliorer ensemble le document ;
  • Le quatrième le sera au fur et à mesure. J’en ai déjà fait environ 1/4, si quelqu’un veut m’aider à le finir, je serais heureux de recevoir sa contribution et d’ajouter son nom au bas de la page :-).

Je suis bien entendu prêt à ajouter tout lien vers des traductions ou toute page html que vous m’enverriez concernant l’affaire. J’aimerais par exemple trouver le temps de traduire la réponse de Linus à Ken Brown, mais je pense que je n’y arriverai pas… :-( Allez ! Quelqu’un peut s’y coller, y a pas grand chose :-).

Tout est relatif...

Allez…un p’tit peu de physique, ça peut pas faire de mal.

Mamie et la relativité restreinte

Moi j’trouve ça marrant la façon dont c’est expliqué… même si j’ai pas tout compris. Alors si y en a pour qui c’est super clair… N’hésitez pas à poster.

Votez Bon sang !

Demain, vous qui utilisez l’informatique ou vous qui travaillez dans le domaine, votez !

Procuration

C’est très simple à faire, je l’ai fait récemment, il suffit de suivre les quelques étapes suivantes :

  • Trouver quelqu’un qui vote dans la même ville que vous.
  • Vous allez à la gendarmerie ou au commissariat le plus proche avec votre carte d’identité et votre carte d’électeur
  • Vous dites que vous souhaitez remplir une demande de procuration
  • Vous remplissez la paperasse
  • Environ 15 minutes plus tard, vous êtes repartis et c’est fini…

Pourquoi et pour qui voter

Parce que votre vote aura d’autant plus de poids que le taux d’abstention est annoncé fort ! Si 20% de la population seulement vote, le vôtre en vaut 5 fois plus.

Personnellement, je pense voter à gauche indépendamment de mes opinions politiques habituelles parce que c’est le seul parti à posséder une section dédiée à l’informatique (TemPS réels) et à lutter contre les brevets.

Rappel pour ceux qui ont oublié : Chirac était contre les brevets et le gouvernement a voté pour…

DEMAIN, VOTEZ ET VOTEZ BIEN

Utilisation de StringBuffer et autres ruses

Mise à jour 2009 : Aujourd’hui, préférez simplement l’utilisation de la classe StringBuilder à la place de StringBuffer. Le reste de l’article reste valable.

Voici donc le premier billet traitant de programmation, je pense que ce n’est que le premier d’une longue série. J’espère aussi que ça sera le petit coup de pouce qui manque à Syl pour savoir sur quoi blogguer plus souvent :-).

Aujourd’hui on va faire du Java.

Exemple de code qu’il est MAL®

Vous le savez certainement ou vous l’avez au moins entendu dire : la classe String est non mutable. Qu’est-ce que ça signifie ? Ça veut dire qu’une fois instanciée vous ne pouvez plus la modifier… Vous pouvez vérifier, il n’existe aucun mutateur (setter) pour cette classe.

Exemple : écrivons une méthode qui ajoute à hello les chiffres 1 à 9.

public static String sayBadHello(){   String bonjour = "bonjour";   for(int i=1;i<10;++i)   {       bonjour += i;   }   return bonjour;}

Ici, qu’est-ce qui se passe ? On instancie un objet String et on y met “bonjour”. Ensuite, on fait quoi ? Ben, à chaque boucle, on prend la variable bonjour, on lui concatène le chiffre en cours et on affecte le résultat à bonjour.

En faisant ça : on instancie une nouvelle String à chaque fois et l’ancienne String est garbagée (comme l’utilisateur-développeur ne possède alors plus aucune référence vers cette variable, la machine virtuelle sait qu’elle peut supprimer cet ancien objet dès qu’elle le voudra).

Vous voyez le problème maintenant ? Pour une boucle de n éléments, on va instancier n objets ! Si vous passez votre temps à appeler cette méthode, vous déclencherez autant de fois cette aberration.

StringBuffer

Pour éviter ces nombreuses instanciations inutiles, il existe la classe StringBuffer qui, elle, est mutable. J’ose espérer que vous les utilisez déjà et que pour les étudiants d’entre vous, vos profs ont pensé à insister dessus. S’ils ne connaissent pas, ben je m’inquiéterai pour votre formation. Si vous ne connaissiez pas, à partir de maintenant vous n’aurez plus d’excuse :-).

Utilisation des méthodes append

Ces méthodes permettent d’ajouter un grand nombre de types différents à la chaîne stockée sous forme de caractères.

Voici un exemple simple d’utilisation pour corriger l’exemple précédent :

public static String sayGoodHello(){   StringBuffer bonjour = new StringBuffer(20);   bonjour.append("bonjour");   for(int i=1;i<10;++i)   {       bonjour.append(i);   }   return bonjour.toString();}

Plus de finesse

Quelques petits compléments pour les plus affamés :-).

  • Les plus attentifs auront remarqué le ++i là où on rencontre le plus souvent un i++. Ce n’est pas anodin, c’est juste un léger gain en terme de performances mais tellement simple à obtenir que je ne vois pas pourquoi je m’en priverais. À l’origine, je tiens ce conseil d’Anubis qui m’a fait réaliser que dans l’un des cas, on a besoin d’une variable temporaire supplémentaire et non dans l’autre.

    Grossièrement, c’est dû à ça (ces deux déclarations sont environ celles du C++, d’après les quelques souvenirs qu’il m’en reste. Avec ma chance, d’ailleurs, c’est sûrement l’inverse puisque je les remets au pif. Pas grave, l’objectif n’est pas de faire du C++ mais de faire saisir la différence entre la pré et la post-incrémentation) :

    Post-incrémentation : i++

    int operator++() {   int sauvegarde = i;   this.i = this.i +1;   return sauvegarde;}
    

    Pré-incrémentation : ++i

    int operator++(int) {   this.i = this.i +1;   return this.i;}
    
  • Si vous utilisez un StringBuffer avec plusieurs append statiques qui se suivent (merci Linux Magazine) :

    buffer.append("bonjour");buffer.append("au revoir");
    

    Utilisez plutôt :

    buffer.append("bonjour")      .append("au revoir");
    

    Vous éviterez ainsi d’empiler inutilement le retour de la méthode append sans vous en servir.

Houaaa! T'as vu le canon là bas!

On vient de célébrer l’anniversaire du débarquement, je reste donc dans le sujet en vous donnant un lien sur site qui parle des canons les plus effrayants qui existent comme le canon de Paris ou la Grosse Bertha.

Donc si ça vous intéresse, allez donc faire un tour sur le site des canons de l’apocalypse.

Page 27 of 33 Older