<?xml version="1.0" encoding="utf-8"?><?xml-stylesheet title="XSL formatting" type="text/xsl" href="http://blog.emmanueldeloget.com/index.php?feed/rss2/xslt" ?><rss version="2.0"
  xmlns:dc="http://purl.org/dc/elements/1.1/"
  xmlns:wfw="http://wellformedweb.org/CommentAPI/"
  xmlns:content="http://purl.org/rss/1.0/modules/content/"
  xmlns:atom="http://www.w3.org/2005/Atom">
<channel>
  <title>Architecture Logicielle &amp; Développement</title>
  <link>http://blog.emmanueldeloget.com/index.php?</link>
  <atom:link href="http://blog.emmanueldeloget.com/index.php?feed/rss2" rel="self" type="application/rss+xml"/>
  <description></description>
  <language>fr</language>
  <pubDate>Thu, 11 Mar 2010 17:05:06 +0100</pubDate>
  <copyright></copyright>
  <docs>http://blogs.law.harvard.edu/tech/rss</docs>
  <generator>Dotclear</generator>
  
    
  <item>
    <title>Passage à Dotclear v2.1.6</title>
    <link>http://blog.emmanueldeloget.com/index.php?post/2010/03/10/Passage-%C3%A0-Dotclear-v2.1.6</link>
    <guid isPermaLink="false">urn:md5:355235ce3a9d3f023ae537df8bdb6bb9</guid>
    <pubDate>Wed, 10 Mar 2010 13:30:00 +0100</pubDate>
    <dc:creator>Emmanuel Deloget</dc:creator>
        <category>General</category>
        <category>ce blog</category><category>dotclear</category><category>PHP</category><category>plugins</category><category>SQL</category>    
    <description>&lt;p&gt;Il fallait bien que ça arrive un jour&amp;nbsp;: le logiciel de blog sur ce site web est passé de la version 1.2.7 à la version 2.1.6. Et ça n'a pas été sans heurts...&lt;/p&gt;    &lt;p&gt;Il fallait bien que ça arrive un jour&amp;nbsp;: le logiciel de blog sur ce site web est passé de la version 1.2.7 à la version 2.1.6. Et ça n'a pas été sans heurts...Premièrement, il manque encore plein de choses&amp;nbsp;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;les images - ne vous affolez pas si un diagramme manque, il vont revenir d'ici quelques jours (le temps de les dépoussiérer et de les importer dans le nouveau logiciel de blog).&lt;/li&gt;
&lt;li&gt;les notes des billets - je n'ai pas encore trouvé de plugins satisfaisant que vous permette de donner une note aux billets. Mais je continue de chercher (et si je ne trouve pas et bien je me lancerais dans l'écriture d'un tel plugin).&lt;/li&gt;
&lt;li&gt;les tags - la technique que j'ai utilisé pour importer les billets n'a pas récupérer les tags associés. Je vais devoir me taper un peu de SQL pour réussir à faire ce que je veux, et ça devrait revenir dans les jours qui viennent.&lt;/li&gt;
&lt;li&gt;les téléchargements - il va me falloir trouver une solution rapide pour les stocker. Dans l'idée, ils vont tous atterrir dans &lt;a href=&quot;http://download.emmanueldeloget.com/&quot; hreflang=&quot;fr&quot;&gt;http://download.emmanueldeloget.com/&lt;/a&gt;, puisque ce site est maintenant la plateforme de stockage de tout ce qui se télécharge chez moi.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Pour une raison que j'ignore, l'import du blog s'est mal passé, et il m'a fallu ruser pour réussir à importer commentaires et autres billets. Dans un premier temps, j'ai créé un blog en local (et je l'ai paramétré au mieux). J'ai réussi à importer les données de mon blog en ligne dans ce blog local, et j'ai exporté la base de données en trois parties&amp;nbsp;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;la structure de la base&lt;/li&gt;
&lt;li&gt;les données&lt;/li&gt;
&lt;li&gt;les contraintes sur la base&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;J'ai ensuite installé DC 2.1.6 sur la machine de mon hébergeur puis j'ai exporté la structure de la base de données créée (sans les contraintes). J'ai alors effacé les tables, et je les ai recréé grâce à cette dernière exportation. J'ai pu ensuite importer les données et recréer les contraintes.&lt;/p&gt;


&lt;p&gt;Pourquoi cette opération délicate&amp;nbsp;? Principalement parce que si j'essaie d'importer les données dans les tables avec les contraintes, l'import ne fonctionne pas (une erreur SQL se produit à cause de contraintes non satisfaites).&lt;/p&gt;


&lt;p&gt;Une fois les données importées, j'ai pu réinstaller les plugins manquants&amp;nbsp;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Noodles v0.5 (pour les gravatars dans les commentaires)&lt;/li&gt;
&lt;li&gt;Adsense Management v0.6beta90  (devinez pourquoi). J'ai légèrement modifié le plugin pour spécifier le schéma de couleurs dont j'avais besoin.&lt;/li&gt;
&lt;li&gt;Comments Wikibarre  v1.0-RC3 (parce que ça va vous aider de pouvoir mettre en forme vos commentaires)&lt;/li&gt;
&lt;li&gt;ArchivesWidget v1.0,, modifié par mes soins  (pour afficher les archives de la même manière que précédemment). Sans  la modification, les entrées sont triées par années, puis par mois, et le rendu n'est pas très agréable à l'oeil.&lt;/li&gt;
&lt;li&gt;DC1 Redirect v1.0.1 (parce que le format d'URL a changé)&lt;/li&gt;
&lt;li&gt;Tag Flash v1.0.2 (la boule avec les tags)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;J'ai du écrire quelques petits widgets&amp;nbsp;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Xiti Personnal (pour afficher l'icône Xiti)&lt;/li&gt;
&lt;li&gt;Google Search (pour afficher une barre de recherche Google en lieu et place de la barre de recherche fournie en standard)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Ces widgets sont regroupés (avec le &lt;a href=&quot;http://blog.emmanueldeloget.com/index.php?post/2010/03/01/139-plugin-pour-dotclear-216&quot; hreflang=&quot;fr&quot;&gt;widget amazon&lt;/a&gt;) dans un plugin &lt;em&gt;Emmanuel Deloget Web Sites&lt;/em&gt; pour faciliter leur déploiement. &lt;a href=&quot;http://download.emmanueldeloget.com/plugins/&quot; hreflang=&quot;fr&quot;&gt;L'archive est disponible ici&lt;/a&gt;.&lt;/p&gt;


&lt;p&gt;Le thème utilisé est le même que précédemment, mis à jour pour DC 2.1.6.&lt;/p&gt;


&lt;p&gt;Un point intéressant de DC 2, c'est le fait que les templates n'ont pas besoin d'être modifiés pour ajouter de nouveaux éléments dans la page. La notion de widgets permet d'afficher tout ce qu'on souhaite afficher dans les deux barres de navigation. DC 2 est donc infiniment plus ouvert que DC 1 (pour mon plus grand plaisir).&lt;/p&gt;</description>
    
    
    
          <comments>http://blog.emmanueldeloget.com/index.php?post/2010/03/10/Passage-%C3%A0-Dotclear-v2.1.6#comment-form</comments>
      <wfw:comment>http://blog.emmanueldeloget.com/index.php?post/2010/03/10/Passage-%C3%A0-Dotclear-v2.1.6#comment-form</wfw:comment>
      <wfw:commentRss>http://blog.emmanueldeloget.com/index.php?feed/atom/comments/145</wfw:commentRss>
      </item>
    
  <item>
    <title>webvcs - vérification de l'identité en ligne sans transfert du mot de passe</title>
    <link>http://blog.emmanueldeloget.com/index.php?post/2010/03/05/157-webvcs-verification-de-l-identite-en-ligne-sans-transfert-du-mot-de-passe</link>
    <guid isPermaLink="false">urn:md5:20b48b544acf18d3132fed1949bb2889</guid>
    <pubDate>Fri, 05 Mar 2010 19:00:00 +0000</pubDate>
    <dc:creator>Emmanuel Deloget</dc:creator>
        <category>Technologies Web</category>
            
    <description>&lt;p&gt;De nombreux systèmes - qu'ils soient des sites web ou des programmes se connectant à internet - ont besoin de vérifier l'identité de l'utilisateur. Souvent, cette identité est stockée dans une base de donnée qu'il faut alors interroger. Le problème est que pour interroger cette base de donnée, il faut au moins deux information&amp;nbsp;: l'identifiant de connexion et le mot de passe qui lui est associé. Il est courant de voir des implémentations qui font transiter ce mot de passe en clair sur internet - avec tous les risques de sécurité que cette transmission d'information pose.&lt;/p&gt;


&lt;p&gt;Cet article présente une méthode simple d'implémentation ne nécessitant pas le transfert en clair ou crypté du mot de passe, permettant ainsi l'authentification d'un utilisateur de manière plus sécurisée. Cette méthode est implémentée dans le logiciel en cours de développement &lt;code&gt;webvcs&lt;/code&gt;, mais il peut aisément être porté vers une architecture de type client léger.&lt;/p&gt;    &lt;h3&gt;Implémentation&lt;/h3&gt;

&lt;p&gt;L'identification s'effectue en deux passes&amp;nbsp;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;dans la première passe, le client interroge le serveur pour obtenir un identifiant lié à la connexion. Cet identifiant est lié à la certaines informations en provenance de la machine cliente (par exemple, son adresse IP).&lt;/li&gt;
&lt;li&gt;dans la seconde passe, le client envoie le login de l'utilisateur ainsi qu'une clef de hashage créée à partir de l'identifiant de connexion et du mot de passe de l'utilisateur. Le serveur recalcule l'identifiant de connexion, récupère le mot de passe lié au login, et compare la clef de hashage reçue avec la clef de hashage qu'il calcule lui-même. En fonction du résultat de cette comparaison le client reçoit soit une erreur d'authentification, soit un cookie contenant un token d'authentification réussie - qui sera utilisé pour toutes les transactions suivantes entre le client et le serveur.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Dans &lt;code&gt;webvcs&lt;/code&gt;, j'ai choisi d'utiliser l'algorithme de hashage SHA1 - pour sa simplicité, et parce que cette algorithme est implémenté dans de nombreux langages, y compris &lt;a href=&quot;http://pajhome.org.uk/crypt/md5/sha1.html&quot; hreflang=&quot;en&quot;&gt;javascript&lt;/a&gt;, &lt;a href=&quot;http://php.net/manual/fr/function.sha1.php&quot; hreflang=&quot;en&quot;&gt;PHP&lt;/a&gt; (supporté de manière native), &lt;a href=&quot;http://www.packetizer.com/security/sha1/&quot; hreflang=&quot;en&quot;&gt;C et C++&lt;/a&gt;.&lt;/p&gt;


&lt;h3&gt;Considérations de sécurité&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;A aucun moment le client n'envoie le mot de passe en clair. De fait, il n'est pas possible d'intercepter ce mot de passe.&lt;/li&gt;
&lt;li&gt;La longueur du mot de passe n'a pas d'influence sur la longueur de la clef de hashage. En choisissant un mot de passe suffisamment long, on peut éliminer les problèmes que peuvent soulever une attaque de type force brute.&lt;/li&gt;
&lt;li&gt;Même si un attaquant intercepte le token d'authentification, il ne peut pas s'en servir puisque celui-ci est lié à la machine cliente. Par contre, si il est situé sur une machine qui partage ses informations de connexion avec la machine cliente (par exemple si il est situé derrière le même routeur NAT), il peut obtenir les mêmes droits que l'utilisateur connecté.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;SHA1 et MD5 (les deux fonctions de hashage les plus utilisées) sont sujets à des collisions (voir &lt;a href=&quot;http://www.infosec.sdu.edu.cn/uploadfile/papers/How%20to%20Break%20MD5%20and%20Other%20Hash%20Functions.pdf&quot; hreflang=&quot;en&quot;&gt;cet article de X.Wang et H.Yu&lt;/a&gt;). Pour plus de sécurité, on peut leur préférer des évolutions plus récentes telle que SHA-256. En PHP, la fonction &lt;a href=&quot;http://www.php.net/manual/en/function.hash.php&quot; hreflang=&quot;en&quot;&gt;hash()&lt;/a&gt; vous permet de choisir l'agorithme de hashage parmi les algorithmes disponibles.&lt;/p&gt;


&lt;h3&gt;Conclusion&lt;/h3&gt;

&lt;p&gt;Cette authentification n'est pas une authentification complètement sécurisée et de fait, &lt;code&gt;webvcs&lt;/code&gt; qui implémente cette technologie ne doit pas être utilisé dans un contexte où la sécurité est primordiale.&lt;/p&gt;


&lt;p&gt;Elle est toutefois plus fiable qu'une authentification qui ferait passer le mot de passe en clair sur le réseau, ce qui, ramené aux intentions originelle du projet &lt;code&gt;webvcs&lt;/code&gt;, est suffisant dans un premier temps. Le seul moyen d'obtenir une connexion sécurisée entre un client et un serveur reste le cryptage complet des échanges de données.&lt;/p&gt;


&lt;h4&gt;Notes sur l'implémentation sur un client léger&lt;/h4&gt;

&lt;p&gt;Pour une implémentation dans un client léger, il suffit d'un bon browser web supportant javascript et la &lt;a href=&quot;http://pajhome.org.uk/crypt/md5/sha1.html&quot; hreflang=&quot;en&quot;&gt;librairie javascript présentée ci-dessus&lt;/a&gt;. Le même système peut être implémenté sur une unique page web car&amp;nbsp;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;la première passe est automatique, les informations d'identification de la machine client pouvant être récupérée lors de la génération de la page de login&amp;nbsp;;&lt;/li&gt;
&lt;li&gt;la seconde passe est effectuée par l'envoi de la requête de test lorsque l'utilisateur se connecte.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Comme dans le cas client riche/serveur, le token d'authentification est renvoyé au client léger sous la forme d'un cookie.&lt;/p&gt;</description>
    
    
    
          <comments>http://blog.emmanueldeloget.com/index.php?post/2010/03/05/157-webvcs-verification-de-l-identite-en-ligne-sans-transfert-du-mot-de-passe#comment-form</comments>
      <wfw:comment>http://blog.emmanueldeloget.com/index.php?post/2010/03/05/157-webvcs-verification-de-l-identite-en-ligne-sans-transfert-du-mot-de-passe#comment-form</wfw:comment>
      <wfw:commentRss>http://blog.emmanueldeloget.com/index.php?feed/atom/comments/144</wfw:commentRss>
      </item>
    
  <item>
    <title>Plugin pour DotClear 2.1.6</title>
    <link>http://blog.emmanueldeloget.com/index.php?post/2010/03/01/139-plugin-pour-dotclear-216</link>
    <guid isPermaLink="false">urn:md5:73ab5b1938ad29f21c7c4d925c14bcc7</guid>
    <pubDate>Mon, 01 Mar 2010 14:00:00 +0000</pubDate>
    <dc:creator>Emmanuel Deloget</dc:creator>
        <category>Technologies Web</category>
            
    <description>&lt;p&gt;&lt;em&gt;Note - ce billet a été posté originellement le mercredi 14 octobre 2009 à 11:30. La version courante du plugin amazon pour DC 2.1.6 est la v0.4.&lt;/em&gt;&lt;/p&gt;


&lt;p&gt;J'ai ouvert un autre blog (qui parle de jeux de rôle, de romans et tout ça&amp;nbsp;; rien de bien intéressant pour le fan de technique que vous êtes). Afin de pouvoir afficher une jolie boite proposant un lien vers un livre particulier sur Amazon, j'ai développé un petit plugin pour DotClear 2.1.6. Ce billet le documente, et vous donne le lien pour le télécharger...&lt;/p&gt;    &lt;h3&gt;Installation&lt;/h3&gt;

&lt;p&gt;La dernière version de l'archive est stockée ici&amp;nbsp;: &lt;a href=&quot;http://download.emmanueldeloget.com/plugins/&quot;&gt;http://download.emmanueldeloget.com/plugins/&lt;/a&gt;. L'installation du plugin est effectuée par l'interface d'administration (comme pour les autres plugins).&lt;/p&gt;


&lt;h3&gt;Utilisation&lt;/h3&gt;

&lt;p&gt;Ce plugin est un widget - pour l'activer, il suffit de déposer le widget dans l'un des bandeaux depuis l'interface d'administration du blog. Les options de configurations sont&amp;nbsp;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Serveur Amazon&lt;/strong&gt;&amp;nbsp;: le nom du serveur qui héberge la publicité (exemple: rcm-fr.amazon.fr)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;ID partenaire&lt;/strong&gt;&amp;nbsp;: votre ID partenaire Amazon&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;MD&lt;/strong&gt; (optionnel)&amp;nbsp;: pour repérer la valeur de cette variable, allez sur Amazon et générez un lien pour un livre quelconque. Dans le code HTML proposé, repérez la chaine &quot;&amp;amp;MD=valeur&amp;amp;&quot;. Récupérer la valeur précisée pour renseigner la variable MD.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Liste des ASINs&lt;/strong&gt;&amp;nbsp;: liste d'ASIN séparés par des virgules (,). Certaines pages Amazon présentent directement un ASIN, que vous pouvez directement copier dans la liste. D'autres pages présentent un ISBN. Dans ce cas, générez un lien pour cet ouvrage et repérez dans le code HTML la chaine &quot;asins=valeur&quot;. Récupérez la valeur et ajoutez la à la liste.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;L'ASIN de l'élément affiché est pris au hasard dans la liste proposée. Vous pouvez un exemple d'utilisation sur &lt;a href=&quot;http://rpg.emmanueldeloget.com/&quot;&gt;http://rpg.emmanueldeloget.com/&lt;/a&gt;.&lt;/p&gt;


&lt;h3&gt;Versions&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;0.1&amp;nbsp;: version initiale&lt;/li&gt;
&lt;li&gt;0.2&amp;nbsp;: support de toutes les variables modifiables pour le paramétrage de l'affichage&lt;/li&gt;
&lt;li&gt;0.3&amp;nbsp;: support des variables de couleur de bordure et cible pour l'ouverture du lien&lt;/li&gt;
&lt;li&gt;0.4&amp;nbsp;: si &lt;strong&gt;MD&lt;/strong&gt; n'est pas renseigné, la variable n'est pas rajoutée à l'URI généré.&lt;/li&gt;
&lt;/ul&gt;</description>
    
    
    
          <comments>http://blog.emmanueldeloget.com/index.php?post/2010/03/01/139-plugin-pour-dotclear-216#comment-form</comments>
      <wfw:comment>http://blog.emmanueldeloget.com/index.php?post/2010/03/01/139-plugin-pour-dotclear-216#comment-form</wfw:comment>
      <wfw:commentRss>http://blog.emmanueldeloget.com/index.php?feed/atom/comments/126</wfw:commentRss>
      </item>
    
  <item>
    <title>webvcs - un système de contrôle de version sans serveur</title>
    <link>http://blog.emmanueldeloget.com/index.php?post/2010/02/25/156-webvcs-un-systeme-de-controle-de-version-sans-serveur</link>
    <guid isPermaLink="false">urn:md5:87a4409b8e23d70a97bc15a1a711d0a9</guid>
    <pubDate>Thu, 25 Feb 2010 13:00:00 +0000</pubDate>
    <dc:creator>Emmanuel Deloget</dc:creator>
        <category>Technologies Web</category>
            
    <description>&lt;p&gt;Pour mes projets personnels, je suis en train de développer un logiciel que j'ai nommé &lt;code&gt;webvcs&lt;/code&gt;, et qui n'est autre qu'un SVCS (pour &lt;em&gt;serverless version control system&lt;/em&gt;) composé de deux parties&amp;nbsp;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;un client (fonctionnant sous Windows 32/64, mais le porter sous Linux ou Mac OS X ne devrait pas poser de problèmes)&lt;/li&gt;
&lt;li&gt;un ensemble de scripts PHP pouvant s'installer sur n'importe quel serveur web autorisant l'exécution de scripts PHP 5.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Le but&amp;nbsp;: héberger sur mon site web mes propres projets open source, sans avoir besoin de passer par un plateforme telle que codeplex, sourceforge ou google code.&lt;/p&gt;    &lt;h3&gt;Le fonctionnement, coté web&lt;/h3&gt;

&lt;p&gt;Les scripts PHP émulent un serveur VCS simple, capable de comprendre quelques notions de base&amp;nbsp;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;import&lt;/strong&gt;&amp;nbsp;: importer un projet dans le système&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;get revision&lt;/strong&gt;&amp;nbsp;: récupère une version particulière d'un fichier&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;commit&lt;/strong&gt;&amp;nbsp;: enregistrer les fichiers modifiés sur le serveur web&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;branch&lt;/strong&gt;&amp;nbsp;: crée une branche.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Les trois notions manipulées sont, dans l'ordre de taille&amp;nbsp;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;le fichier&amp;nbsp;: c'est l'unité de base du système. Les fichiers sont pour l'instant stockés dans une base de donnée SQL (mysql pour l'instant, mais l'écriture d'un driver pour un autre SGBC ne me semble pas trop complexe), mais je pense développer un sous-système permettant l'utilisation de webvcs sur des serveurs sans accès à une base de donnée.&lt;/li&gt;
&lt;/ul&gt;
&lt;ul&gt;
&lt;li&gt;le travail (job)&amp;nbsp;: lorsqu'un commit est effectué, il est nécessairement lié à une activité (&lt;em&gt;activity&lt;/em&gt;) - qui peut être une évolution, une correction de bug, etc - pour produire un &lt;em&gt;job&lt;/em&gt;. L'idée est de ne pas permettre un commit si ce commit n'est pas motivé par quelque chose. Les jobs sont gérés sur la base de transactions - un seul job peut être appliqué à la fois, ce qui permet d'assurer la possibilité de travail concurrentiel sur un même ensemble de fichiers. Bien évidemment, les &lt;em&gt;activities&lt;/em&gt; doivent exister avant le commit pour que celui-ci puisse se faire.&lt;/li&gt;
&lt;/ul&gt;
&lt;ul&gt;
&lt;li&gt;la branche (branch)&amp;nbsp;: un utilisateur travaille nécessairement sur une branche - que cette branche soit la branche principale (&lt;em&gt;mainline&lt;/em&gt;) ou une branche secondaire (marquée par un label). Dès qu'il y a création d'un label, il y a création d'une branche - et inversement. Il est possible d'intégrer un job dans une autre branche que celle dans laquelle il a été produit.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Le tout fonctionne sur la base d'un protocole web très simple inspiré par les technologies du type &quot;web service&quot; et que je documenterais plus tard (ce qui, je l'espère, autorisera la création de versions ASP.Net de webvcs).&lt;/p&gt;


&lt;h3&gt;Le fonctionnement, coté client&lt;/h3&gt;

&lt;p&gt;L'application cliente webvcs est relativement simple. Elle ne comporte qu'un nombre réduit de fonctions&amp;nbsp;: connect/disconnect, import, get, commit, branch. La question de la sécurité est gérée sommairement via les commandes connect/disconnect (le connect a une durée de vie limitée à une dizaine de minutes d'inactivité, donc le disconnect n'est pas nécessaire dans la plupart des cas). Un hash est calculé à partir des informations d'identification et des informations liées à la machine cliente, ce hash étant systématiquement durant les dialogues entre le logiciel client et les scripts installés sur le serveur. Un saupoudrage de gestion pas trop idiote permet de s'assurer avec une &quot;certaine certitude&quot; que la personne dialoguant avec les scripts serveur est bien celle qu'elle prétends être. Point important&amp;nbsp;: les mots de passe ne circulent jamais en clair sur le réseau.&lt;/p&gt;


&lt;p&gt;Les autres actions sont assez triviales, donc je ne vais pas m'étendre sur le sujet.&lt;/p&gt;


&lt;h3&gt;Beta-testeurs&amp;nbsp;?&lt;/h3&gt;

&lt;p&gt;Le logiciel est en cours de développement. Il n'est pas mûr pour être testé, j'en suis à la phase de pré-alpha. Dès que j'entrerais dans une phase alpha (avec un produit suffisamment fonctionnel pour être testé et utilisé mais comportant encore des problèmes de stabilité voire des fonctions manquantes), je vous tiendrais au courant.&lt;/p&gt;


&lt;p&gt;Idem pour ceux qui veulent rejoindre le développement&amp;nbsp;: je les encourage pour l'instant à me faire part de leurs idées. Dès que le logiciel sera en pré-alpha, il apparaîtra comme par magie sur mon site web, et il sera utilisé pour continuer le développement sur lui-même (lire&amp;nbsp;: webvcs sera utilisé pour héberger le projet webvcs&amp;nbsp;; c'est la raison pour laquelle j'ai besoin de m'assurer qu'il fonctionne suffisamment avant de le lâcher dans la nature...)&lt;/p&gt;


&lt;p&gt;En conclusion&amp;nbsp;: dès que j'ai quelque chose à vous dire sur le projet en cours, je mettrais à jour ce blog. Vous n'avez donc qu'à le suivre régulièrement pour être informé de l'avancement du projet :)&lt;/p&gt;</description>
    
    
    
          <comments>http://blog.emmanueldeloget.com/index.php?post/2010/02/25/156-webvcs-un-systeme-de-controle-de-version-sans-serveur#comment-form</comments>
      <wfw:comment>http://blog.emmanueldeloget.com/index.php?post/2010/02/25/156-webvcs-un-systeme-de-controle-de-version-sans-serveur#comment-form</wfw:comment>
      <wfw:commentRss>http://blog.emmanueldeloget.com/index.php?feed/atom/comments/143</wfw:commentRss>
      </item>
    
  <item>
    <title>Le futur standard C++ : les templates variadiques</title>
    <link>http://blog.emmanueldeloget.com/index.php?post/2010/02/08/155-le-futur-standard-c-les-templates-variadiques</link>
    <guid isPermaLink="false">urn:md5:393b94d057d7d8efbabeb7f29f3c228e</guid>
    <pubDate>Mon, 08 Feb 2010 14:00:00 +0000</pubDate>
    <dc:creator>Emmanuel Deloget</dc:creator>
        <category>C++</category>
            
    <description>&lt;p&gt;Oui, je sais, variadique n'est pas un mot très franchouillard (et franchouillard n'est pas trouvé par le dictionnaire de Firefox, qui me propose antibrouillard à la place). Il faut toutefois bien trouver quelque chose. Les fonctions à un argument sont des fonctions monadiques. Une fonction à plusieurs arguments est dite polyadique. Alors utiliser le néologisme &quot;variadique&quot; pour parler d'un nombre d'arguments variable ne me choque pas vraiment - d'autant plus que ce néologisme est très utilisé dans la communauté C / C++.&lt;/p&gt;


&lt;p&gt;Outre cette digression, reste à expliciter le but de cet article. Comme les articles précédents de la série (et certains commencent à être ancien), cette saillie technique va tenter de vous donner quelques informations d'importance concernant cette nouveauté du futur standard C++ - l'une des plus importante, si vous voulez mon avis.&lt;/p&gt;    &lt;h3&gt;L'Existant&lt;/h3&gt;

&lt;p&gt;Afin de bien saisir toute la puissance de ce nouvel outil, il convient de faire le tour des solutions existantes. A l'heure actuelle, notre bon vieux standard datant de 1998 et amendé en 2003 se contente de définir une notation simple pour gérer tout ce qui est fonction et macros variadiques&amp;nbsp;: les célèbres &quot;trois petits points&quot; (...) qu'on retrouve par exemple dans la définition de &lt;code&gt;std::printf&lt;/code&gt;&amp;nbsp;:&lt;/p&gt;


&lt;pre&gt;namespace std {
  int printf(const char* format, ...);
}&lt;/pre&gt;


&lt;p&gt;Cette déclaration signifie que la fonction prends au moins un argument (la chaîne de formatage) mais qu'on peut lui en spécifier d'autres. Le problème principal est qu'il est impossible de connaître le type de chaque argument. Pour pouvoir les traiter correctement, on doit spécifier un certain nombre de codes dans la chaine de formatage. C'est dangereux, et loin d'être résistant à l'erreur, ainsi que le code suivant le montre&amp;nbsp;:&lt;/p&gt;


&lt;pre&gt;int i = 0;
std::printf(&quot;%s est en fait du type int&quot;, i);
// crash, car printf() va tenter de transformer 0 en un pointeur vers une 
// chaîne de caractère ; or 0 est le pointeur null...&lt;/pre&gt;


&lt;p&gt;Ce code ne peut pas être vérifier par le compilateur, qui au maximum pourra se contenter de lever un warning - mais pas une erreur, tant votre légendaire sagacité lui est précieuse - après tout, t peut très bien contenir une adresse valide pour une chaine de caractère - bien que cela soit improbable et certainement en dehors de la norme C++ (qui ne spécifie pas de conversion possible entre un type intégral et un pointeur).&lt;/p&gt;


&lt;p&gt;Bref, ce n'est pas génial, mais ça tombe en marche suffisamment souvent pour qu'on le considère avec bienveillance.&lt;/p&gt;


&lt;p&gt;Au niveau des arguments de templates, rien n'existe - donc le problème est à priori réglé. A priori seulement, car le TR1 définit de nombreux types template qui peuvent prendre un nombre quelconque d'arguments&amp;nbsp;: &lt;code&gt;std::tr1::tuple&amp;lt;&amp;gt;&lt;/code&gt; est un excellent exemple. Comment écrire le code permettant de créer un tuple quelconque alors que le langage impose que le nombre d'arguments du type template soit connu&amp;nbsp;? Les concepteurs de boost et de la librairie standard GNU sont ingénieux&amp;nbsp;: un savant mélange de macros, une bonne dose d'utilisation du préprocesseur et hop, le tour est joué... pour un nombre maximum d'arguments. Pour simplifier, le code ressemble à&amp;nbsp;:&lt;/p&gt;


&lt;pre&gt;#define N__ARGUMENT_COUNT 10
#include &quot;definition_with_N_args.h&quot;&lt;br /&gt;
#define N__ARGUMENT_COUNT 9
#include &quot;definition_with_N_args.h&quot;&lt;br /&gt;
...&lt;/pre&gt;


&lt;p&gt;Le fait est qu'une fois passé par le précompilateur, l'unité de compilation obtenue est une horreur sans nom. Elle comptera des milliers de lignes, et par conséquent sera extrêmement longue à compiler. En fait, pour certains cas particuliers dans le TR1, je soupçonne que le temps de compilation des fichiers headers n'est plus (et de loin) une fonction linéaire du nombre d'arguments qu'il est possible d'utiliser. Et puis on abeau dire&amp;nbsp;: 10 arguments, c'est peut être assez pour régler un problème particulier. Pour en régler un autre, il en faudra peut-être 20, ou 30.&lt;/p&gt;


&lt;p&gt;&lt;img src=&quot;http://blog.emmanueldeloget.com/images/cpp/ct_performance.png&quot; alt=&quot;temps du compilation du TR1 GNU en fonction du nombre d&amp;#039;argument des templates&quot; style=&quot;display:block; margin:0 auto;&quot; /&gt;&lt;/p&gt;


&lt;p&gt;Ce problème est l'une des motivation principale de &lt;a href=&quot;http://www.generic-programming.org/~dgregor/cpp/variadic-templates.html&quot; hreflang=&quot;en&quot;&gt;Douglas Gregor&lt;/a&gt;, la personne qui a formalisé la proposition des templates variadiques pour le C++ - et dont j'ai honteusement volé le diagramme ci-dessus.&lt;/p&gt;


&lt;p&gt;Bref, cet court état des lieux démontre assez clairement que les solutions existantes sont loin d'être optimales. Il était temps de faire quelque chose...&lt;/p&gt;


&lt;h3&gt;Variadic templates&amp;nbsp;: la proposition &lt;a href=&quot;http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2004/n1603.pdf&quot; hreflang=&quot;en&quot;&gt;N1603&lt;/a&gt; (pfd)&lt;/h3&gt;

&lt;p&gt;La toute première proposition de Douglas Gregor, Jaakko Järvi et Gary Powell décrivant les templates variadiques a été publiée en Février 2004 sous le numéro N1603. Elle présente une évolution majeure du coeur du langage en décrivant une syntaxe (encore approximative et remarquablement loin de ce qui a été adopté par le comité de normalisation) permettant l'utilisation d'un nombre de paramètres variable dans la définition d'une classe ou d'une fonction template. Il faut attendre septembre 2006 (proposition &lt;a href=&quot;http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2006/n2080.pdf&quot; hreflang=&quot;en&quot;&gt;N2080&lt;/a&gt;) pour commencer à voir ce qui deviendra la syntaxe officielle. Une fois les bases solidement établies, les propositions s'intéressent à la formulation de cette nouvelle fonctionnalité de manière à l'intégrer à la norme C++. Se suivent les proposition N2152, N2192 et &lt;a href=&quot;http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2242.pdf&quot; hreflang=&quot;en&quot;&gt;N2242&lt;/a&gt; en avril 2007. Cette dernière version sera à peine remaniée avant d'être intégrée au draft du standard C++ en le mois suivant (voir &lt;a href=&quot;http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2283.html&quot; hreflang=&quot;en&quot;&gt;N2283: Editor's Note&lt;/a&gt;. Depuis cette date, peu de chose ont véritablement changé, si ce n'est la syntaxe de l'opérateur &lt;code&gt;sizeof...()&lt;/code&gt; associé.&lt;/p&gt;


&lt;p&gt;Nous allons étudier ce qui est présenté dans la dernière version du draft du standard - &lt;a href=&quot;http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2009/n3000.pdf&quot; hreflang=&quot;en&quot;&gt;N3000&lt;/a&gt;.&lt;/p&gt;


&lt;p&gt;La concept maître des templates variadiques est la notion de paquet de paramètres (&lt;em&gt;parameters pack&lt;/em&gt; dans le texte du standard&amp;nbsp;; nous allons simplement utiliser l'acronyme PP pour parler d'eux). Les PP sont intimement liés à une syntaxe particluière mettant en oeuvre les trois caractères &lt;code&gt;...&lt;/code&gt; déjà utilisé pour signifier un nombre variable d'arguments dans la déclaration d'une fonction C.&lt;/p&gt;


&lt;p&gt;Prenons les déclarations suivantes&amp;nbsp;:&lt;/p&gt;


&lt;pre&gt;// déclaration d'une classe template prenant un nombre variable de types en argument
template &amp;lt;class... Args&amp;gt;
class C { };&lt;br /&gt;&lt;/pre&gt;


&lt;p&gt;Dans cette déclaration, on crée un PP de nom de Args. Ce PP, on peut en obtenir la taille grâce à l'opérateur %%sizeof...()%% qui prends en paramètre un PP et renvoie un &lt;code&gt;std::size_t&lt;/code&gt; qui correspond au nombre d'entités qu'il contient. Si on déclare &lt;code&gt;C&amp;lt;int,double,long&amp;gt;&lt;/code&gt;, on a la relation &lt;code&gt;sizeof...(Args) == 3&lt;/code&gt; dans la portée de C.&lt;/p&gt;


&lt;p&gt;Un PP peut être &quot;dépaqueté&quot; grâce à &lt;code&gt;...&lt;/code&gt; qui agit dans ce cas comme un méta-opérateur recréant la liste d'argument.&lt;/p&gt;


&lt;pre&gt;template &amp;lt;class... Args&amp;gt;
struct C { 
  static const std::size_t size = sizeof...(Args); 
};&lt;br /&gt;
template &amp;lt;class... Args&amp;gt;
struct D {
  static const bool has_two_args = C&amp;lt;Args...&amp;gt;::size == 2;
};&lt;/pre&gt;


&lt;p&gt;Dans ce code, l'expression &lt;code&gt;Args...&lt;/code&gt; reconstruit la liste d'arguments complète de manière à la passer à la définition de C.&lt;/p&gt;


&lt;p&gt;On peut se servir de cette propriété pour récursivement vider le PP. Par exemple&amp;nbsp;:&lt;/p&gt;


&lt;pre&gt;// pré-déclaration de C
template &amp;lt;class... Args&amp;gt; struct C;&lt;br /&gt;
// plus de paramètre : fin de la récursion
template &amp;lt;&amp;gt; 
struct C&amp;lt;&amp;gt; { };
// récursion : C&amp;lt;T,Args...&amp;gt; hérite de C&amp;lt;Args...&amp;gt; 
template &amp;lt;class T, class... Args&amp;gt;
struct C&amp;lt;T, Args...&amp;gt; : public C&amp;lt;Args...&amp;gt; {
  T value;
};&lt;/pre&gt;


&lt;p&gt;Si on analyse ce code et ce qui se passe lorsqu'on instancie C avec les paramètres &lt;code&gt;&amp;lt;int,float,long&amp;gt;&lt;/code&gt;&amp;nbsp;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;C&amp;lt;int,float,long&amp;gt; définit une variable value de type int et hérite de C&amp;lt;float,long&amp;gt;&lt;/li&gt;
&lt;li&gt;C&amp;lt;float,long&amp;gt; définit une variable value de type float et hérite de C&amp;lt;long&amp;gt;&lt;/li&gt;
&lt;li&gt;C&amp;lt;long&amp;gt; définit une variable value de type long et hérite de C&amp;lt;&amp;gt;.&lt;/li&gt;
&lt;li&gt;C&amp;lt;&amp;gt; stoppe la récursion.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Au final, On se retrouve avec un type définissant 3 variables, une de chaque type passé en paramètre.&lt;/p&gt;


&lt;p&gt;Lorsqu'on défini une fonction prenant un nombre variable d'arguments, on joue en fait avec un ou plusieurs PP.&lt;/p&gt;


&lt;pre&gt;template &amp;lt;class... Types&amp;gt;
void function(Types... values) { }&lt;/pre&gt;


&lt;p&gt;Cette définition fait intervenir deux PP&amp;nbsp;: Types (une liste de type) et values (une liste de valeurs). values et Types sont liés, puisque le type de chacun des paramètres de la fonction va se retrouver dans le PP Types.&lt;/p&gt;


&lt;p&gt;Grâce à cette notion de PP et grâce à la syntaxe relativement simple des templates variadiques, on peut réécrire une version type-safe de la fonction &lt;code&gt;printf()&lt;/code&gt;&amp;nbsp;:&lt;/p&gt;


&lt;pre&gt;void printf(const char* format)
{
  while (*format) {
    if (*format == '%') throw std::exception(&quot;not enough arguments provided&quot;);
    std::cout &amp;lt;&amp;lt; *format;
    ++format;
  }
}&lt;br /&gt;
template &amp;lt;class T, class... Args&amp;gt;
void printf(const char* format, const T&amp;amp; value, const Args&amp;amp;... args)
{
  while (*format) {
    if (*format == '%') {
      // on peut passer le caractère donnant le type de la valeur
      // puisque celui-ci est automatiquement déduit pas std::cout. 
      ++format; 
      std::cout &amp;lt;&amp;lt; value;
      printf(format, args...);
    } else {
      std::cout &amp;lt;&amp;lt; *format;
    }
    ++format;
  }
  throw std::exception(&quot;too many arguments provided&quot;);
}&lt;/pre&gt;


&lt;p&gt;Encore une fois, la notation &lt;code&gt;...&lt;/code&gt; nous a permis de dépaqueter les PP args et Args&amp;nbsp;; encore une fois, nous avons utilisé la récursion pour dépiler progressivement les différents arguments des deux PP. Une petite nouveauté toutefois&amp;nbsp;: dans la définition de la version variadique de printf(), on voit qu'on a utilisé la notation &lt;code&gt;const Args&amp;amp;... args&lt;/code&gt;. Cette notation permet bien évidemment à dire que chaque argument du PP args est une référence constante vers un type de du PP Args.&lt;/p&gt;



&lt;h3&gt;Conclusion&lt;/h3&gt;

&lt;p&gt;Bien entendu, la librairie standard va profiter de cette nouvelle notation - notamment ceux des types définis dans le TR1 qui utilisent un nombre variable d'arguments (&lt;code&gt;std::tr1::tuple&amp;lt;&amp;gt;&lt;/code&gt;, &lt;code&gt;std::tr1::function&amp;lt;&amp;gt;&lt;/code&gt;...). Dès que vous allez devoir travailler avec un ensemble variable d'arguments, vous allez pouvoir utiliser les templates variadiques de manière à vous assurer que vous contrôlez correctement le type des paramètres utilisés. Cette solution simple à mettre en oevre va limiter les problèmes liés aux fonctions variadiques définies dans le standard C et reprises dans le standard C++ de 1998.&lt;/p&gt;


&lt;p&gt;A noter que le support des templates variadiques commence à faire son apparition dans les compilateurs du marché. Si Visual Studio .Net 2010 beta 2 ne semble pas les supporter, les dernières versions de GCC (notamment la version en cours de développement gcc 4.5) proposent un support expérimental - activé par l'option &lt;code&gt;--std=c++0x&lt;/code&gt; en ligne de commande. Vous pouvez donc vous amuser à en tester les finesses.&lt;/p&gt;</description>
    
    
    
          <comments>http://blog.emmanueldeloget.com/index.php?post/2010/02/08/155-le-futur-standard-c-les-templates-variadiques#comment-form</comments>
      <wfw:comment>http://blog.emmanueldeloget.com/index.php?post/2010/02/08/155-le-futur-standard-c-les-templates-variadiques#comment-form</wfw:comment>
      <wfw:commentRss>http://blog.emmanueldeloget.com/index.php?feed/atom/comments/142</wfw:commentRss>
      </item>
    
  <item>
    <title>const X&amp; x ou X const&amp; x ? (et autres amusements)</title>
    <link>http://blog.emmanueldeloget.com/index.php?post/2010/02/04/154-const-x-x-ou-x-const-x</link>
    <guid isPermaLink="false">urn:md5:7db5d857fc57f957c93dbad0229c0839</guid>
    <pubDate>Thu, 04 Feb 2010 20:00:00 +0000</pubDate>
    <dc:creator>Emmanuel Deloget</dc:creator>
        <category>C++</category>
            
    <description>&lt;p&gt;Parce que ces deux notations sont strictement équivalentes&lt;sup&gt;[&lt;a href=&quot;http://blog.emmanueldeloget.com/index.php?post/2010/02/04/154-const-x-x-ou-x-const-x#pnote-154-1&quot; id=&quot;rev-pnote-154-1&quot;&gt;1&lt;/a&gt;]&lt;/sup&gt;, quelle est celle qu'il faut utiliser&amp;nbsp;? Est-ce qu'il est nécessaire de préciser que la surcharge d'une méthode virtuelle est elle-même virtuelle&amp;nbsp;? Faut-il utiliser les version post-fixée ou pré-fixées des opérateurs d&quot;incrémentation/décrémentation&amp;nbsp;?&lt;/p&gt;


&lt;p&gt;Je ne prétends pas vous donner une réponse définitive à ces questions, mais j'ai ma petite idée sur ce qu'il est préférable de faire.&lt;/p&gt;
&lt;div class=&quot;footnotes&quot;&gt;&lt;h4&gt;Notes&lt;/h4&gt;
&lt;p&gt;[&lt;a href=&quot;http://blog.emmanueldeloget.com/index.php?post/2010/02/04/154-const-x-x-ou-x-const-x#rev-pnote-154-1&quot; id=&quot;pnote-154-1&quot;&gt;1&lt;/a&gt;] si vous êtes un peu rouillé sur le sujet et que vous lisez relativement bien l'anglais, vous pouvez vous reporter à la &lt;a href=&quot;http://www.parashift.com/c++-faq-lite/const-correctness.html&quot; hreflang=&quot;en&quot;&gt;C++ FAQ Lite&lt;/a&gt;. Si vous êtes en plus rouillé en anglais, dirigez vous vers la &lt;a href=&quot;http://cpp.developpez.com/faq/cpp/?page=strings#STRINGS_difference_char_const_char&quot; hreflang=&quot;fr&quot;&gt;FAQ de dvp.com&lt;/a&gt;&lt;/p&gt;&lt;/div&gt;
    &lt;h3&gt;&lt;code&gt;const X&amp;amp; x&lt;/code&gt; contre &lt;code&gt;X const&amp;amp; x&lt;/code&gt;&lt;/h3&gt;

&lt;p&gt;En C++ comme en C, une déclaration se lit en anglais de la gauche vers la droite - sauf en ce qui concerne &lt;code&gt;const&lt;/code&gt;. En cas de doute, rappelez vous que ce mot-clef modifie la mutabilité de l'entité qui le précède. Ainsi, &lt;code&gt;X const* p&lt;/code&gt; est un pointeur vers un type X constant (c'est à dire que la valeur de p peut changer, mais pas la variable pointée par p), tandis que &lt;code&gt;X* const p&lt;/code&gt; est un pointeur constant vers un type X (c'est à dire que la valeur du pointeur ne peut pas changer, mais la variable pointée par p peut être modifiée). Cette étrange étrangeté rends le code C++ un peu plus compliqué à déchiffrer - comme s'il n'était pas assez compliqué comme ça.&lt;/p&gt;


&lt;p&gt;Élargissons un peu le problème. Une variable d'un type pointeur constant sur un type constant se déclare ainsi&amp;nbsp;:&lt;/p&gt;


&lt;pre&gt;X const* const p;&lt;/pre&gt;


&lt;p&gt;De cette manière, p n'est pas modifiable (pointeur constant) et la variable pointée par p ne l'est pas non plus (type constant). Cette déclaration est assez lisible, car le mot-clef &lt;code&gt;const&lt;/code&gt; est employé plusieurs fois. Qu'on enlève une seule occurrence du mot-clef, et la déclaration devient singulièrement plus complexe&amp;nbsp;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;le code est moins clair, parce deux interprétation proches sont possibles si on ne connait pas assez bien son standard C++.&lt;/li&gt;
&lt;li&gt;il y a une possibilité d'erreur lors de l'écriture du code, puisque l'inversion de &lt;code&gt;*&lt;/code&gt; et &lt;code&gt;const&lt;/code&gt; modifie le comportement du code de manière drastique.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;On peut aussi définir la même variable ainsi&amp;nbsp;:&lt;/p&gt;


&lt;pre&gt;const X* const p;&lt;/pre&gt;


&lt;p&gt;Cette définition est fonctionnellement équivalente, mais on la lit autrement - de gauche à droite, pour une fois&amp;nbsp;: il s'agit maintenant d'une variable constante de type pointeur sur un type constant. D'autre part, si on enlève le premier &lt;code&gt;const&lt;/code&gt; (et si on prends pour règle de ne jamais écrire &lt;code&gt;X const*&lt;/code&gt; à la place de &lt;code&gt;const X*&lt;/code&gt;), on réduit l'ambiguïté de la définition du type à la lecture puisqu'on ne confondra pas les deux formes &lt;code&gt;X const*&lt;/code&gt; et &lt;code&gt;X* const&lt;/code&gt;. Il est donc plus rassurant de définir une variable d'un type constant en préfixant le nom du type avec &lt;code&gt;const&lt;/code&gt; plutôt que de le mettre en suffixe.&lt;/p&gt;


&lt;p&gt;mais revenons à la question originelle&amp;nbsp;: le problème ne se pose pas en ces termes puisque les références C++ sont nécessairement constantes&amp;nbsp;: &lt;code&gt;X&amp;amp; const&lt;/code&gt; n'a donc pas de sens en C++, et il est impossible de le confondre avec &lt;code&gt;X const&amp;amp;&lt;/code&gt;. Mais puisqu'on préfère la notation &lt;code&gt;const X*&lt;/code&gt; à &lt;code&gt;X const*&lt;/code&gt;, il est logique et cohérent de préférer aussi &lt;code&gt;const X&amp;amp;&lt;/code&gt; à &lt;code&gt;X const&amp;amp;&lt;/code&gt;.&lt;/p&gt;


&lt;h3&gt;Je mets &lt;code&gt;virtual&lt;/code&gt; ou pas?&lt;/h3&gt;

&lt;p&gt;Soit la classe B&amp;nbsp;:&lt;/p&gt;


&lt;pre&gt;class B {
public:
  virtual void f() { }
}&lt;/pre&gt;


&lt;p&gt;Cette classe défini une méthode virtuelle &lt;code&gt;B::f()&lt;/code&gt;. Si je crée une classe &lt;code&gt;D&lt;/code&gt; qui hérite de &lt;code&gt;B&lt;/code&gt; afin de surcharger &lt;code&gt;f()&lt;/code&gt;, est-ce qu'il est nécessaire de préciser que &lt;code&gt;f()&lt;/code&gt; est virtuelle ou non&amp;nbsp;?&lt;/p&gt;


&lt;p&gt;Bien évidemment, non, ça n'est pas nécessaire&amp;nbsp;: la méthode héritée est déclarée virtuelle implicitement par le compilateur si aucune déclaration explicite n'est présente. Ainsi&amp;nbsp;:&lt;/p&gt;


&lt;pre&gt;class D : public B {
public:
  void f() { ... }
}&lt;/pre&gt;


&lt;p&gt;et&lt;/p&gt;


&lt;pre&gt;class D : public B {
public:
  virtual void f() { ... }
}&lt;/pre&gt;


&lt;p&gt;Sont des définitions strictement équivalentes. Dans ce cas, est il préférable de préciser explicitement que la méthode est virtuelle ou peut on se contenter du fait que le compilateur l'ajoute de manière implicite&amp;nbsp;?&lt;/p&gt;


&lt;p&gt;Rappelons nous que le code que nous écrivons n'est pas destiné à la machine - mais aux autres programmeurs&lt;sup&gt;[&lt;a href=&quot;http://blog.emmanueldeloget.com/index.php?post/2010/02/04/154-const-x-x-ou-x-const-x#pnote-154-1&quot; id=&quot;rev-pnote-154-1&quot;&gt;1&lt;/a&gt;]&lt;/sup&gt;. La première qualité d'un code source, c'est sa lisibilité. Par définition, une information implicite est une information manquante - elle dégrade la lisibilité. Par conséquent, il est toujours préférable d'être explicite lorsqu'on écrit du code. Ajoutons donc ces 8 caractères - ce n'est pas comme si ça allait provoquer une usure prématurée de votre clavier...&lt;/p&gt;


&lt;h3&gt;&lt;code&gt;v++&lt;/code&gt; contre &lt;code&gt;++v&lt;/code&gt;&lt;/h3&gt;

&lt;p&gt;Au moins, celle-la est simple. Les réponses aux autres questions sont largement dépendantes d'un style de programmation - mais la réponse à cette question a des implications techniques définies.&lt;/p&gt;


&lt;p&gt;Revenons quand même un peu sur les définitions&amp;nbsp;: l'opérateur postfixé (&lt;code&gt;v++&lt;/code&gt;) renvoie la valeur de v, puis incrémente la variable. L'opérateur préfixé &lt;code&gt;++v&lt;/code&gt;) incrémente d'abord la variable puis renvoie la valeur de celle-ci. Dans la plupart des cas, ces opérations d'incrémentation sont effectuées de manière unitaire, et on ne stocker même pas le résultat. Dans d'autres cas, le résultat nous importe. La réponse n°1 est donc triviale&amp;nbsp;: si le résultat de l'opération a une importance pour vous, alors la question ne se pose plus. Soit vous avez besoin de l'opérateur postfixé, soit vous avez besoin de l'opérateur préfixé, mais en aucun cas vous ne pouvez vous permettre de prendre un de ces deux opérateurs au hasard.&lt;/p&gt;


&lt;p&gt;Maintenant, il peut arriver que nous n'ayons pas besoin du résultat - seule l'opération d'incrémentation nous intéresse. Par exemple&amp;nbsp;:&lt;/p&gt;


&lt;pre&gt;for (int i=0; i&amp;lt;size(); i++) {
  ...
}&lt;/pre&gt;


&lt;p&gt;est strictement équivalent à&lt;/p&gt;


&lt;pre&gt;for (int i=0; i&amp;lt;size(); ++i) {
  ...
}&lt;/pre&gt;


&lt;p&gt;(le même code est généré puisque la partie qui récupère la valeur de i est supprimée par le compilateur lors d'une passe d'optimisation).&lt;/p&gt;


&lt;p&gt;A priori, les deux possibilités nous sont offertes, donc allons-y gaiment, et laissons la fonction &lt;code&gt;std::rand()&lt;/code&gt; décider pour nous de la notation à utiliser. Sauf que (bien évidemment, il y a un &quot;sauf que&quot;) l'équivalence stricte que j'ai avancé ci-dessus a une sévère limitation&amp;nbsp;: elle n'est valide que si la variable incrémentée est un type scalaire entier ou sur un pointeur. Hors, le C++ nous permet de redéfinir l'opérateur ++() sur n'importe quelle classe.&lt;/p&gt;


&lt;p&gt;L'exemple typique de redéfinition de ++() est l'itérateur du conteneur &lt;code&gt;std::vector&amp;lt;&amp;gt;&lt;/code&gt;.&lt;/p&gt;


&lt;pre&gt;typedef std::vector&amp;lt;type&amp;gt;::iterator itype;&lt;br /&gt;
for (itype i=v.begin(); i!=v.end(); &lt;strong&gt;???&lt;/strong&gt;) {
  ...
}&lt;/pre&gt;


&lt;p&gt;Doit on remplacer &lt;strong&gt;???&lt;/strong&gt; par un incrémentation de &lt;code&gt;i&lt;/code&gt; préfixée ou postfixée&amp;nbsp;? La réponse nous viens de la définition déjà donnée de ces opérateurs, et de la façon dont le compilateur les traite lorsqu'ils ont utilisé.&lt;/p&gt;


&lt;p&gt;Le compilateur est intelligent - mais il n'est pas pour autant le plus intelligent de vous deux. Lorsqu'il appelle une fonction, il ne peut pas se permettre de ne pas vider le code de cette fonction à des fins d'optimisation. Ce code peut avoir des effets de bord qu'il ignore, et qui peuvent modifier le comportement du programme. Par conséquent, il met le code complet de la fonction. Si ce code est inliné, il est possible qu'il puisse en éliminer une partie - mais c'est quand même plus difficile que ça en a l'air (ici, internal_state.advance() est l'opération qui effectue l'incrémentation sur l'état interne de l'instance).&lt;/p&gt;


&lt;p&gt;Le code typique d'un opérateur ++ préfixé est le suivant&amp;nbsp;:&lt;/p&gt;


&lt;pre&gt;{
  internal_state.advance();
  return *this;
}&lt;/pre&gt;


&lt;p&gt;Celui d'un opérateur postfixé correspondant est proche de&amp;nbsp;:&lt;/p&gt;


&lt;pre&gt;{
  T copy = *this;
  internal_state.advance();
  return copy;
}&lt;/pre&gt;


&lt;p&gt;L'opérateur postfixé, de part sa définition, a besoin de faire une copie de l'état précédant l'incrémentation - de manière à pouvoir retourner cet état. Sur des objets non triviaux, cette opération peut être coûteuse. Par conséquent, l'opérateur préfixé - qui n'a pas besoin de faire cette copie - est sensiblement plus rapide que la version postfixée.&lt;/p&gt;


&lt;p&gt;Lorsque le choix existe, on préfèrera dès lors utilisé la version préfixée de l'opérateur d'incrémentation (ou de décrémentation).&lt;/p&gt;
&lt;div class=&quot;footnotes&quot;&gt;&lt;h4&gt;Notes&lt;/h4&gt;
&lt;p&gt;[&lt;a href=&quot;http://blog.emmanueldeloget.com/index.php?post/2010/02/04/154-const-x-x-ou-x-const-x#rev-pnote-154-1&quot; id=&quot;pnote-154-1&quot;&gt;1&lt;/a&gt;] il pourrait vous arriver des mésaventures du genre &quot;analyse ce code source afin d'y trouver un bug, sachant que tu n'as pas d'accès aux librairies sur lesquelles ce code est basé et que tu ne peux pas le compiler&quot;. Avoir tous les outils et toutes les informations nécessaires à la résolution d'un problème est un luxe.&lt;/p&gt;&lt;/div&gt;
</description>
    
    
    
          <comments>http://blog.emmanueldeloget.com/index.php?post/2010/02/04/154-const-x-x-ou-x-const-x#comment-form</comments>
      <wfw:comment>http://blog.emmanueldeloget.com/index.php?post/2010/02/04/154-const-x-x-ou-x-const-x#comment-form</wfw:comment>
      <wfw:commentRss>http://blog.emmanueldeloget.com/index.php?feed/atom/comments/141</wfw:commentRss>
      </item>
    
  <item>
    <title>Visual Studio .Net 2010 (beta 2)</title>
    <link>http://blog.emmanueldeloget.com/index.php?post/2010/02/01/153-visual-studio-net-2010-beta-2</link>
    <guid isPermaLink="false">urn:md5:46d3dcc53b313ff613696bb0c79ed6bb</guid>
    <pubDate>Mon, 01 Feb 2010 14:00:00 +0000</pubDate>
    <dc:creator>Emmanuel Deloget</dc:creator>
        <category>News</category>
            
    <description>    &lt;p&gt;Les versions beta des outils de développement de la gamme Visual Studio .Net 2010 Express sont disponibles au téléchargement sur le site de Microsoft depuis quelques semaines déjà. Pour information, le compilateur intégré à l'IDE a été mis à jour et comprends un certain nombre de constructions décrites dans le futur standard du C++ (le bien nommé C++0x, ou x est maintenant un chiffre hexadécimal).&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;http://www.microsoft.com/express/Downloads/#2010-All&quot; hreflang=&quot;en&quot;&gt;Download des versions Express&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Les autres versions beta (Pro, Ultimate, ...) sont aussi disponibles en téléchargement gratuit&amp;nbsp;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;http://www.microsoft.com/visualstudio/en-us/try/default.mspx#download&quot; hreflang=&quot;en&quot;&gt;Download des versions complètes&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Ces versions s'arrêteront de fonctionner le 30 juin 2010 (vous avez donc largement le temps de les tester...).&lt;/p&gt;


&lt;p&gt;A noter que même si ce sont là des beta (attendez vous donc à quelques bugs), il n'en reste pas moins que les compilateurs proposés sont tout à fait valables. Le code généré peut ne pas être exempts de tout bug (ceci-dit, il est plus probable qu'il soit exempts de tout bug lié au compilateur ou aux librairies).&lt;/p&gt;


&lt;p&gt;A noter aussi que j'utilise VS 2010 beta 1 pour compiler le code lié à la série d'articles &lt;ins&gt;Implémentation d'un système de règle pour un jeu de rôle&lt;/ins&gt;. Je n'ai noté pour l'instant aucun problème majeur.&lt;/p&gt;</description>
    
    
    
          <comments>http://blog.emmanueldeloget.com/index.php?post/2010/02/01/153-visual-studio-net-2010-beta-2#comment-form</comments>
      <wfw:comment>http://blog.emmanueldeloget.com/index.php?post/2010/02/01/153-visual-studio-net-2010-beta-2#comment-form</wfw:comment>
      <wfw:commentRss>http://blog.emmanueldeloget.com/index.php?feed/atom/comments/140</wfw:commentRss>
      </item>
    
  <item>
    <title>gcc sous Windows ? C'est possible, mais...</title>
    <link>http://blog.emmanueldeloget.com/index.php?post/2010/01/18/152-gcc-sous-windows-c-est-possible-mais</link>
    <guid isPermaLink="false">urn:md5:ce49cfdf95a8efb3fbb7f38ab3f261d3</guid>
    <pubDate>Mon, 18 Jan 2010 14:00:00 +0000</pubDate>
    <dc:creator>Emmanuel Deloget</dc:creator>
        <category>Expériences</category>
            
    <description>&lt;p&gt;... c'est pas simple. A la lumière de ma propre expérience, voici quelques points noirs (parce que les points pas noir, ça n'aide pas vraiment à faire un choix, n'est-ce pas) sur les plateformes de développement Windows basées sur GCC.&lt;/p&gt;    &lt;h3&gt;Cygwin&lt;/h3&gt;


&lt;p&gt;Le tout intégré. Cygwin est un environnement qui émule vaguement le fonctionnement d'un Unix-like sous Windows. Le coeur de cygwin, c'est sa DLL cygwin.dll qui permet à une application d'utiliser un grand nombre de services POSIX sous Windows.&lt;/p&gt;


&lt;p&gt;C'est une bonne chose, surtout pour le portage d'applications ou de librairies. Ca ne va pas toutefois sans problèmes.&lt;/p&gt;


&lt;h5&gt;Installation&lt;/h5&gt;

&lt;p&gt;Le système d'installation est lourd et peu pratique à utiliser. A l'heure des gestionnaires de packages tel synaptic (Ubuntu), le système de cygwin montre d'ennuyeuses limites&amp;nbsp;: ainsi, la sélection des packages est peu claire. Difficile de voir aussi quelles vont être les dépendances d'un package. Encore plus difficile, comprendre quel package est installé dans l'environnement. De mes tests, il est carrément plus simple de générer un répertoire cygwin en installant tout sur une machine avec un bon débit en download et de copier le répertoire cygwin sur une autre machine que de tenter de réaliser la même installation sur deux machines différentes. C'est petit...&lt;/p&gt;


&lt;h5&gt;/bin/sh, ou la lenteur faite programme.&lt;/h5&gt;

&lt;p&gt;La version cygwin du shell (en fait bash) est d'un lenteur à faire peur. Un script un peu chargé (par exemple un script généré par les autotools GNU) peut mettre jusqu'à plusieurs minutes à s'exécuter là ou le même script nécessite quelques secondes sous Linux. Je ne comprends pas vraiment très bien les raisons de cette incroyable lenteur, mais elle est là. Et bien évidemment, si le script est sur un disque partagé, le résultat est encore pire...&lt;/p&gt;


&lt;h5&gt;Des soupçons sur la stabilité&amp;nbsp;?&lt;/h5&gt;

&lt;p&gt;Les binaires que j'ai générés (à partir d'une code source en C++) souffrent tous du même mal&amp;nbsp;: lorsqu'une exception est générée, le dépilement ne se fait pas correctement et la fonction &lt;code&gt;abort()&lt;/code&gt; est appelée dès qu'on quitte la fonction qui génère l'exception. Impossible de contrer le problème, et impossible d'en comprendre la source. Je soupçonne un problème dans la librairie de GCC fournie avec la distribution - mais ça peut être aussi un problème liés aux options de compilation utilisées.&lt;/p&gt;


&lt;h5&gt;Une documentation peu explicite...&lt;/h5&gt;


&lt;pre&gt;#include &amp;lt;iostream&amp;gt;&lt;br /&gt;
int main() 
{
 std::cout &amp;lt;&amp;lt; &quot;test&quot; &amp;lt;&amp;lt; std::endl
}&lt;/pre&gt;


&lt;p&gt;Ce code pourtant simple génère un warning au moment du link et le programme généré ne fonctionne carrément pas. C'est dommage, étant donné que cette option de compilation ésotérique est censée être activée par défaut sur cygwin. En cherchant bien, et malgré les informations données par GCC et l'aide en ligne de GCC, c'est l'option &lt;code&gt;--enable-runtime-pseudo-relocs&lt;/code&gt; qu'il faut utiliser à l'étape du linkage.&lt;/p&gt;


&lt;h3&gt;Mingw&lt;/h3&gt;


&lt;p&gt;Mingw est le concurrent de cygwin. Enfin, pas vraiment puisqu'il résout un problème différent&amp;nbsp;: la création d'applications standard Windows en utilisant le compilateur gcc (plutôt que le portage d'applications POSIX sur Windows).&lt;/p&gt;


&lt;h5&gt;Installation&lt;/h5&gt;

&lt;p&gt;L'installation de cygwin est complexe, mais au moins, tout est automatisé. En comparaison, l'installation de mingw est représentative de ce que j'appellerais &quot;la volonté de faire compliqué&quot;. En fait, si on veut un système vaguement équivalent à cygwin, il faut installer mingw, puis msys, puis ceci, puis cela, ... Le tout en passant par des download et des lignes de commande. Rébarbatif. Surtout quand on sait que généralement, les outils dont un développeur a besoin changent peu. Incroyable que ni les gens de cygwin ni les gens de mingw n'aient pensé à créer une archive avec le système complet pré-installé, histoire de gagner du temps (c'est mon employeur qui serait heureux&amp;nbsp;; j'aurais gagné une bonne demi-journée de travail...)&lt;/p&gt;


&lt;h5&gt;/bin/sh... ok, on sait déjà.&lt;/h5&gt;

&lt;p&gt;Mais ça n'empêche pas de revenir dessus. Le bash de mingw est lent, bien qu'il semble un poil plus rapide que celui de cygwin. Il reste néanmoins trop lent. Est-il si incroyablement complexe que personne n'ai pris le temps de comprendre d'où venait cette lenteur&amp;nbsp;? Les commentaires sur Internet parlent de 3 à 10 fois plus lent. C'est un peu trop à mon goût.&lt;/p&gt;


&lt;h5&gt;&quot;Faire semblant&quot; et &quot;faire semblant&quot;&lt;/h5&gt;

&lt;p&gt;Cygwin fait semblant d'être un OS avec une couche POSIX et y réussit relativement bien. MSYS fait semblant d'être une couche POSIX et échoue lamentablement. Il fait un peu trop semblant en fait. Le résultat, c'est un système de fichier complètement incompréhensible (franchement, &lt;code&gt;ls -l /&lt;/code&gt; ne renvoie aucun répertoire &lt;code&gt;/usr&lt;/code&gt;, ce qui n'empêche pas de faire &lt;code&gt;cd /usr&lt;/code&gt; - et de se retrouver dans &lt;code&gt;/&lt;/code&gt;. Enfin, je crois. Enfin, je ne comprends rien.). Sans compter que le système de montage de partitions est obscure, que /home/$user ne pointe pas sur le répertoire de l'utilisateur mais sur un répertoire spécialement créé, etc. Agaçant au possible.&lt;/p&gt;


&lt;h3&gt;Conclusion&lt;/h3&gt;


&lt;p&gt;Ces deux produits sont matures techniquement, mais souffrent d'un certain nombre de défauts qui ne facilitent pas leur utilisation en entreprise. Et bien sûr, j'en ai besoin (sinon, est-ce que ça serait ne serait-ce qu'un peu drôle&amp;nbsp;? Je vous le demande...)&lt;/p&gt;</description>
    
    
    
          <comments>http://blog.emmanueldeloget.com/index.php?post/2010/01/18/152-gcc-sous-windows-c-est-possible-mais#comment-form</comments>
      <wfw:comment>http://blog.emmanueldeloget.com/index.php?post/2010/01/18/152-gcc-sous-windows-c-est-possible-mais#comment-form</wfw:comment>
      <wfw:commentRss>http://blog.emmanueldeloget.com/index.php?feed/atom/comments/139</wfw:commentRss>
      </item>
    
  <item>
    <title>Noel, joyeux</title>
    <link>http://blog.emmanueldeloget.com/index.php?post/2009/12/27/151-noel-joyeux</link>
    <guid isPermaLink="false">urn:md5:52d69c3e88a0c44d1f15fc0f5b300c38</guid>
    <pubDate>Sun, 27 Dec 2009 10:07:59 +0000</pubDate>
    <dc:creator>Emmanuel Deloget</dc:creator>
        <category>General</category>
            
    <description>    &lt;p&gt;Je fais très court et sans complexe&amp;nbsp;: ce billet est entre avec mon nouveau téléphone portable. Ça y est, j'ai enfin un iPhone. Si vous y voyez un certain esprit de contradiction avec un témoignage récent, ben, heu, il y a de ça, ok.&lt;/p&gt;</description>
    
    
    
          <comments>http://blog.emmanueldeloget.com/index.php?post/2009/12/27/151-noel-joyeux#comment-form</comments>
      <wfw:comment>http://blog.emmanueldeloget.com/index.php?post/2009/12/27/151-noel-joyeux#comment-form</wfw:comment>
      <wfw:commentRss>http://blog.emmanueldeloget.com/index.php?feed/atom/comments/138</wfw:commentRss>
      </item>
    
  <item>
    <title>Quelques petites modifications...</title>
    <link>http://blog.emmanueldeloget.com/index.php?post/2009/12/18/149-quelques-petites-modifications</link>
    <guid isPermaLink="false">urn:md5:e1916bddbb69eb379420ff3999923a45</guid>
    <pubDate>Fri, 18 Dec 2009 13:30:00 +0000</pubDate>
    <dc:creator>Emmanuel Deloget</dc:creator>
        <category>General</category>
            
    <description>&lt;p&gt;Je me suis permis de changer quelques petites choses à la présentation de ce blog...&lt;/p&gt;    &lt;p&gt;Ainsi, la liste des tags est maintenant en haut de chaque page - vous n'avez qu'à cliquer sur &lt;strong&gt;Montrer tous les tags&lt;/strong&gt; pour qu'elle s'affiche. Cette solution me permet de libérer un peu de place dans le sidebar gauche, et d'augmenter la visibilité de certaines fonctions du blog (les liens de syndication sont maintenant en haut à droite&amp;nbsp;; avant, ils n'étaient visible qu'après avoir scrollé en bas de page).&lt;/p&gt;


&lt;p&gt;Le code pour montrer/cacher les tags:&lt;/p&gt;


&lt;pre&gt;&amp;lt;script type=&quot;text/javascript&quot;&amp;gt;
&amp;lt;!--
  function toggle_visibility(id, idTitle) {
    var e = document.getElementById(id);
    var t = document.getElementById(idTitle);
    if(e.style.display == 'block')
    {
      e.style.display = 'none';
      t.innerHTML = &quot;Montrer tous les tags&quot;;
    }
    else
    {
      e.style.display = 'block';
      t.innerHTML = &quot;Cacher tous les tags&quot;;
    }
  }
//--&amp;gt;
&amp;lt;/script&amp;gt;&lt;br /&gt;
&amp;lt;!-- debut tags --&amp;gt;
&amp;lt;div class=&quot;post&quot;&amp;gt;
  &amp;lt;div id=&quot;tagcloud&quot;&amp;gt;
    &amp;lt;h2&amp;gt;&amp;lt;a href=&quot;http://blog.emmanueldeloget.com/index.php?post/2009/12/18/149-quelques-petites-modifications#&quot; id=&quot;tagcloud_title&quot; 
      onclick=&quot;toggle_visibility('tagcloud_content','tagcloud_title')&quot;&amp;gt;Montrer tous les tags&amp;lt;/a&amp;gt;&amp;lt;/h2&amp;gt;
    &amp;lt;div id=&quot;tagcloud_content&quot; style=&quot;display:none;&quot;&amp;gt;
      &amp;lt;?php twTags::tagCloud($levels = 5, $block = '%s', $item = '&amp;lt;span class=&quot;level-%2$d&quot;&amp;gt;%1$s&amp;lt;/span&amp;gt;') ?&amp;gt;
    &amp;lt;/div&amp;gt;
  &amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;!-- fin tags --&amp;gt;&lt;/pre&gt;



&lt;p&gt;Voilà. C'est mieux, non&amp;nbsp;?&lt;/p&gt;</description>
    
    
    
          <comments>http://blog.emmanueldeloget.com/index.php?post/2009/12/18/149-quelques-petites-modifications#comment-form</comments>
      <wfw:comment>http://blog.emmanueldeloget.com/index.php?post/2009/12/18/149-quelques-petites-modifications#comment-form</wfw:comment>
      <wfw:commentRss>http://blog.emmanueldeloget.com/index.php?feed/atom/comments/136</wfw:commentRss>
      </item>
    
  <item>
    <title>Sortie prochaine de XQual XStudio v1.1</title>
    <link>http://blog.emmanueldeloget.com/index.php?post/2009/12/18/148-sortie-prochaine-de-xqual-xstudio-v11</link>
    <guid isPermaLink="false">urn:md5:7c1ab1fc043c7dd705a5465ea9ddfccb</guid>
    <pubDate>Fri, 18 Dec 2009 13:00:00 +0000</pubDate>
    <dc:creator>Emmanuel Deloget</dc:creator>
        <category>News</category>
            
    <description>&lt;p&gt;XQual va bientôt sortir la version 1.1 de son logiciel gratuit XStudio dont j'avais testé il y a déjà quelques temps la &lt;a href=&quot;http://blog.emmanueldeloget.com/index.php/2008/05/13/132-xqual-studio-04b3[fr&quot;&gt;version 0.4b3&lt;/a&gt;. Pour rappel, XStudio est un logiciel de management de tests ouvert, permettant de créer des campagnes de validation de tout type (tests unitaires, tests fonctionnels, ...) et produisant des rapports de grande qualité.&lt;/p&gt;    &lt;p&gt;Depuis la version 0.4b3, de nombreuses fonctionnalités se sont rajoutées. Il serait un peu complexe de toutes les citer ici, mais on peu citer les plus importantes&amp;nbsp;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Passage en GPL3&lt;/li&gt;
&lt;li&gt;100% graphique&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.xqual.com/resources/open_source/sdk/javadoc/index.html&quot; hreflang=&quot;en&quot;&gt;API simple et open source&lt;/a&gt; (LGPL3) pour le développement de nouveaux Launchers (à noter que la version 0.4b3 présentait deux lauchers - &lt;a href=&quot;http://www.xqual.com/open_source/launchers.html&quot; hreflang=&quot;en&quot;&gt;il y a une quinzaine maintenant&lt;/a&gt; - de quoi trouver votre bonheur).&lt;/li&gt;
&lt;li&gt;Support des tests manuels et automatiques&lt;/li&gt;
&lt;li&gt;Intégration avec Bugzilla (d'autres outils de tracking - Trac, Jira - sont prévus en version 1.2).&lt;/li&gt;
&lt;li&gt;Fonctionne sous Windows (XP, Vista, 7), Mac OS X (Snow Leopard) et Linux&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;La documentation a elle aussi beaucoup évolué - elle est plus complète, et propose de nombreux tutoriaux.&lt;/p&gt;


&lt;p&gt;Ce logiciel, maintenant en version stable (la version 1.0 est sortie fin novembre 2009), est un concurrent direct de certains packages commerciaux. Tous ceux qui souhaitent découvrir une solution de &lt;em&gt;test management&lt;/em&gt; fiable, efficace et peut couteuse se doivent de le tester au moins une fois. La prise en main est rapide, et les possibilités sont infinies (pour peu que vous ayez un programmeur Java disponible pour vous créer un launcher adaptés à vos besoins).&lt;/p&gt;


&lt;p&gt;Pour plus d'informations, vous pouvez vous rendre sur &lt;a href=&quot;http://www.xqual.com/&quot; hreflang=&quot;en&quot;&gt;le site web du produit&lt;/a&gt;.&lt;/p&gt;</description>
    
    
    
          <comments>http://blog.emmanueldeloget.com/index.php?post/2009/12/18/148-sortie-prochaine-de-xqual-xstudio-v11#comment-form</comments>
      <wfw:comment>http://blog.emmanueldeloget.com/index.php?post/2009/12/18/148-sortie-prochaine-de-xqual-xstudio-v11#comment-form</wfw:comment>
      <wfw:commentRss>http://blog.emmanueldeloget.com/index.php?feed/atom/comments/135</wfw:commentRss>
      </item>
    
  <item>
    <title>template&lt;typename T&gt; struct do_not_misuse</title>
    <link>http://blog.emmanueldeloget.com/index.php?post/2009/12/17/147-templatetypename-t-struct-do_not_misuse</link>
    <guid isPermaLink="false">urn:md5:a9f283635c0e05789597ab908ddb168e</guid>
    <pubDate>Thu, 17 Dec 2009 17:00:00 +0000</pubDate>
    <dc:creator>Emmanuel Deloget</dc:creator>
        <category>C++</category>
            
    <description>&lt;p&gt;En C++, être capable d'abstraire un type de données pour qu'il puisse être utilisé sous une forme paramétrée est à la fois tentant, amusant, difficile et très souvent inutile. Je vais laisser de coté le dernier point (j'y reviendrait peut-être dans un article futur, et ceux qui lisent ce blog régulièrement savent que j'ai déjà traité le sujet dans un &lt;a href=&quot;http://blog.emmanueldeloget.com/index.php/2007/02/22/52-tony-cox-premature-abstraction-is-the-root-of-all-evil&quot; hreflang=&quot;fr&quot;&gt;billet datant de 2007&lt;/a&gt;) pour me concentrer sur le précédent&amp;nbsp;: la difficulté intrinsèque liée à la programmation générique en C++.&lt;/p&gt;


&lt;p&gt;Mesdames et messieurs, venez vous assoir - le show va commencer...&lt;/p&gt;    &lt;h3&gt;Je code générique, donc je suis&lt;/h3&gt;

&lt;p&gt;Comme cette magnifique et chaleureuse introduction l'annonce, utiliser des techniques de méta-programmation ou de programmation générique en C++ a quelque chose d'étrangement attirant. On voit bien que le code peut devenir excessivement complexe, certains points de détails nous échappent royalement (dans de nombreux cas, je soupçonne les développeurs de ne même pas en avoir conscience), et bizarrement, c'est ce coté extrêmement technique de l'écriture de template en C++ qui fait aussi sa popularité. Au programmeur débutant, il semble que les templates peuvent tout faire. Au programmeur intermédiaire, il apparaît que les templates sont une solution possible à nombre de ses propres problèmes. Au programmeur chevronné, les templates sont un outil d'une puissance incomparable qu'il convient d'utiliser de manière innovante pour résoudre des problèmes qui, soyons honnêtes, n'existent pas forcément dans d'autres langages... Et finalement, à l'ethnologue qui observe ces trois programmeurs, les templates sont une sorte de déité sortie tout droit de l'inconscient de ses adorateurs.&lt;/p&gt;


&lt;p&gt;Il est vrai que la complexité des templates est un véritable challenge pour un programmeur - quel que soit son niveau. Plutôt que de vous dire que vous ne devriez pas vous y frotter, cet article va plutôt s'attacher à vous lister quelques points auxquels vous devez penser lorsque vous touchez aux templates en C++ - autrement appelé des Bonnes Pratiques&lt;sup&gt;[&lt;a href=&quot;http://blog.emmanueldeloget.com/index.php?post/2009/12/17/147-templatetypename-t-struct-do_not_misuse#pnote-147-1&quot; id=&quot;rev-pnote-147-1&quot;&gt;1&lt;/a&gt;]&lt;/sup&gt;.&lt;/p&gt;


&lt;h3&gt;Redéfinir les types paramètre&lt;/h3&gt;

&lt;p&gt;Un type de donnée quelconque utilisé dans la définition d'une classe template et faisant partie de l'interface publique de cette classe doit être redéfini sous la forme d'un type de donnée appartenant à la classe template.&lt;/p&gt;


&lt;p&gt;&lt;em&gt;Exemple&lt;/em&gt;:&lt;/p&gt;


&lt;pre&gt;template &amp;lt;class T&amp;gt;
struct type
{
  &lt;strong&gt;typedef T value_type;&lt;/strong&gt;
  bool operator()(const &lt;strong&gt;value_type&lt;/strong&gt;&amp;amp; a, const &lt;strong&gt;value_type&lt;/strong&gt;&amp;amp; b)
  { ... }
};&lt;/pre&gt;


&lt;p&gt;Il y a plusieurs raisons pour ça&amp;nbsp;: la première est que cette redéfinition est une abstraction dont vont dépendre les détails de l'implémentation. Dans la définition précédente, si je change T, je n'ai qu'une ligne à changer. Si je n'ai pas défini un type alias alors une modification de T pourrait avoir un impact sur toute la définition de l'interface. Deuxièmement, si &lt;code&gt;type&amp;lt;T&amp;gt;&lt;/code&gt; est utilisé à son tour comme argument d'une classe template, il peut m'être impossible de déterminer T et donc de baser mes traitements sur les particularités de ce type. Ce n'est plus le cas dans notre définition, car je peux retrouver T via &lt;code&gt;type&amp;lt;T&amp;gt;::value_type&lt;/code&gt;.&lt;/p&gt;


&lt;p&gt;C'est vrai pour tous les types de données qui peuvent être utilisés dans l'interface publique de la classe.&lt;/p&gt;


&lt;pre&gt;template &amp;lt;class T&amp;gt;
class t_collection
{
public:
  &lt;strong&gt;typedef std::vector&amp;lt;T&amp;gt; vector_type;&lt;/strong&gt;
  &lt;strong&gt;typedef typename std::vector&amp;lt;T&amp;gt;::iterator iterator_type;&lt;/strong&gt;&lt;br /&gt;
private:
  vector_type m_vector;&lt;br /&gt;
public:
  t_collection(const vector_type&amp;amp; in) { ... }
  t_collection(iterator_type first, iterator_type end) { .. }
  iterator_type begin() { ... }
  iterator_type end() { ... }
};&lt;/pre&gt;


&lt;p&gt;N'oubliez pas que dans certains cas, vous pouvez avoir besoin d'utiliser le mot-clef &lt;code&gt;typename&lt;/code&gt;&lt;/p&gt;


&lt;h3&gt;N'oubliez pas les exceptions&lt;/h3&gt;

&lt;p&gt;Votre code template a l'obligation d'être résistant aux exceptions. En termes simples, cela signifie qu'une exception générée par votre code (et donc, bien évidemment, par le code que vous appelez) ne doit pas mettre en péril l'invariant de votre classe ni créer de &lt;em&gt;resource leak&lt;/em&gt;. La manière la plus simple de procéder et de faire en sorte de n'effectuer aucune modification de l'état interne de votre classe tant qu'il est encore possible qu'une exception soit levée.&lt;/p&gt;


&lt;p&gt;Cet exemple n'est pas résistant aux exceptions&amp;nbsp;:&lt;/p&gt;


&lt;pre&gt;template &amp;lt;class T&amp;gt;
class type
{
public:
  typedef T value_type;
  typedef const value_type&amp;amp; cr_value_type;
  typedef value_type* p_value_type;&lt;br /&gt;
private:
  p_value_type m_array;
  std::size_t m_size;&lt;br /&gt;
public:
  type() : m_array(NULL), m_size(0) { }&lt;br /&gt;
  void add(cr_value_type value)
  {
    p_value_type array = new value_type[m_size + 1];
    array[m_size] = value;
    ++m_size;
    delete m_array;
    m_array = array;
  }
};&lt;/pre&gt;


&lt;p&gt;Le code de &lt;code&gt;add()&lt;/code&gt; est &lt;em&gt;presque&lt;/em&gt; correct. Lu de cette manière, il n'y a guère de doute qu'il fonctionne. Que se passe-t-il si on utiliser cette classe &lt;code&gt;misuse&lt;/code&gt; en lieu et place du paramètre T&amp;nbsp;?&lt;/p&gt;


&lt;pre&gt;struct misuse
{
...
  misuse&amp;amp; operator=(const misuse&amp;amp; other)
  {
    if (!other.allow_copy()) throw std::runtime_error(&quot;instance does not allow copy&quot;);
    ...
    return *this;
  }
...
};&lt;/pre&gt;


&lt;p&gt;Vous avez bien lu, une exception est générée par &lt;code&gt;operator=()&lt;/code&gt;. Tout à coup, un problème se pose dans le code de &lt;code&gt;type&amp;lt;T&amp;gt;::add()&lt;/code&gt;&amp;nbsp;: au cas ou une exception est générée par la seconde ligne, alors la mémoire allouée à la première ligne est perdue. Et maintenant, la question que vous vous posez est&amp;nbsp;: comment éviter le problème&amp;nbsp;? Vous n'avez pas accès au code de &lt;code&gt;misuse&lt;/code&gt;, donc vous ne devez modifier que &lt;code&gt;type&amp;lt;T&amp;gt;&lt;/code&gt;. La solution la plus simple est de récupérer les exceptions (dans un bloc try/catch), nettoyer ce qui doit l'être avant de relancer l'exception reçue. Honnêtement, ce n'est pas particulièrement beau.&lt;/p&gt;


&lt;p&gt;L'autre solution est d'utiliser des techniques telle que &lt;a href=&quot;http://blog.emmanueldeloget.com/index.php/2007/02/08/49-raii&quot; hreflang=&quot;fr&quot;&gt;RAII&lt;/a&gt; en conjonction avec d'autre mécanismes de protection tel que par exemple &lt;a href=&quot;http://en.wikibooks.org/wiki/More_C%2B%2B_Idioms/Copy-and-swap&quot; hreflang=&quot;en&quot;&gt;l'idiome swap&lt;/a&gt;.&lt;/p&gt;


&lt;p&gt;Ainsi, par exemple&amp;nbsp;:&lt;/p&gt;


&lt;pre&gt;template &amp;lt;class T&amp;gt;
class type
{
public:
  typedef T value_type;
  typedef const value_type&amp;amp; cr_value_type;
  typedef value_type* p_value_type;&lt;br /&gt;
private:
  &lt;strong&gt;class array_container&lt;/strong&gt;
  &lt;strong&gt;{&lt;/strong&gt;
    &lt;strong&gt;p_value_type m_array;&lt;/strong&gt;
    &lt;strong&gt;std::size_t    m_size;&lt;/strong&gt;
  &lt;strong&gt;public:&lt;/strong&gt;
    &lt;strong&gt;array_container(std::size_t n) : m_array(new value_type&lt;a href=&quot;http://blog.emmanueldeloget.com/index.php?post/2009/12/17/n&quot;&gt;n&lt;/a&gt;), m_size(n) { }&lt;/strong&gt;
    &lt;strong&gt;~array_container() { delete m_array; }&lt;/strong&gt;
    &lt;strong&gt;void swap(array_container&amp;amp; other) throw ()&lt;/strong&gt;
    &lt;strong&gt;{&lt;/strong&gt;
      &lt;strong&gt;std::swap(m_array, other.m_array);&lt;/strong&gt;
      &lt;strong&gt;std::swap(m_size, other.m_size);&lt;/strong&gt;
    &lt;strong&gt;}&lt;/strong&gt;
    &lt;strong&gt;std::size_t size() const { return m_size; }&lt;/strong&gt;
  &lt;strong&gt;};&lt;/strong&gt;&lt;br /&gt;
  array_container m_array;&lt;br /&gt;
public:
  type() : m_array(NULL), m_size(0) { }&lt;br /&gt;
  void add(cr_value_type value)
  {
    &lt;strong&gt;array_container other_array(m_array.size() + 1);&lt;/strong&gt;
    &lt;strong&gt;other_array[m_array.size()] = value;&lt;/strong&gt;
    &lt;strong&gt;other_array.swap(m_array);&lt;/strong&gt;
  }
};&lt;/pre&gt;


&lt;p&gt;Que se passe-t-il dans ce cas&amp;nbsp;? Si une exception est générée au moment de la copie de &lt;code&gt;value&lt;/code&gt;, &lt;code&gt;type&amp;lt;T&amp;gt;::array_container::swap()&lt;/code&gt; n'aura pas lieu. Le contenu de &lt;code&gt;m_array&lt;/code&gt; n'est donc pas modifié (l'invariant est donc conservé). De plus, le destructeur de &lt;code&gt;type&amp;lt;T&amp;gt;::array_container&lt;/code&gt; sera appelé pour détruire l'instance &lt;code&gt;other&lt;/code&gt;. La mémoire allouée sera donc libérée.&lt;/p&gt;


&lt;h3&gt;Élargissez l'utilisation de votre template au maximum&lt;/h3&gt;

&lt;p&gt;Est-ce que votre classe template ne fonctionne que sur un nombre réduit de type&amp;nbsp;? Si oui, peut-être est-ce parce que c'est un mauvais candidat à la généralisation. Une autre raison est que vous avez mis des contraintes trop fortes sur le type de donnée qui peut être passé en paramètre. Dans la plupart des cas, c'est parce que vous utilisez les connaissances que vous possédez sur la classe paramètre.&lt;/p&gt;


&lt;pre&gt;template &amp;lt;class T&amp;gt;
struct type
{
  typedef T value_type;&lt;br /&gt;
  void call_func(const value_type&amp;amp; value) const 
  { value.func(); }
};&lt;/pre&gt;


&lt;p&gt;Vous en avez parfaitement le droit. Au moment de l'instanciation, le compilateur va vérifier que la classe T possède bien une méthode &lt;code&gt;T::func()&lt;/code&gt; et va générer une erreur dans le cas contraire. Cependant, toutes les classes ne définissent pas cette méthode &lt;code&gt;T::func()&lt;/code&gt; dont vous avez pourtant besoin.&lt;/p&gt;


&lt;p&gt;La solution est de passer par des &lt;a href=&quot;http://blog.emmanueldeloget.com/index.php/2006/12/21/45-tr1-type_traits&quot; hreflang=&quot;fr&quot;&gt;type traits&lt;/a&gt; et des &lt;em&gt;&lt;a href=&quot;http://en.wikipedia.org/wiki/Policy-based_design&quot; hreflang=&quot;en&quot;&gt;policies&lt;/a&gt;&lt;/em&gt;&lt;sup&gt;[&lt;a href=&quot;http://blog.emmanueldeloget.com/index.php?post/2009/12/17/147-templatetypename-t-struct-do_not_misuse#pnote-147-2&quot; id=&quot;rev-pnote-147-2&quot;&gt;2&lt;/a&gt;]&lt;/sup&gt;.&lt;/p&gt;


&lt;p&gt;Dans cet exemple, on peut faire&amp;nbsp;:&lt;/p&gt;


&lt;pre&gt;template &amp;lt;class T, class P = policy&amp;lt;T&amp;gt; &amp;gt;
strut type
{
  typedef P policy_type;
  typedef T value_type;&lt;br /&gt;
  void call_func(const value_type&amp;amp; value) const
  {
     policy_type&amp;lt;T&amp;gt;::call_func(value);
  }
};&lt;/pre&gt;


&lt;p&gt;Et on défini la classe policy:&lt;/p&gt;


&lt;pre&gt;&lt;em&gt;// par défaut, ne défini rien...&lt;/em&gt;
template &amp;lt;class T&amp;gt; class policy { };&lt;br /&gt;
template &amp;lt;&amp;gt;
class policy&amp;lt;mon_type_a&amp;gt;
{
  static void call_func(const mon_type&amp;amp; value)
  { value.function_a(); }
};&lt;br /&gt;
template &amp;lt;&amp;gt;
class policy&amp;lt;mon_type_b&amp;gt;
{
  static void call_func(const mon_type&amp;amp; value)
  { value.function_b(); }
};&lt;/pre&gt;


&lt;p&gt;Pour permettre à &lt;code&gt;type&amp;lt;T&amp;gt;&lt;/code&gt; de manipuler un type T qui ne contient pas de méthode &lt;code&gt;func&lt;/code&gt;, il suffit de créer la &lt;em&gt;policy&lt;/em&gt; correspondante.&lt;/p&gt;


&lt;h3&gt;Respectez le &lt;a href=&quot;http://c2.com/cgi/wiki?PrincipleOfLeastAstonishment&quot; hreflang=&quot;en&quot;&gt;principe de moindre surprise&lt;/a&gt;&lt;/h3&gt;

&lt;p&gt;Les template permettent, par le biais de spécialisations et autre amusements divers, de redéfinir des comportements qui sont parfois très différent selon les paramètres qui sont utilisés pour l'instanciation du template. Un exemple avec la fonction &lt;code&gt;std::advance&lt;/code&gt;, qui avance un itérateur d'un certain nombre de pas. Si l'itérateur en question est un itérateur à accès aléatoire (par exemple &lt;code&gt;std::vector&amp;lt;&amp;gt;::iterator&lt;/code&gt;), &lt;code&gt;std::advance&lt;/code&gt; va simplement utiilser son operator+(). Si l'itérateur ne propose qu'un accès séquentiel (par exemple &lt;code&gt;std::list&amp;lt;&amp;gt;::iterator&lt;/code&gt;), &lt;code&gt;std::advance&lt;/code&gt; va boucler sur l'appel de l'operator++().&lt;/p&gt;


&lt;p&gt;Plus généralement, évitez de changer du tout au tout le comportement d'une classe en fonction des paramètres qui lui sont donnée, à moins que ce changement notable de comportement ne soit induit par le design lui-même.&lt;/p&gt;
&lt;div class=&quot;footnotes&quot;&gt;&lt;h4&gt;Notes&lt;/h4&gt;
&lt;p&gt;[&lt;a href=&quot;http://blog.emmanueldeloget.com/index.php?post/2009/12/17/147-templatetypename-t-struct-do_not_misuse#rev-pnote-147-1&quot; id=&quot;pnote-147-1&quot;&gt;1&lt;/a&gt;] Attention: des fois, ça pique les yeux.&lt;/p&gt;
&lt;p&gt;[&lt;a href=&quot;http://blog.emmanueldeloget.com/index.php?post/2009/12/17/147-templatetypename-t-struct-do_not_misuse#rev-pnote-147-2&quot; id=&quot;pnote-147-2&quot;&gt;2&lt;/a&gt;] Faute de meilleur terme...&lt;/p&gt;&lt;/div&gt;
</description>
    
    
    
          <comments>http://blog.emmanueldeloget.com/index.php?post/2009/12/17/147-templatetypename-t-struct-do_not_misuse#comment-form</comments>
      <wfw:comment>http://blog.emmanueldeloget.com/index.php?post/2009/12/17/147-templatetypename-t-struct-do_not_misuse#comment-form</wfw:comment>
      <wfw:commentRss>http://blog.emmanueldeloget.com/index.php?feed/atom/comments/134</wfw:commentRss>
      </item>
    
  <item>
    <title>Mac OS X - je t'aime !</title>
    <link>http://blog.emmanueldeloget.com/index.php?post/2009/12/09/146-mac-os-x-je-t-aime</link>
    <guid isPermaLink="false">urn:md5:8830f3fa500a3d903abd4c6cfc3c4247</guid>
    <pubDate>Wed, 09 Dec 2009 18:00:00 +0000</pubDate>
    <dc:creator>Emmanuel Deloget</dc:creator>
        <category>Opinions</category>
            
    <description>&lt;p&gt;Et pas qu'un peu&amp;nbsp;! Qui pourrait oser prétendre que ce système, extrêmement bien conçu, mériterait de s'attirer mes foudres&amp;nbsp;? Certainement pas vous. Et pour vous remercier de votre sollicitude, je vous présente un tour d'horizon des raisons pour lesquelles je suis tombé amoureux des petites machines de firme de Cupertino.&lt;/p&gt;    &lt;h3&gt;L'auguste machine&amp;nbsp;: le rêve des programmeurs&lt;/h3&gt;

&lt;p&gt;Oh mon dieu qu'elle est jolie&amp;nbsp;! J'ai sous les yeux deux superbes bêtes&amp;nbsp;: un iBook G4 fonctionnant sous Mac OS X 10.4.11 et un MacBook (intel) fonctionnant sous Mac OS X 10.5.8. Et pour le développeur que je suis, ces machines sont une véritable révolution.&lt;/p&gt;


&lt;p&gt;Dans un premier temps, ce qui frappe, c'est l'indéniable chance qu'on les utilisateurs de Mac de n'avoir besoin que d'un seul et unique bouton sur leur souris. Pour avoir accès aux fonctions qui seraient accessibles en un clic si le pad présentait deux boutons, il suffit de jouer avec ces mignonnes touches poétiquement nommées &lt;em&gt;Pomme&lt;/em&gt; et &lt;em&gt;Fleur&lt;/em&gt; ou (plus prosaïquement) &quot;Ctrl&quot; ou &quot;Shift&quot;. Un clic sur le bouton droit devient ainsi &lt;em&gt;Ctrl+bouton&lt;/em&gt;. C'est tellement plus simple que je me demande pourquoi les constructeurs PC font la course aux boutons.&lt;/p&gt;


&lt;p&gt;Et en parlant du clavier, que dire&amp;nbsp;? il est magnifique et fonctionnel. On pourrait regretter son léger manque de réponse, qui donne un peu l'impression d'appuyer dans du pudding pas assez cuit, mais n'y voyez pas là une critique&amp;nbsp;: je préfère. Comme ça, je suis obligé de faire très attention à ce que j'écris histoire d'éviter de l'écrire deux fois. Passé la fausse impression de perte de temps qui en découle, cette technique finit par s'avérer très reposante pour l'esprit et les doigts. Certains mauvais esprits penserait que certaines touches manquent&amp;nbsp;: ou sont les touches |, {, ou encore }&amp;nbsp;? Soyez franc&amp;nbsp;: en tant que programmeur, vous les utilisez souvent ces touches&amp;nbsp;? Si vous le faite, vous ne devriez pas. Pourquoi perdre son temps avec un langage basé sur les paradigmes d'un C ancestral lorsque des langages de nouvelle génération aussi puissants que le Basic nous tendent les bras&amp;nbsp;? Soyez un peu sérieux quand même, et sachez vous remettre en question&amp;nbsp;! Ce clavier est parfait - il rompt vos mauvaise habitudes acquises durant des années de travail sur des systèmes très inférieurs à celui d'Apple. Ainsi, oubliez la touche &quot;AltGr&quot; - rien que le nom fait froid dans le dos. Ne soyez pas affolé des changements de position de certaines touches comme '-' ou '_', qui se transforment respectivement en '§' et '!' sur le beau clavier tout blanc de mon MacBook. La raison principale de cette modification est que ces dernières touches sont trop peu usitées. Alors afin d'assurer leur promotion, elles ont été placées à une position plus centrale et plus visible.&lt;/p&gt;


&lt;h3&gt;Un système en avance sur son temps&lt;/h3&gt;

&lt;p&gt;Vous avez programmé une application pour un OS quelconque récemment&amp;nbsp;? Peut être avez vous utilisé un langage bas de gamme tel que le C ou l'horrible C++. Franchement, vous êtes dépassé&amp;nbsp;: l'avenir est à Objective-C, un langage magnifique offrant une véritable implémentation objet au dessus de C. Tellement au dessus qu'en fait, le -C à la fin du nom n'est là que pour rassurer les programmeurs vieillissants engoncés dans leurs mauvaises pratiques de programmation au rabais. Objective-C, c'est le futur.&lt;/p&gt;


&lt;p&gt;HelloWorld.h&lt;/p&gt;

&lt;pre&gt;#import &amp;lt;Foundation/Foundation.h&amp;gt;&lt;br /&gt;
@interface HelloWorld : NSObject {
  // no instance variables
}&lt;br /&gt;
// methods
- (void)sayHello;&lt;br /&gt;
@end&lt;/pre&gt;


&lt;p&gt;HelloWorld.m&lt;sup&gt;[&lt;a href=&quot;http://blog.emmanueldeloget.com/index.php?post/2009/12/09/146-mac-os-x-je-t-aime#pnote-146-1&quot; id=&quot;rev-pnote-146-1&quot;&gt;1&lt;/a&gt;]&lt;/sup&gt;&lt;/p&gt;

&lt;pre&gt;#import &quot;HelloWorld.h&quot;&lt;br /&gt;
@implementation HelloWorld&lt;br /&gt;
- (void)sayHello
{
  NSLog(@&quot;Hello, world, at %@&quot;, [NSCalendarDate calendarDate]);
}&lt;br /&gt;
@end&lt;/pre&gt;


&lt;p&gt;main.m&lt;/p&gt;

&lt;pre&gt;#import &amp;lt;Foundation/Foundation.h&amp;gt;
#import &quot;HelloWorld.h&quot;&lt;br /&gt;
int main (int argc, const char * argv&lt;a href=&quot;http://blog.emmanueldeloget.com/index.php?post/2009/12/09/&quot;&gt;&lt;/a&gt;) {
  NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];&lt;br /&gt;
  // my stuff
  HelloWorld *hw = [[HelloWorld alloc] init];
  [hw autorelease];&lt;br /&gt;
  [hw sayHello];&lt;br /&gt;
  [pool release];
  return 0;
}&lt;/pre&gt;


&lt;p&gt;C'est quand même bien plus clair que le même programme écrit en C, n'est-ce pas&amp;nbsp;?&lt;/p&gt;


&lt;h3&gt;Des documents de partout!&lt;/h3&gt;

&lt;p&gt;Prenons le fabuleux &lt;em&gt;darwinbuild&lt;/em&gt;, un outil permettant entre autre le développement de modifications dans le kernel XNU (la base Open Source de Mac OS X&amp;nbsp;; oui, la base est Open Source. Mais le kernel d'un Mac OS X n'est pas Open Source. Chez Apple, on est pas des sales communistes. On préfère nettement récupérer les modifications des utilisateurs, les incorporer dans un système propriétaire, et fermer le tout en empêchant toute modification ultérieure. Il ne faut pas exagérer non plus: l'Open Source est dangereux pour les vendeurs de logiciels). Les derniers mots de la &lt;a href=&quot;http://darwinbuild.macosforge.org/&quot; hreflang=&quot;en&quot;&gt;page d'accueil de cet outil&lt;/a&gt; sont&amp;nbsp;:&lt;/p&gt;


&lt;blockquote&gt;&lt;p&gt;If you are interested in building and modifying Darwin projects, the documentation on this website, and the DarwinBuild tools, will prove to be an invaluable resource.&lt;/p&gt;&lt;/blockquote&gt;


&lt;p&gt;Et c'est vrai&amp;nbsp;! La documentation de ce site web (c'est à dire, cette page d'accueil et la page d'accueil du wiki) sont claire et concise - une prouesse, quand on connait la complexité du système&amp;nbsp;! Le système Mac étant un système simple, il est vrai qu'un outil aussi complet que darwinbuild ne pouvait être que simple d'utilisation. Et bien évidemment, c'est le cas&amp;nbsp;: seules 15 options de ligne de commande possible. Seules les plus compliquées sont documentées, parce que les autres parlent d'elle même (franchement, il faut être un peu lent d'esprit pour ne pas comprendre ce que &lt;code&gt;darwnibuild -nochroot -build=&lt;em&gt;bname&lt;/em&gt; &lt;em&gt;project&lt;/em&gt;&lt;/code&gt; va faire).&lt;/p&gt;


&lt;h3&gt;En conclusion&lt;/h3&gt;

&lt;p&gt;Mac OS X est un excellent système, particulièrement étudié pour que vous ne puissiez pas vous y retrouver si vous avez ne serait-ce que 3 minutes d'expérience avec un autre système d'exploitation. Il est très simple d'utilisation, surtout si vous ne voulez pas faire autre chose que regarder le magnifique écran aux chatoyantes couleurs. Il épouse parfaitement le paradigme de simplicité offert par le hardware le supportant.&lt;/p&gt;

&lt;pre&gt;&lt;/pre&gt;

&lt;p&gt;Et dire qu'il y a quelques mois, j'ai failli acheter un mac...&lt;/p&gt;
&lt;div class=&quot;footnotes&quot;&gt;&lt;h4&gt;Notes&lt;/h4&gt;
&lt;p&gt;[&lt;a href=&quot;http://blog.emmanueldeloget.com/index.php?post/2009/12/09/146-mac-os-x-je-t-aime#rev-pnote-146-1&quot; id=&quot;pnote-146-1&quot;&gt;1&lt;/a&gt;] '.m' est l'extension des fichiers d'implémentation de Objective-C. Ca vient de... En fait, je sais pas d'où ça peut venir.&lt;/p&gt;&lt;/div&gt;
</description>
    
    
    
          <comments>http://blog.emmanueldeloget.com/index.php?post/2009/12/09/146-mac-os-x-je-t-aime#comment-form</comments>
      <wfw:comment>http://blog.emmanueldeloget.com/index.php?post/2009/12/09/146-mac-os-x-je-t-aime#comment-form</wfw:comment>
      <wfw:commentRss>http://blog.emmanueldeloget.com/index.php?feed/atom/comments/133</wfw:commentRss>
      </item>
    
  <item>
    <title>Implémentation d'un système de règle pour un jeu de rôle - Retour à nos problèmes</title>
    <link>http://blog.emmanueldeloget.com/index.php?post/2009/12/06/145-implementation-d-un-systeme-de-regle-pour-un-jeu-de-role-retour-a-nos-problemes</link>
    <guid isPermaLink="false">urn:md5:9cbc61f9104b0e60c231fea2d580ff6d</guid>
    <pubDate>Sun, 06 Dec 2009 15:30:00 +0000</pubDate>
    <dc:creator>Emmanuel Deloget</dc:creator>
        <category>Architecture Orientée Objet</category>
            
    <description>&lt;p&gt;Après avoir bien étudié les possibilités qui s'offrent à nous pour éviter de tomber dans le piège terrible des références circulaires, nous pouvons reprendre notre petit bonhomme de chemin et étudier un peu plus les besoin liés à l'implémentation d'un système de règle pour un jeu de rôle, et même commencer à proposer des solutions.&lt;/p&gt;


&lt;p&gt;&lt;strong&gt;Mise à jour&lt;/strong&gt;&amp;nbsp;: le code source qui met en oeuvre la technique présentée dans ce billet &lt;a href=&quot;http://download.emmanueldeloget.com/libdnd4/libdnd4-0.2.tar.gz&quot; hreflang=&quot;zp&quot;&gt;est disponible&lt;/a&gt;. Gardez en mémoire qu'il ne s'agit pour l'instant que d'un début - il est fort possible que l'ensemble évolue très rapidement. Le code source est compilable sous linux (./configure &amp;amp;&amp;amp; make &amp;amp;&amp;amp; make check) et sous Windows avec Visual Studio 2008 (au moins&amp;nbsp;; quelques warnings subsistent). Bien évidemment, il s'agit de C++, et l'ensemble du système de gestion de message est basé sur des classes template - de manière à maximiser sa réutilisation future. Amusez vous bien avec ce code source&amp;nbsp;!&lt;/p&gt;    &lt;h3&gt;Petit rappel&lt;/h3&gt;


&lt;p&gt;Vous vous rappelez de ce schéma, publié dans &lt;a href=&quot;http://blog.emmanueldeloget.com/index.php/2009/10/26/141-implementation-d-un-systeme-de-regle-pour-un-jeu-de-role-analyse-des-besoins&quot; hreflang=&quot;fr&quot;&gt;le second article de cette série&lt;/a&gt;&amp;nbsp;?&lt;/p&gt;


&lt;p&gt;&lt;img src=&quot;http://blog.emmanueldeloget.com/public/jeu-de-role/rpg-character-closed-system.png&quot; alt=&quot;rpg-character-closed-system.png&quot; style=&quot;display:block; margin:0 auto;&quot; title=&quot;rpg-character-closed-system.png, mar. 2010&quot; /&gt;&lt;/p&gt;


&lt;p&gt;&lt;a href=&quot;http://blog.emmanueldeloget.com/index.php/2009/11/23/143-implementation-d-un-systeme-de-regle-pour-un-jeu-de-role-cassons-la-circularite&quot; hreflang=&quot;fr&quot;&gt;L'article précédent&lt;/a&gt; nous a donné les outils qui vont nous permettre de casser une partie de ces liens et ainsi nous donner la possibilité d'implémenter ce système - et même plus.&lt;/p&gt;


&lt;p&gt;Cet article continue de considérer le personnage comme étant un système fermé, de manière à ne pas s'encombrer des difficultés supplémentaires liées à son intégration dans un environnement encore plus complexe que lui. On verra dans les articles suivants que cette approche ne fait que nous donner une base de travail, sans pour autant nous fournir la solution correcte au problème pris dans son ensemble.&lt;/p&gt;


&lt;h3&gt;Le livreur de lait - du producteur au consommateur&lt;/h3&gt;


&lt;p&gt;Ceux qui lisent régulièrement ces pages savent qu'il existe des solutions efficaces pour répondre au problème de la transmission de messages. Le sujet a été traité en particulier dans la série &lt;em&gt;Du contrôle des fenêtres&lt;/em&gt;, et notamment dans &lt;a href=&quot;http://blog.emmanueldeloget.com/index.php/2007/05/09/74-du-controle-des-fenetres-premiere-partie&quot; hreflang=&quot;fr&quot;&gt;la première partie de cette série&lt;/a&gt;. Cependant, la solution mise en œuvre était à ce moment très liée à l'architecture des messages Windows - principalement pour des raisons de simplicité. Nous avons besoin d'un système plus générique, offrant les fonctions suivantes&amp;nbsp;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;N'importe qui peut envoyer un message&lt;/strong&gt;&amp;nbsp;; le monde des &lt;em&gt;producteurs&lt;/em&gt; est ouvert.&lt;/li&gt;
&lt;/ul&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;N'importe quelle classe d'objet peut enregistrer une ou plusieurs fonctions de réception de message&lt;/strong&gt;&amp;nbsp;; je ne dois pas demander à une classe de dériver d'une classe spécifique dès lors que je souhaite déclarer une fonction de réception de message. Mon but est de présenter un système générique d'envoi/réception de messages. Idéalement, il devrait même m'être possible de créer une fonction libre (hors classe) et de l'enregistrer en tant que fonction de réception de message. Plus formellement, le monde des &lt;em&gt;consommateurs&lt;/em&gt; est ouvert.&lt;/li&gt;
&lt;/ul&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Plusieurs fonctions de réception de message peuvent réceptionner le même message&lt;/strong&gt;&amp;nbsp;; un message n'a pas nécessairement un seul destinataire, car j'ai une relation n/n entre les producteurs et les consommateurs ( ce qui signifie que Np producteurs peuvent envoyer un message particulier, et chaque message peut être traité par Nc consommateurs).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Parmi ces trois points, c'est bien évidemment le second qui est le plus important. En substance, il nous empêche de mettre en place une solution similaire à celle mise en place dans le cadre de la série &lt;em&gt;Du contrôle des fenêtres&lt;/em&gt; puisque cette dernière s'appuie principalement sur le fait que tous les objets réceptionnant des messages sont des fenêtres, qui dérivent d'une classe unique &lt;code&gt;window&lt;/code&gt;.&lt;/p&gt;


&lt;h3&gt;Formalisation&lt;/h3&gt;


&lt;p&gt;Qu'est-ce qu'une fonction de réception de message&amp;nbsp;? Au niveau formel, il s'agit d'une &lt;a href=&quot;http://fr.wikipedia.org/wiki/Fonction_de_rappel&quot; hreflang=&quot;fr&quot;&gt;fonction de rappel&lt;/a&gt; donc avant tout d'une entité qu'on peut exécuter.&lt;/p&gt;


&lt;blockquote&gt;&lt;p&gt;&lt;strong&gt;Définition&lt;/strong&gt;&amp;nbsp;: FRM, fonction de réception de message&lt;br /&gt;
&lt;em&gt;Une fonction de réception de message une fonction de rappel typée, aussi appelée &lt;strong&gt;fonction déléguée&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;&lt;/blockquote&gt;


&lt;p&gt;Selon les langages, plusieurs possibilités nous sont offertes&lt;sup&gt;[&lt;a href=&quot;http://blog.emmanueldeloget.com/index.php?post/2009/12/06/145-implementation-d-un-systeme-de-regle-pour-un-jeu-de-role-retour-a-nos-problemes#pnote-132-1&quot; id=&quot;rev-pnote-132-1&quot;&gt;1&lt;/a&gt;]&lt;/sup&gt;&amp;nbsp;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;une méthode de classe&lt;/li&gt;
&lt;li&gt;une fonction libre (uniquement dans les langages permettant l'utilisation du paradigme procédural; par exemple, C++)&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://en.wikipedia.org/wiki/Function_object&quot; hreflang=&quot;en&quot;&gt;un objet fonction&lt;/a&gt; (certains langages orientés objet ne supporte pas la création de foncteurs)&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://fr.wikipedia.org/wiki/Fonction_anonyme&quot; hreflang=&quot;fr&quot;&gt;une fonction anonyme&lt;/a&gt; (uniquement dans les langages permettant l'utilisation du paradigme fonctionnel&amp;nbsp;; par exemple, C#, Java).&lt;sup&gt;[&lt;a href=&quot;http://blog.emmanueldeloget.com/index.php?post/2009/12/06/145-implementation-d-un-systeme-de-regle-pour-un-jeu-de-role-retour-a-nos-problemes#pnote-132-2&quot; id=&quot;rev-pnote-132-2&quot;&gt;2&lt;/a&gt;]&lt;/sup&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://fr.wikipedia.org/wiki/Fermeture_(informatique)&quot; hreflang=&quot;fr&quot;&gt;une fermeture&lt;/a&gt; (uniquement dans les langages supportant cette fonctionnalité&amp;nbsp;; par exemple C#, Java, JavaScript)&lt;sup&gt;[&lt;a href=&quot;http://blog.emmanueldeloget.com/index.php?post/2009/12/06/145-implementation-d-un-systeme-de-regle-pour-un-jeu-de-role-retour-a-nos-problemes#pnote-132-3&quot; id=&quot;rev-pnote-132-3&quot;&gt;3&lt;/a&gt;]&lt;/sup&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Les FRM traitent des messages.&lt;/p&gt;


&lt;blockquote&gt;&lt;p&gt;&lt;strong&gt;Définition&lt;/strong&gt;: fonction &lt;code&gt;reduction&lt;/code&gt; et messages&lt;br /&gt;
&lt;em&gt;Soit T l'ensemble des types de donnée qu'il est possible de décrire avec un langage L, et K un sous-ensemble de T sur lesquelles l'opérateur == est défini. On définit la fonction &lt;code&gt;reduction&lt;/code&gt; de T vers K telle que quelque soit t1, t2 de T, &lt;code&gt;reduction&lt;/code&gt;(t1) == &lt;code&gt;reduction&lt;/code&gt;(t2) si et seulement si t1 et t2 sont identiques.&lt;/em&gt;&lt;br /&gt;
&lt;em&gt;Un message est une instance d'un type M de T.&lt;/em&gt;&lt;/p&gt;&lt;/blockquote&gt;


&lt;p&gt;Vous devez vous demander pourquoi est-ce que je parle de fonction &lt;code&gt;reduction&lt;/code&gt; - quelle espèce de lien peut-elle avoir avec notre problème&amp;nbsp;? Si vous vous rappelez de &lt;a href=&quot;http://blog.emmanueldeloget.com/index.php/2009/11/23/143-implementation-d-un-systeme-de-regle-pour-un-jeu-de-role-cassons-la-circularite&quot; hreflang=&quot;fr&quot;&gt;cette histoire de bouteille de lait et d'étiquettes&lt;/a&gt;, alors vous ferez sans doute le rapprochement&amp;nbsp;: la fonction &lt;code&gt;reduction&lt;/code&gt; n'est rien d'autre que le système d'étiquetage des messages, qui transforme les informations fournies par le producteur (le message lui même) en un code compréhensible par l'entreprise de livraison de lait.&lt;/p&gt;


&lt;p&gt;Histoire d'être complet, on termine notre formalisation du problème avec quelques définitions supplémentaires.&lt;/p&gt;


&lt;blockquote&gt;&lt;p&gt;&lt;strong&gt;Définition&lt;/strong&gt;&amp;nbsp;: fonction &lt;code&gt;traduction&lt;/code&gt;&lt;br /&gt;
&lt;em&gt;Soit T l'ensemble des types de données qu'il est possible de décrire avec un langage L. Soit A, M des sous-ensembles de T. On définit une fonction &lt;code&gt;traduction&lt;/code&gt; de M vers A, ou M est un type de message et A est le type d'argument d'une FRM.&lt;/em&gt;&lt;/p&gt;&lt;/blockquote&gt;


&lt;p&gt;Pourquoi a-t-on besoin d'une fonction &lt;code&gt;traduction&lt;/code&gt;&amp;nbsp;? Celle-ci n'entre pas vraiment dans le schéma décrit dans la métaphore du livreur de lait. L'utilité de cette fonction est plus avancée, et peut se comprendre en augmentant légèrement la métaphore sus-dite.&lt;/p&gt;


&lt;p&gt;Supposons que notre livreur de lait soit non pas une entreprise locale mais une entreprise mondiale. Elle reçoit des bouteilles de lait en provenance de producteurs du monde entier, et les distribue à ces clients qui peuvent être située à des milliers de kilomètres de l'usine du producteur. Chaque bouteille de lait présente des informations utiles au livreur (qui les exploite après passage dans la fonction &lt;code&gt;reduction&lt;/code&gt;) et des informations qui sont utiles au consommateur. Le consommateur est (comme tout consommateur qui se respecte) un peu tatillon, et il s'attend à récupérer ces informations sous une certaine forme. Pour notre producteur, c'est un problème, car ne sachant pas quel client va recevoir la bouteille, il ne peut pas anticiper la façon dont les informations doivent être arrangée. Le livreur passe donc par des petites entreprises locales, sises près des consommateurs, et dont le but et de transformer les informations figurant sur les bouteilles de lait dans le format attendu par les consommateurs. Ainsi, ces derniers ont accès aux informations dont ils ont besoin, sans pour autant que ça n'ai d'impact sur le travail du producteur et du livreur. C'est le rôle de la fonction &lt;code&gt;traduction&lt;/code&gt;.&lt;/p&gt;


&lt;h3&gt;C'est bien beau tout ça, mais concrètement...&lt;/h3&gt;


&lt;p&gt;La section précédente nous a donné des informations sur les opérations que nous devons supporté, mais ne nous a pas vraiment aidé à concevoir notre système de gestion de messages.&lt;/p&gt;


&lt;p&gt;Quels sont les collaborations que nous allons devoir prendre en compte&amp;nbsp;? Les extrémités du processus sont évidentes&amp;nbsp;: nous allons avoir une entité qui va envoyer le message (le producteur) sous une forme connue F1, une entité qui va réceptionner le message (le consommateur) sous une forme F2. Entre temps, le message au format F1 aura été traité par le livreur grâce à la fonction &lt;code&gt;reduction&lt;/code&gt;, et un prestataire l'aura transformé grâce à la fonction &lt;code&gt;traduction&lt;/code&gt;. Le producteur n'est pas vraiment partie prenante du système - il en est l'utilisateur. Nous le laissons donc de coté. De même, le consommateur est lui aussi un utilisateur.&lt;/p&gt;


&lt;p&gt;Dans notre architecture, nous allons donc déclarer les classes suivantes&amp;nbsp;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;message&lt;/code&gt;, notre type M.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;key&lt;/code&gt;, le type K de retour de la fonction &lt;code&gt;reduction&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;message_dispatcher&lt;/code&gt;, l'équivalent de notre livreur de lait (connait les types M, K et R, type de retour des FRM)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;marshaller&lt;/code&gt;, l'équivalent de notre prestataire local (connait les types M, A - type de retour de la fonction &lt;code&gt;traduction&lt;/code&gt; - et R)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;delegate&lt;/code&gt;, qui encapsule une FRM (connait A et R)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;En temps normal, les opérations suivantes prennent place&amp;nbsp;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Les consommateurs enregistrent les FRM (sous la forme d'un &lt;code&gt;delegate&lt;/code&gt; associée à une valeur de type &lt;code&gt;key&lt;/code&gt; et à un &lt;code&gt;marshaller&lt;/code&gt;) auprès de l'instance de &lt;code&gt;message_dispatcher&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Lorsqu'un producteur envoie un &lt;code&gt;message&lt;/code&gt; au &lt;code&gt;message_dispatcher&lt;/code&gt;, ce dernier le transforme en instance de &lt;code&gt;key&lt;/code&gt; de manière à récupérer la liste des FRM destinataires du &lt;code&gt;message&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Le &lt;code&gt;message&lt;/code&gt; est transformé par le &lt;code&gt;marshaller&lt;/code&gt; associé au &lt;code&gt;delegate&lt;/code&gt; en un argument d'un type connu par ce dernier.&lt;/li&gt;
&lt;li&gt;Le &lt;code&gt;delegate&lt;/code&gt; est alors exécuté et appelle le FRM.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Selon le langage de programmation utilisé, quelques complications peuvent arriver lorsqu'on souhaite effectuer des opérations qui paraissent triviales mais ne le sont pas (notamment, en C++, le fait de désinscrire un FRM - il nous faut alors trouver le moyen de retrouver ce FRM particulier dans la liste des FRM enregistrés. Je vous laisse gérer ce point particulier en forme d'exercice).&lt;/p&gt;


&lt;p&gt;Pour finir, je vous livre le diagramme de classe correspondant à cette architecture. Le code source C++ documenté lié à ce projet devrait faire l'objet d'une annonce d'ici le début de la semaine prochaine.&lt;/p&gt;


&lt;p&gt;&lt;img src=&quot;http://blog.emmanueldeloget.com/public/jeu-de-role/message_dispatcher.png&quot; alt=&quot;message_dispatcher.png&quot; style=&quot;display:block; margin:0 auto;&quot; title=&quot;diagramme des classes liées à message_dispatcher&quot; /&gt;&lt;/p&gt;


&lt;p&gt;A bientôt&amp;nbsp;!&lt;/p&gt;
&lt;div class=&quot;footnotes&quot;&gt;&lt;h4&gt;Notes&lt;/h4&gt;
&lt;p&gt;[&lt;a href=&quot;http://blog.emmanueldeloget.com/index.php?post/2009/12/06/145-implementation-d-un-systeme-de-regle-pour-un-jeu-de-role-retour-a-nos-problemes#rev-pnote-132-1&quot; id=&quot;pnote-132-1&quot;&gt;1&lt;/a&gt;] Je ne vous cache pas que malgré cette envie dévorante de vous présenter un code source adaptés à vos besoins, je ne vais pas (dans cet article et dans les suivants) vous livrer de fichier écrits dans un autre langage que le C++ - par goût pour ce langage imperméable, et parce que je dois bien faire un choix. Je proposerai toutefois de temps en temps des exemple de code dans d'autres langages.&lt;/p&gt;
&lt;p&gt;[&lt;a href=&quot;http://blog.emmanueldeloget.com/index.php?post/2009/12/06/145-implementation-d-un-systeme-de-regle-pour-un-jeu-de-role-retour-a-nos-problemes#rev-pnote-132-2&quot; id=&quot;pnote-132-2&quot;&gt;2&lt;/a&gt;] La prochaine version de C++ supporte les fonctions anonymes.&lt;/p&gt;
&lt;p&gt;[&lt;a href=&quot;http://blog.emmanueldeloget.com/index.php?post/2009/12/06/145-implementation-d-un-systeme-de-regle-pour-un-jeu-de-role-retour-a-nos-problemes#rev-pnote-132-3&quot; id=&quot;pnote-132-3&quot;&gt;3&lt;/a&gt;] La prochaine version de C++ supporte les fermetures.&lt;/p&gt;&lt;/div&gt;
</description>
    
    
    
          <comments>http://blog.emmanueldeloget.com/index.php?post/2009/12/06/145-implementation-d-un-systeme-de-regle-pour-un-jeu-de-role-retour-a-nos-problemes#comment-form</comments>
      <wfw:comment>http://blog.emmanueldeloget.com/index.php?post/2009/12/06/145-implementation-d-un-systeme-de-regle-pour-un-jeu-de-role-retour-a-nos-problemes#comment-form</wfw:comment>
      <wfw:commentRss>http://blog.emmanueldeloget.com/index.php?feed/atom/comments/132</wfw:commentRss>
      </item>
    
  <item>
    <title>Anniversaire III (et demi)</title>
    <link>http://blog.emmanueldeloget.com/index.php?post/2009/12/01/144-anniversaire-iii-et-demi</link>
    <guid isPermaLink="false">urn:md5:50a0a61e1dbffe2fe8ae2066ec69d2d0</guid>
    <pubDate>Tue, 01 Dec 2009 19:00:00 +0000</pubDate>
    <dc:creator>Emmanuel Deloget</dc:creator>
        <category>General</category>
            
    <description>&lt;p&gt;Ce blog est né en 2006. En 2007, je fêtais son premier anniversaire, en 2008 le second. Et en 2009, et bien j'ai tout simplement oublié de le faire. Tâchons de réparer cette odieuse injustice, et de donner quelques chiffres...&lt;/p&gt;    &lt;h3&gt;Des tas de problèmes&lt;/h3&gt;


&lt;p&gt;Du quatrième trimestre 2008 à la fin du troisième trimestre 2009, j'ai du lutter contre moi-même pour dépasser plusieurs problèmes - et en particulier quelques problèmes de santé importants. Bien évidemment, le rythme des publications s'en est ressenti. Je commence à revenir à un rythme plus normal, même si on remarque que ce n'est toujours pas très reluisant. Quoi qu'il en soit, je récupère bien, donc vous pouvez vous attendre à avoir de plus en plus d'articles sur différents sujets.&lt;/p&gt;


&lt;p&gt;Ainsi, en plus d'un an (en fait, depuis le 21/07/2008), seul 9 articles ont été postés sur ce site. Pas grandiose... Dans l'ordre chronologique de parution, le nombre de visites (à ce jour) pour chacun de ces billets&amp;nbsp;:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Anniversaire II&amp;nbsp;: le retour de la mort se venge&amp;nbsp;: &lt;strong&gt;747 visites&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;Paris GDC'08 - Conference Coverage (Frank Hauselmann)&amp;nbsp;: &lt;strong&gt;786 visites&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;Le futur standard C++&amp;nbsp;: concepts: &lt;strong&gt;1206 visites&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;Le futur standard C++&amp;nbsp;: concepts, deuxième prise&amp;nbsp;: &lt;strong&gt;1086 visites&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;Etude du C++ Technical Report 1 - reference_wrapper&amp;nbsp;: je confirme, c'est tordu.&amp;nbsp;: &lt;strong&gt;1151 visites&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;Plugin pour DotClear 2.1.6&amp;nbsp;: &lt;strong&gt;212 visites&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;Implémentation d'un système de règle pour un jeu de rôle - Introduction&amp;nbsp;: &lt;strong&gt;268 visites&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;Implémentation d'un système de règle pour un jeu de rôle - Analyse des besoins&amp;nbsp;: &lt;strong&gt;248 visites&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;Une nouvelle console de jeu&amp;nbsp;: la Freebox HD (?!)&amp;nbsp;: &lt;strong&gt;40 visites&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;Implémentation d'un système de règle pour un jeu de rôle - Cassons la circularité&amp;nbsp;! : &lt;strong&gt;56 visites&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Soit un total de 5800 visites sur la période.&lt;/p&gt;


&lt;p&gt;On notera qu'entre le billet 5 et le billet 6 de cette liste, il y a un trou d'une année - ce qui explique les différences en terme de nombre de visites - et que les deux derniers articles datent de la fin du mois de novembre, ce qui explique le nombre de visite encore plus bas - ils viennent de paraître.&lt;/p&gt;


&lt;h3&gt;La fréquentation du site&lt;/h3&gt;


&lt;p&gt;Les chiffres sont donnés par Google Adsense. Bien entendu, les visiteurs ayant activés AdBlock ou un programme similaire ne sont pas comptés dans ces chiffres, mais ce n'est pas grâve pour moi, puisqu'ils ne participent pas vraiment à l'effort de guerre autrement qu'en en faisant la publicité (ce qui est déjà pas mal, je vous le concède).&lt;/p&gt;


&lt;pre&gt;aou-08       2 386
sep-08       2 572
oct-08       3 100
nov-08       2 591
dec-08       2 748
jan-09       2 392
fev-09       2 980
mar-09       2 714
avr-09       2 464
mai-09       2 454
juin-09      2 083
juil-09      1 664 	
aou_09       1 367
sep-09       1 661
oct-09       3 422
nov-09       2 879
&lt;strong&gt;total       39 477&lt;/strong&gt;&lt;/pre&gt;


&lt;p&gt;On voit un trou évident qui arrive dès Juin 2009 - après déjà plusieurs mois sans nouvelles de ma part. J'en conclus que vous êtes globalement fidèles, et c'est plutôt une bonne chose pour moi.&lt;/p&gt;


&lt;p&gt;Ces près de 40,000 visites se sont transformées en 104 clics sur les annonces Google - pas de quoi faire vivre ce site (loin de là&amp;nbsp;; il en faudrait 3 fois plus !) avec un record de fréquentation (et de nombre de clics) le 27 octobre 2009 (341 visites, 6 clics).&lt;/p&gt;


&lt;h3&gt;Source des visites&lt;/h3&gt;


&lt;p&gt;Chose importante&amp;nbsp;: la part des visites en provenance d'un autre site a plus que doublé (en pourcentage), passant de moins de 10% pour [juillet 2007 - juillet 2008] à près de 23% pour les 15 mois écoulés. Sans surprise, on retrouve les classiques&amp;nbsp;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;developpez.com, avec plus de 1700 visites&lt;/li&gt;
&lt;li&gt;siteduzero.com avec près de 1200 visites&lt;/li&gt;
&lt;li&gt;gamedev.net avec 230 visites environ&lt;/li&gt;
&lt;li&gt;netvibes.com avec un peu plus de 100 visites&lt;/li&gt;
&lt;li&gt;geekzone.fr, source d'une quarantaine de visites.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Au niveau des moteurs de recherche (63.74% des visites), on compte bien évidemment google (98% des recherches proviennent de google) suivi par yahoo (0.82%) puis live/bing (0.48%). Les mots-clef les plus cherchés sont&amp;nbsp;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;architecture logicielle (3,6% des recherches)&amp;nbsp;; (remarque&amp;nbsp;: pour cette recherche, j'apparais très haut sur la première page de résultats sur google).&lt;/li&gt;
&lt;li&gt;std::auto_ptr (même remarque)&lt;/li&gt;
&lt;li&gt;raii&lt;/li&gt;
&lt;li&gt;emmanuel deloget&lt;/li&gt;
&lt;li&gt;xna isfixedtimestep&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Au niveau des browsers, on ne sera pas surpris de voir que FF est le browser le plus représenté - 68% des visiteurs. C'est principalement du au fait que les visiteurs sont très souvent des personnes ayant des connaissances informatiques poussées, et qu'ils ont fait le choix d'un navigateur qui correspond à leurs attentes. Enfin je crois... :)&lt;/p&gt;


&lt;h3&gt;Commentaires et notes&lt;/h3&gt;

&lt;p&gt;Durant cette année et demi, 33 commentaires ont été postés. Ce nombre n'est pas particulièrement élevé, mais il reste correcte (environ 2 commentaires par mois, sachant que je n'ai pas été présent pendant plus d'un an, c'est déjà pas mal). Plus intéressants, vous vous êtes un peu plus lâchés sur les notes&amp;nbsp;: aujourd'hui, vous avez posés 153 notes aux différents articles de ce blog, pour une moyenne très honorable de 3.87 / 5 (la moyenne étant à 3, puisque la note de 0 est impossible). Les billets les mieux notés&amp;nbsp;:&lt;/p&gt;


&lt;pre&gt;&lt;strong&gt;Titre du billet&lt;/strong&gt;										&lt;strong&gt;note	nb&lt;/strong&gt;
Exploration de XNA : les sprites animés							5.00	2
Exploration de XNA : la gestion du clavier						5.00	2
Du contrôle des fenêtres, seconde partie						5.00	2
Implémentation d'un système de règle pour un jeu de rôle - Cassons la circularité !	5.00	3
Exploration de XNA : Anatomie d'un projet XNA						5.00	5
Exploration de XNA : Introduction							4.86	7
Implémentation d'un système de règle pour un jeu de rôle - Introduction			4.75	4
Exploration de XNA : affichage de sprites						4.75	4
std::auto_ptr&amp;lt;&amp;gt; et fuite de mémoire							4.67	3
Exploration de XNA : les planches de sprites						4.50	2
L'hérésie des variables globales							4.50	2
Du contrôle des fenêtres, première partie						4.33	3
Le futur standard C++ : les classes d'énumérations					4.33	3
Implémentation d'un système de règle pour un jeu de rôle - Analyse des besoins		4.20	5
Exploration de XNA : Les machines à états						4.00	4&lt;/pre&gt;


&lt;p&gt;Seuls les articles ayant reçu plus de 1 vote (nb &amp;gt; 1) et ayant une note &amp;gt;= 4 sont présents dans cette liste. On remarque toujours que la série XNA continue d'avoir un certain succès, mais que les nouveaux venus (notamment la série &lt;em&gt;Implémentation d'un système de règle pour un jeu de rôle&lt;/em&gt;) sont relativement bien perçus. C'est gentil de votre part - je vais continuer dans cette direction.&lt;/p&gt;


&lt;p&gt;A l'année prochaine pour une autre étude des résultats de ce site web&amp;nbsp;!&lt;/p&gt;</description>
    
    
    
          <comments>http://blog.emmanueldeloget.com/index.php?post/2009/12/01/144-anniversaire-iii-et-demi#comment-form</comments>
      <wfw:comment>http://blog.emmanueldeloget.com/index.php?post/2009/12/01/144-anniversaire-iii-et-demi#comment-form</wfw:comment>
      <wfw:commentRss>http://blog.emmanueldeloget.com/index.php?feed/atom/comments/131</wfw:commentRss>
      </item>
    
  <item>
    <title>Implémentation d'un système de règle pour un jeu de rôle - Cassons la circularité !</title>
    <link>http://blog.emmanueldeloget.com/index.php?post/2009/11/23/143-implementation-d-un-systeme-de-regle-pour-un-jeu-de-role-cassons-la-circularite</link>
    <guid isPermaLink="false">urn:md5:ff6361acbc11d9e4577a44e74c0b26a1</guid>
    <pubDate>Mon, 23 Nov 2009 18:00:00 +0000</pubDate>
    <dc:creator>Emmanuel Deloget</dc:creator>
        <category>Architecture Orientée Objet</category>
            
    <description>&lt;p&gt;Dans l'article précédent, on a vu que l'implémentation d'un système fermé ayant pour put la gestion d'un personnage dans un jeu de rôle modérément complexe avant des conséquences pour le moins inattendues, et notamment le fait que de nombreuses entités se retrouvait dans un état d'interdépendance complexe. Cet article, plus général que le titre ne le montre, essaie de donner quelques pistes pour casser ces dépendances circulaire dans le but de nous permettre la création d'une architecture simple, ouverte et efficace.&lt;/p&gt;    &lt;h3&gt;Qu'est-ce qu'une dépendance circulaire&amp;nbsp;?&lt;/h3&gt;


&lt;p&gt;Bien évidemment, je pose la question alors que je sais que vous connaissez la réponse. Une dépendance circulaire existe à partir du moment ou une classe A dépends d'elle même de manière indirecte, par opposition à une dépendance directe qui (en termes de design) n'est pas dommageable. Cela signifie que A dépends d'une classe B qui elle même dépends de A.&lt;/p&gt;


&lt;p&gt;La conséquence logique est que A et B sont &lt;a href=&quot;http://en.wikipedia.org/wiki/Coupling_(computer_science)&quot; hreflang=&quot;en&quot;&gt;fortement couplées&lt;/a&gt;. Ce couplage a un impact non désirable sur à la fois le code et l'architecture.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Sur l'architecture, ce fort couplage implique que A et B sont nécessairement utilisées ensemble&amp;nbsp;; ni l'une ni l'autre n'est réutilisable sans l'autre. Si A dépends aussi de plusieurs classes A1, ..., An, alors l'utilisation de B dans un projet nécessite la connaissance de A, A1, ..., An - ce qui n'a pas vraiment de sens. L'architecture est fortement complexifiée du fait même de ce couplage fort.&lt;/li&gt;
&lt;/ul&gt;
&lt;ul&gt;
&lt;li&gt;Sur le code, une modification dans l'un des deux classes a de grandes chances d'impliquer une modification dans l'autre classe - de manière plus formelle, A est une responsabilité de B qui est une responsabilité de A. En vertu du &lt;a href=&quot;http://blog.emmanueldeloget.com/index.php/2006/09/07/16-le-principe-de-responsabilite-unique&quot; hreflang=&quot;fr&quot;&gt;principe de responsabilité unique&lt;/a&gt;, cela signifie que ni A ni B ne peuvent avoir d'autre responsabilité&amp;nbsp;; conceptuellement, on voit bien qu'il y a un problème, parce que ça voudrait dire que ni A ni B ne font quoi que ce soit.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Certaines personnes semblent penser que dès lors que deux classes présentent une forte &lt;a href=&quot;http://en.wikipedia.org/wiki/Cohesion_(computer_science)&quot; hreflang=&quot;en&quot;&gt;cohésion&lt;/a&gt; (c'est à dire qu'elles traitent de sujets très similaires et qu'il y a de fortes chances qu'elles soient utilisées dans le même cadre applicatif) alors le fait qu'elles soient en plus fortement couplées n'a pas véritablement d'incidence sur la qualité du design ou sur le code. Ce n'est pas vrai, pour une simple et bonne raison&amp;nbsp;: tôt ou tard, un couplage fort entraine l'utilisation dans un module de dépendances qui n'ont pas de lien de cohésion avec les autres parties du module. La cohésion globale est donc réduite d'autant. A terme, plus le couplage est fort, plus la cohésion du module sera faible. Seul un couplage faible permet de s'assurer d'une forte cohésion entre les différentes classes d'un module.&lt;/p&gt;


&lt;h3&gt;Soit&amp;nbsp;; que faire alors&amp;nbsp;?&lt;/h3&gt;


&lt;p&gt;Nous ne connaissons hélas pas beaucoup de manières différentes pour casser ce type de relation malsaine, d'autant que dans notre cas cette relation n'est pas seulement une vue de l'esprit mais bel et bien une réalité liée à l'architecture des règles elle-même.&lt;/p&gt;


&lt;p&gt;La première technique est l'ajout de niveaux d'abstraction supplémentaires. Cette technique consiste à découpler deux classes A et B en rajoutant une classe intermédiaire C telle que (&quot;x -&amp;gt; y&quot; signifie &quot;x dépends de y&quot;)&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;avant la modification&amp;nbsp;: A1 -&amp;gt; B1 -&amp;gt; A1&lt;/li&gt;
&lt;li&gt;après la modification&amp;nbsp;: A2 -&amp;gt; B2, A2 -&amp;gt; C2 et B2 -&amp;gt; C2 (généralement, C2 est une super-classe de A2).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;img src=&quot;http://blog.emmanueldeloget.com/images/jeu-de-role/reference_circulaire.jpeg&quot; alt=&quot;&quot; /&gt;&lt;br /&gt;
&lt;em&gt;Dans la famille &quot;Avant - Après&quot;, je veux le diagramme de classe&lt;/em&gt;&lt;/p&gt;


&lt;p&gt;Cette technique est efficace dans de nombreux cas. Pour notre cas particulier, on s'aperçoit rapidement que cette solution n'est pas envisageable - compte tenu du nombre d'interactions entre les différentes classes. En effet, si il est aisé de casser une dépendance circulaire entre deux classes, il est beaucoup plus complexe avec cette technique de casser la dépendance circulaire entre N classes fortement interdépendantes.&lt;/p&gt;


&lt;p&gt;L'autre solution est un peu plus complexe à visualiser dans sa version complète, mais elle convient parfaitement à notre cas&amp;nbsp;: c'est l'application de la métaphore livreur de lait&lt;sup&gt;[&lt;a href=&quot;http://blog.emmanueldeloget.com/index.php?post/2009/11/23/143-implementation-d-un-systeme-de-regle-pour-un-jeu-de-role-cassons-la-circularite#pnote-143-1&quot; id=&quot;rev-pnote-143-1&quot;&gt;1&lt;/a&gt;]&lt;/sup&gt;. Le livreur de lait travaille pour le distributeur &lt;code&gt;lactus&lt;/code&gt;, connue par tout les producteurs et consommateurs de lait du monde entier ou presque. Lactus prends à sa charge les livraisons de lait partout&amp;nbsp;: un producteur envoie son lait à Lactus, qui l'envoie aux clients qui souhaite boire ce lait spécifique.&lt;/p&gt;


&lt;p&gt;Dans ce monde parfait, Lactus n'a pas besoin de connaître la composition exacte de chaque bouteille de lait qui transite par ses locaux. Elle pourrait ne rien connaître du tout, mais ça la forcerait à envoyer le lait à tout le monde si elle souhaite être sûre de n'oublier personne. Afin d'optimiser ses ressources humaines, elle a donc imposé un système simple&amp;nbsp;: chaque bouteille possède une étiquette particulière avec la marque du fabricant. Les consommateurs demandent alors les bouteilles de lait de tel ou tel fabricant.&lt;/p&gt;


&lt;p&gt;Les avantages de ce système sont certains&amp;nbsp;: celui qui envoie le lait n'a pas à savoir qui va le recevoir&amp;nbsp;; celui qui reçoit le lait se moque de qui est vraiment le producteur&amp;nbsp;; et enfin, Lactus n'a pas besoin de connaître quoi que ce soit à propos du lait échangées ou à propos de ses clients, si ce n'est le strict minimum - la marque du lait et l'adresse du client.&lt;/p&gt;


&lt;p&gt;On voit clairement que ce système est fort bien adapté à notre problème&amp;nbsp;: avec une telle vision, il devient possible de regrouper beaucoup d'entités qui autrement serait interdépendantes pour en faire des entités qui sont complètement indépendantes. A noter que vous pourriez croire que si cette technique marche bien dans ce cas, il n'y a pas de raison qu'elle ne marche pas dans le cas simple (A -&amp;gt; B -&amp;gt; A). Il est évident qu'elle fonctionnera - mais à quel prix&amp;nbsp;? Alors que l'ajout d'une abstraction supplémentaire ne coute quasiment rien, un système de message tel que celui décrit ici nécessite une boite à lettre, des objets messages et tout une ribambelle de petites considérations qui rendent le design non trivial. De fait, il convient de réserver cette solution aux cas ou elle correspond vraiment bien - d'autant que dans la grande majorité des cas, c'est le problème simple qui se pose, et ce problème simple bénéficie grandement de l'ajout d'une abstraction.&lt;/p&gt;


&lt;p&gt;A bientôt pour de nouvelles aventures...&lt;/p&gt;
&lt;div class=&quot;footnotes&quot;&gt;&lt;h4&gt;Notes&lt;/h4&gt;
&lt;p&gt;[&lt;a href=&quot;http://blog.emmanueldeloget.com/index.php?post/2009/11/23/143-implementation-d-un-systeme-de-regle-pour-un-jeu-de-role-cassons-la-circularite#rev-pnote-143-1&quot; id=&quot;pnote-143-1&quot;&gt;1&lt;/a&gt;] en fait, je l'appelle comme ça, mais elle n'a probablement aucun nom...&lt;/p&gt;&lt;/div&gt;
</description>
    
    
    
          <comments>http://blog.emmanueldeloget.com/index.php?post/2009/11/23/143-implementation-d-un-systeme-de-regle-pour-un-jeu-de-role-cassons-la-circularite#comment-form</comments>
      <wfw:comment>http://blog.emmanueldeloget.com/index.php?post/2009/11/23/143-implementation-d-un-systeme-de-regle-pour-un-jeu-de-role-cassons-la-circularite#comment-form</wfw:comment>
      <wfw:commentRss>http://blog.emmanueldeloget.com/index.php?feed/atom/comments/130</wfw:commentRss>
      </item>
    
  <item>
    <title>Une nouvelle console de jeu : la Freebox HD (?!)</title>
    <link>http://blog.emmanueldeloget.com/index.php?post/2009/11/23/142-une-nouvelle-console-de-jeu-la-freebox-hd</link>
    <guid isPermaLink="false">urn:md5:ee2fa06018e221caa2edae823d7aa748</guid>
    <pubDate>Mon, 23 Nov 2009 14:00:00 +0000</pubDate>
    <dc:creator>Emmanuel Deloget</dc:creator>
        <category>News</category>
            
    <description>&lt;p&gt;Pour les propriétaires de cet objet, c'était évident&amp;nbsp;: vu la forme de la télécommande, il était prévu depuis longtemps que la Freebox HD puisse être utilisée comme console de jeu. Bien sûr, on ne parle pas ici de jeux de dernière génération - point de Modern Warfare 2 ou de Batman - Arkham Asylum. Non, juste des petits jeux amusants et plein de fun, qui passent le temps. Quoi que... C'est maintenant le cas&amp;nbsp;: depuis le 19 novembre, la Freebox HD accueille un nouveau menu (Jeux) et de nouvelles possibilités. Encore mieux, camarades programmeurs&amp;nbsp;: vous pouvez vous même proposer vos créations à Free...&lt;/p&gt;    &lt;p&gt;Tout est basé (encore une fois, c'est une habitude chez Free) sur un framework libre - &lt;a href=&quot;http://elixir.freebox.fr/?section=accueil&quot; hreflang=&quot;fr&quot;&gt;Elixir&lt;/a&gt;, un binding Javascript à l'ensemble de librairies Enlightenment Foundation Library (EFL). EFL a été développé pour &lt;a href=&quot;http://www.enlightenment.org/&quot; hreflang=&quot;en&quot;&gt;Enlightenment DR17&lt;/a&gt;, afin de le rendre encore plus personnalisable tout en gardant des performances haut de gamme, même sur des machines relativement anciennes.&lt;/p&gt;


&lt;p&gt;C'est quoi, EFL&amp;nbsp;? Pour reprendre le texte officiel&amp;nbsp;:&lt;/p&gt;


&lt;blockquote&gt;&lt;p&gt;&lt;em&gt;The EFL contains solutions for almost any graphical interface task, far beyond just rendering images. EVAS provides a highly optimized canvas library. Ecore provides a simple and modular abstraction interface and advanced event management including timers. EDB provides a compact database format for intuitive and easy configuration management, including the storing of binaries. EET provides an integrated and flexible container that ends the traditions of providing themes in tarballs. Edje provides a revolutionary library and tool set for completely abstracting application interfaces from their code, including a complex and flexible method of designing interfaces. EWL provides a complete widget library built on all the other components of the EFL.&lt;/em&gt;&lt;/p&gt;&lt;/blockquote&gt;


&lt;p&gt;Ou, en version française&amp;nbsp;:&lt;/p&gt;


&lt;blockquote&gt;&lt;p&gt;&lt;em&gt;EFL contient des solutions pour presque toute les tâches graphiques, bien au delà du rendu d'images. EVAS offre un &lt;/em&gt;canvas&lt;em&gt; hautement optimisée. Ecore propose une interface d'abstraction simple et modulaire et un gestionnaire d'évennement avancé incluant les timers. EDB est un format de base de données compact incluant le stockage de binaires  pour une configuration simple et intuitive. EET offre un conteneur intégré et flexible qui en termine avec la tradition des thèmes stockés en archives TAR. Edje est une librairie et un ensemble d'outil révolutionnaires pour abstraire complètement l'interface du code, comprennant entre autre une méthode complexe et flexible de définition d'interfaces. EWL est une librairie de widget complète bâtie sur les autres composants de EFL.&lt;/em&gt;&lt;/p&gt;&lt;/blockquote&gt;


&lt;p&gt;Cette architecture EFL + Javascript a de nombreux avantages. Le premier est que vous êtes globalement indépendant de l'architecture système - vous programmez en Javascript. Le second est que l'ensemble est relativement rapide - assez à mon avis pour faire des petits jeux type cartes, shooter ou plateforme (je pense même qu'un jeu comme World of Goo aux fonctionnalités un peu réduite est réalisable sur la Freebox HD). Et c'est tant mieux parce que c'est globalement ce qu'on lui demande à cette &quot;console&quot;.&lt;/p&gt;


&lt;p&gt;En tout cas, voilà une nouvelle plateforme intéressante, notamment pour les développeurs d'applications mobiles qui devraient y trouver un intérêt certain (et quelques millions de consommateurs potentiels). A noter que free mettra en place courant 2010 un système type App Store pour acheter et télécharger des applications fonctionnant sur la Freebox HD.&lt;/p&gt;


&lt;p&gt;Pour plus d'information, c'est &lt;a href=&quot;http://elixir.freebox.fr&quot; hreflang=&quot;fr&quot;&gt;ici&lt;/a&gt;. Amusez vous bien&amp;nbsp;!&lt;/p&gt;</description>
    
    
    
          <comments>http://blog.emmanueldeloget.com/index.php?post/2009/11/23/142-une-nouvelle-console-de-jeu-la-freebox-hd#comment-form</comments>
      <wfw:comment>http://blog.emmanueldeloget.com/index.php?post/2009/11/23/142-une-nouvelle-console-de-jeu-la-freebox-hd#comment-form</wfw:comment>
      <wfw:commentRss>http://blog.emmanueldeloget.com/index.php?feed/atom/comments/129</wfw:commentRss>
      </item>
    
  <item>
    <title>Implémentation d'un système de règle pour un jeu de rôle - Analyse des besoins</title>
    <link>http://blog.emmanueldeloget.com/index.php?post/2009/10/26/141-implementation-d-un-systeme-de-regle-pour-un-jeu-de-role-analyse-des-besoins</link>
    <guid isPermaLink="false">urn:md5:9c8321462f69d4a1ec9eb42415d7e930</guid>
    <pubDate>Mon, 26 Oct 2009 16:00:00 +0000</pubDate>
    <dc:creator>Emmanuel Deloget</dc:creator>
        <category>Architecture Orientée Objet</category>
            
    <description>&lt;p&gt;L'article précédent ne donne guère de solution - il se contente de présenter une problématique qui se résume à&amp;nbsp;: pour transformer un système de règle complexe en code, de nombreux problèmes liés à l'architecture logicielle doivent être résolus. Si j'ai pris l'exemple de Dungeons &amp;amp; Dragons (4ème édition), c'est que ce système est un exemple typique représentatif d'un système de règle complexe. Et nous allons voir dans ce billet dans quelle mesure il peut être complexe.&lt;/p&gt;    &lt;h3&gt;Les besoins&lt;/h3&gt;

&lt;p&gt;Il est impossible de prévoir une architecture logicielle si on ne fixe pas auparavant les besoins à laquelle cette architecture doit répondre. Si ce point peut paraître évident à certain, de nombreuses entreprises ne l'ont semble-t-il pas encore intégré. Je le répète donc&amp;nbsp;: la connaissance des besoin est impérative à l'élaboration d'une architecture logicielle.&lt;/p&gt;


&lt;p&gt;Supposons que nous souhaitons adapter les règles de Dungeons &amp;amp; Dragons 4ème édition pour les intégrer dans un programme&lt;sup&gt;[&lt;a href=&quot;http://blog.emmanueldeloget.com/index.php?post/2009/10/26/141-implementation-d-un-systeme-de-regle-pour-un-jeu-de-role-analyse-des-besoins#pnote-141-1&quot; id=&quot;rev-pnote-141-1&quot;&gt;1&lt;/a&gt;]&lt;/sup&gt;. Le besoin principal est d'implémenter les règles générales de base&amp;nbsp;; le second besoin est de permettre l'implémentation de règles particulière arbitraires.&lt;/p&gt;


&lt;p&gt;Dans l'ordre&amp;nbsp;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;le joueur doit pouvoir sélectionner une race et une classe&amp;nbsp;; les races ont un effet sur les caractéristiques, les compétences, les talents, les pouvoirs et l'équipement accessible au joueur.&lt;/li&gt;
&lt;li&gt;le joueur doit pouvoir sélectionner une classe&amp;nbsp;; les classes ont un effet sur les caractéristiques, les compétences, les talents, les pouvoirs et l'équipement accessible au joueur.&lt;/li&gt;
&lt;li&gt;le joueur doit avoir accès à plusieurs méthodes pour déterminer ses caractéristiques&amp;nbsp;; les score des caractéristiques ont un effet sur les compétences, les talents, les pouvoirs et l'équipement accessible au joueur.&lt;/li&gt;
&lt;li&gt;le joueur doit pouvoir choisir ses compétences.&lt;/li&gt;
&lt;li&gt;le joueur doit pouvoir sélectionner ses pouvoirs.&lt;/li&gt;
&lt;li&gt;le joueur doit pouvoir acheter son équipement&amp;nbsp;; l'équipement a un effet sur les caractéristiques, les compétences, les talents et les pouvoirs du joueur.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Je n'ai pas détaillé l'effet que les pouvoirs peuvent avoir sur le jeu - et pour cause&amp;nbsp;: le pouvoir est activé lorsque le personnage agit, et peut avoir un effet arbitraire sur son environnement. Il ne s'agit même plus d'effet sur le personnage lui-même, mais bien d'effet sur le jeu en cours. Ainsi, un pouvoir d'attaque peut avoir une influence sur les actions qui peuvent être entreprises par un autre personnage. Le problème des compétences est autre&amp;nbsp;: l'utilisation d'une compétence a aussi un effet sur l'environnement - un bluff réussi peut aider lors d'une négociation, ... De fait, l'environnement est aussi impacté par les compétences, mais dans une mesure moindre que par les pouvoirs.&lt;/p&gt;


&lt;p&gt;En fait, si on supprime cette possibilité d'agir sur l'extérieur en utilisant un pouvoir ou une compétence, il reste que le personnage peut être représenté par un système fermé que nous pouvons étudier aisément.&lt;/p&gt;


&lt;h3&gt;Le personnage en tant que système fermé&lt;/h3&gt;

&lt;p&gt;La liste ci-dessus peut être représentée par le diagramme ci-dessous.&lt;/p&gt;


&lt;p&gt;&lt;img src=&quot;http://blog.emmanueldeloget.com/images/jeu-de-role/rpg-character-closed-system.png&quot; alt=&quot;Personnage en tant que système fermé&quot; style=&quot;display:block; margin:0 auto;&quot; /&gt;&lt;/p&gt;


&lt;p&gt;Le diagramme montre clairement les éléments qui ont un impact sur les autres éléments du système&lt;sup&gt;[&lt;a href=&quot;http://blog.emmanueldeloget.com/index.php?post/2009/10/26/141-implementation-d-un-systeme-de-regle-pour-un-jeu-de-role-analyse-des-besoins#pnote-141-2&quot; id=&quot;rev-pnote-141-2&quot;&gt;2&lt;/a&gt;]&lt;/sup&gt;&amp;nbsp;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Race -&amp;gt; caractéristiques, compétences, pouvoirs &amp;amp; talents, équipement&lt;/li&gt;
&lt;li&gt;Classe -&amp;gt; caractéristiques, compétences, pouvoirs &amp;amp; talents, équipement&lt;/li&gt;
&lt;li&gt;Caractéristiques -&amp;gt; compétences, pouvoirs &amp;amp; talents, équipement&lt;/li&gt;
&lt;li&gt;Compétences -&amp;gt; pouvoirs, équipement&lt;/li&gt;
&lt;li&gt;Pouvoirs &amp;amp; talents -&amp;gt; caractéristiques, compétences, pouvoirs &amp;amp; talents, équipement&lt;/li&gt;
&lt;li&gt;Équipement -&amp;gt; caractéristiques, compétences, pouvoirs &amp;amp; talents, équipement&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;On peut déjà noter que deux informations (groupe 1) sont indépendantes des autres (la Race et la Classe). Deux autres informations sont des groupes (groupe 2) de grandeurs (les Caractéristiques et les Compétences). Suivent trois autres informations (pouvoirs, talents, équipement, formant le groupe 3) qui implémentent des règles particulières. Explorons ces groupes plus en profondeur.&lt;/p&gt;


&lt;p&gt;Le groupe 1 est utilisé pour l'initialisation d'un personnage. Il n'a d'autre fonction que de fournir un cadre de base - autoriser ou interdire un équipement particulier, fournir une liste de compétence, décrire une liste de pouvoirs disponibles, etc. De nouveaux manuels peuvent ajouter de nouvelles races et de nouvelles classes.&lt;/p&gt;


&lt;p&gt;Le groupe 2 contient des informations qui sont similaires, mais pas identiques. Caractéristiques et compétences sont est grandeurs chiffrées qui peuvent être affectées par des modificateurs et qui servent à générer d'autres modificateurs ayant un impact sur des jets de dés. Les différences majeures résident dans l'initialisation de ces grandeurs et la génération du modificateur associé, mais dans l'essence, ce sont des &lt;em&gt;scores&lt;/em&gt; auxquels sont associés des noms. La liste des compétences et des caractéristique est fixée, toutefois la liste de leurs utilisations est étendue régulièrement.&lt;/p&gt;


&lt;p&gt;Le groupe 3 défini une corpus de règles particulières qui ont un impact sur le personnage dans son ensemble. De nouveaux talents, pouvoirs et objets sont publiés régulièrement, rajoutant de nouvelles règles particulières à ce corpus déjà fournit.&lt;/p&gt;
&lt;div class=&quot;footnotes&quot;&gt;&lt;h4&gt;Notes&lt;/h4&gt;
&lt;p&gt;[&lt;a href=&quot;http://blog.emmanueldeloget.com/index.php?post/2009/10/26/141-implementation-d-un-systeme-de-regle-pour-un-jeu-de-role-analyse-des-besoins#rev-pnote-141-1&quot; id=&quot;pnote-141-1&quot;&gt;1&lt;/a&gt;] &lt;strong&gt;ATTENTION&lt;/strong&gt; : cet article utilise Dungeons &amp;amp; Dragons 4ème édition car ce système de règle présente des difficultés représentatives des systèmes de règle complexe des jeux de rôle modernes ; je rappelle que &lt;a href=&quot;http://www.wizards.com/d20/files/4E_GSL.pdf&quot; hreflang=&quot;en&quot;&gt;selon la GSL §3 et §5.5&lt;/a&gt;, il est interdit d'effectuer une telle adaptation.&lt;/p&gt;
&lt;p&gt;[&lt;a href=&quot;http://blog.emmanueldeloget.com/index.php?post/2009/10/26/141-implementation-d-un-systeme-de-regle-pour-un-jeu-de-role-analyse-des-besoins#rev-pnote-141-2&quot; id=&quot;pnote-141-2&quot;&gt;2&lt;/a&gt;] on a regroupé pouvoir et talents du fait de leurs similitudes&lt;/p&gt;&lt;/div&gt;
</description>
    
    
    
          <comments>http://blog.emmanueldeloget.com/index.php?post/2009/10/26/141-implementation-d-un-systeme-de-regle-pour-un-jeu-de-role-analyse-des-besoins#comment-form</comments>
      <wfw:comment>http://blog.emmanueldeloget.com/index.php?post/2009/10/26/141-implementation-d-un-systeme-de-regle-pour-un-jeu-de-role-analyse-des-besoins#comment-form</wfw:comment>
      <wfw:commentRss>http://blog.emmanueldeloget.com/index.php?feed/atom/comments/128</wfw:commentRss>
      </item>
    
  <item>
    <title>Implémentation d'un système de règle pour un jeu de rôle - Introduction</title>
    <link>http://blog.emmanueldeloget.com/index.php?post/2009/10/19/140-implementation-d-un-systeme-de-regle-pour-un-jeu-de-role-introduction</link>
    <guid isPermaLink="false">urn:md5:901aa4d9b623204d94e9e4e45c53f03b</guid>
    <pubDate>Mon, 19 Oct 2009 16:00:00 +0000</pubDate>
    <dc:creator>Emmanuel Deloget</dc:creator>
        <category>Architecture Orientée Objet</category>
            
    <description>&lt;p&gt;Même si ça peut paraître relativement simple, l'implémentation d'un système de règle pour un jeu de rôle est une tâche complexe. Il existe de nombreuses raisons à ça&amp;nbsp;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;les règles elles même ne sont pas hiérarchisées&amp;nbsp;: dans un système parfait, une règle particulière ne fait pas référence à une règle plus générale&amp;nbsp;; au mieux, elle se substitue à la règle générale. Dans le cas des jeux de rôle, ça n'est pas le cas. Les règles particulières peuvent non seulement se substituer aux règles générales, mais elle peuvent aussi les étendre ou les modifier de manière plus fine.&lt;/li&gt;
&lt;li&gt;le nombre de cas à gérer n'est pa connu par avance&amp;nbsp;: un jeu de rôle est un produit vivant. Un supplément va nécessairement étendre le système de jeu pour ajouter de nouvelles options. Avant sa parution, il est impossible de savoir quelle modification va avoir un impact sur l'architecture du code. Il convient donc d'ouvrir l'architecture au maximum, sans pourtant tomber dans le travers de la sur-ingénierie qui serait contre-productive.&lt;/li&gt;
&lt;/ul&gt;    &lt;p&gt;L'ouverture impossible à prévoir ainsi que les références circulaires sont deux grand ennemis de l'architecte.&lt;/p&gt;


&lt;p&gt;On a vu il y a déjà quelques années que le principe OCP (Open Close Principle), principe à appliquer afin d'ouvrir son code de manière à autoriser les extensions futures, nécessite de faire des choix dans son design. Puisqu'il est impossible d'ouvrir complètement le code, il convient de choisir de manière stratégique quelles sont les parties qui risquent d'être étendue. Une fois ces parties décidées, il devient possible de prévoir l'ouverture de code nécessaire à la gestion de futures évolutions. Mais si il est impossible de prévoir dans quel sens les règles d'un jeu peuvent être modifiées, comment faire pour ouvrir son code de manière stratégique&amp;nbsp;?&lt;/p&gt;


&lt;p&gt;Les références circulaires posent en plus un autre problème&amp;nbsp;: celui du couplage du code. Dans l'idéal, on devrait pouvoir arranger les classes d'un projet en strates. Plus on descend dans les strates, moins on est abstrait. Bien évidemment, les classes d'une strate ne peuvent dépendre que des classes de la même strate ou d'une strate supérieure, jamais des classes d'une strate inférieure. Il y a bel et bien une relation hiérarchique entre les classes. Dans le système de règle d'un jeu de rôle, il est relativement fréquent qu'une règle particulière très concrète modifie une règle plus générale et plus abstraite. Dans ces conditions, il devient difficile de générer un diagramme de classe élimine les références circulaires.&lt;/p&gt;


&lt;p&gt;Bien sûr, difficile ne veut pas dire impossible.&lt;/p&gt;


&lt;h3&gt;Allez, on réfléchi un peu&lt;/h3&gt;

&lt;p&gt;D'un point de vue personnel, j'utilise principalement deux systèmes de jeu&amp;nbsp;: le système D20 mis en place par Wizard of the Coast comme support du jeu de rôle Dungeons &amp;amp; Dragons, et le système BASIC utilisé par les jeux publiés par la société Chaosium, éditrice entre autre de l'Appel de Cthulhu (dont je vous recommande chaudement la 6ème édition française, qui étonnamment est légèrement meilleure que la 6ème édition en version originale). Le système BASIC est très simple&amp;nbsp;: en fait, la création des personnages est rationalisée et ne nécessite aucune règle particulière qui aurait un effet quelconque sur une règle plus générale. Chaque personnage est défini par un certain nombre de caractéristiques et un certain nombre de compétences (qui peuvent dépendre des caractéristiques). L'équipement peut fournir des bonus lors de l'utilisation d'une compétence. Au niveau social, un personnage est défini par son occupation, son métier et les cercles d'influences sur lequel il a un impact. En terme d'architecture logicielle, on a un système purement descendant&amp;nbsp;: on va toujours soit du général vers le particulier, soit du particulier vers le général. Le seul point qui échappe à cette règle concerne le métier du personnage - le personnage choisi ses compétences en fonction de son occupation professionnelle, et son métier en fonction de ses scores de compétence. Toutefois, ce système peut quand même être modélisé simplement par strates.&lt;/p&gt;


&lt;p&gt;En terme d'ouvertures, l'ensemble est aussi relativement simple&amp;nbsp;: les options de jeu autorise les joueurs à utiliser des compétences non prévues, ou du nouveau matériel, ou à choisir une nouvelle occupation&amp;nbsp;; de manière générale, un nouvel élément de règle peut être symbolisé par une nouvelle classes à une strate donnée. Il est donc relativement aisé de prévoir de manière stratégique les strates de classes qu'il faudra ouvrir afin de permettre d'éventuelles extensions des règles.&lt;/p&gt;


&lt;p&gt;Dungeons &amp;amp; Dragons se révèle très différent. Même si les règles de la quatrième édition ont été retravaillée pour être plus simples et plus accessible, de nombreux points peuvent poser problème à l'architecte logiciel.&lt;/p&gt;


&lt;p&gt;Si on ne prends en compte que les règles générales, on se retrouve dans une situation proche de celle présentée dans les paragraphes précédents et qui concerne l'Appel de Cthulhu. Un joueur choisi sa race et sa classe, puis détermine les caractéristiques de son personnage et ses compétences, puis choisit ses talents, ses pouvoirs et son équipement. Dans l'ensemble, le système reste descendant et peut être arrangé en strate. Le problème est posé par une simple petite phrase résumant la philosophie des règles&amp;nbsp;: le particulier prends le pas sur le général. De fait, il est possible d'imaginer un talent qui ne peut être pris que si une compétence particulière a été sélectionnée au moment de la création du personnage et qui modifie une autre compétence.&lt;/p&gt;


&lt;blockquote&gt;&lt;p&gt;&lt;strong&gt;Exemple de talent&amp;nbsp;: persuasif&lt;/strong&gt;&lt;br /&gt;
&lt;em&gt;Condition&lt;/em&gt;&amp;nbsp;: entraîné en Intimidation&lt;br /&gt;
&lt;em&gt;Effet&lt;/em&gt;&amp;nbsp;: le personnage bénéficie d'un bonus de +2 à la compétence Diplomatie.&lt;/p&gt;&lt;/blockquote&gt;


&lt;p&gt;Ce talent affecte la liste des compétences tout en étant dépendante d'elle. Mathématiquement, on se retrouve avec une référence circulaire évidente (les compétences affectent le talent qui affecte les compétence).&lt;/p&gt;


&lt;p&gt;En ce qui concerne l'ouverture, de nombreux problèmes se posent. Quel que soit la strate de classes considérée, elle peut avoir un effet quelconque sur une autre strate de classes. Ainsi, un objet peut avoir un effet sur les caractéristiques, les compétences, les pouvoirs à disposition, les talents, etc. Un talent peut de même avoir un effet sur l'équipement accessible, les compétences, les caractéristiques, les pouvoirs à disposition, etc. De plus, en considérant bien le système de règle existant, il est tout à fait possible d'imaginer que la définition même des caractéristiques et des compétences puisse être modifiée. C'est déjà arrivé&amp;nbsp;: ainsi, une compétence particulière peut voir son cercle d'action élargi par de nouvelles règles.&lt;/p&gt;


&lt;p&gt;On le voit, l'architecture logicielle à même d'encoder un tel système regorge de pièges et sera difficile à mettre en place. D'une part, elle doit luter pour préserver le plus possible la notion de système en strate qui est nécessaire à l'application correcte de plusieurs des principes fondamentaux de l'architecture orientée objet déjà discutés dans ces pages&amp;nbsp;; d'autre part elle doit aussi permettre un accès à toute donnée modifiable, puisqu'elle ne peut prévoir la variété infinie des modifications au corpus de règle pouvant subvenir. Et comme ces deux désidérata vont dans le sens contraire, il va falloir réfléchir pour trouver des solutions acceptables...&lt;/p&gt;


&lt;p&gt;&lt;em&gt;La suite dans quelques jours...&lt;/em&gt;&lt;/p&gt;</description>
    
    
    
          <comments>http://blog.emmanueldeloget.com/index.php?post/2009/10/19/140-implementation-d-un-systeme-de-regle-pour-un-jeu-de-role-introduction#comment-form</comments>
      <wfw:comment>http://blog.emmanueldeloget.com/index.php?post/2009/10/19/140-implementation-d-un-systeme-de-regle-pour-un-jeu-de-role-introduction#comment-form</wfw:comment>
      <wfw:commentRss>http://blog.emmanueldeloget.com/index.php?feed/atom/comments/127</wfw:commentRss>
      </item>
    
  <item>
    <title>Etude du C++ Technical Report 1 - reference_wrapper : je confirme, c'est tordu.</title>
    <link>http://blog.emmanueldeloget.com/index.php?post/2008/09/01/138-etude-du-c-technical-report-1-reference_wrapper-je-confirme-c-eest-tordu</link>
    <guid isPermaLink="false">urn:md5:8ae3d489e23b6624780d4bd35e8ce172</guid>
    <pubDate>Mon, 01 Sep 2008 14:00:00 +0000</pubDate>
    <dc:creator>Emmanuel Deloget</dc:creator>
        <category>C++</category>
            
    <description>&lt;p&gt;Souvenez vous&amp;nbsp;: il y a près de deux ans, j'essayais avec grand peine d'implémenter la classe &lt;code&gt;std::tr1::reference_wrapper&amp;lt;&amp;gt;&lt;/code&gt;, et j'ai du abandonner.Tout content de pouvoir installer l'implémentation du TR1 de Microsoft Visual C++ 2008 SP1, j'ai tenu à vérifier que mon échec épique n'était pas du à ma stupidité, mais à (comme je le pense sincèrement) une mauvaise formulation du texte du TR1.&lt;/p&gt;    &lt;p&gt;Le problème se situe dans le document &lt;a href=&quot;http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2005/n1836.pdf&quot; hreflang=&quot;zp&quot;&gt;ISO/IEC DT 19768&lt;/a&gt; (pdf), section 2.1.2, paragraphes 2, 3, 4.&lt;/p&gt;


&lt;blockquote&gt;&lt;p&gt;2. reference_wrapper has a weak result type (&lt;a href=&quot;http://blog.emmanueldeloget.com/index.php?post/2008/09/01/3.3&quot;&gt;3.3&lt;/a&gt;).&lt;br /&gt;&lt;br /&gt;
3. The template instantiation &lt;code&gt;reference_wrapper&amp;lt;T&amp;gt;&lt;/code&gt; shall be derived from &lt;code&gt;std::unary_function&amp;lt;T1, R&amp;gt;&lt;/code&gt; only if the type T is any of the following:&lt;br /&gt;
-- a function type or a pointer to function type taking one argument of type T1 and returning R&lt;br /&gt;
-- a pointer to member function type with cv-qualifier cv and no arguments; the type T1 is cv T* and R is the return type of the pointer to member function&lt;br /&gt;
-- a class type that is derived from &lt;code&gt;std::unary_function&amp;lt;T1, R&amp;gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;
4. The template instantiation &lt;code&gt;reference_wrapper&amp;lt;T&amp;gt;&lt;/code&gt; shall be derived from &lt;code&gt;std::binary_function&amp;lt;T1, T2, R&amp;gt;&lt;/code&gt; only if the type T is any of the following:&lt;br /&gt;
-- a function type or a pointer to function type taking two arguments of types T1 and T2 and returning R&lt;br /&gt;
-- a pointer to member function with cv-qualifier cv and taking one argument of type T2; the type T1 is cv T* and R is the return type of the pointer to member function&lt;br /&gt;
-- a class type that is derived from &lt;code&gt;std::binary_function&amp;lt;T1, T2, R&amp;gt;&lt;/code&gt;&lt;/p&gt;&lt;/blockquote&gt;


&lt;p&gt;Des paragraphes 3 et 4, il découle que si la class &lt;code&gt;C1&lt;/code&gt; dérive à la fois de &lt;code&gt;std::unary_function&amp;lt;&amp;gt;&lt;/code&gt; et &lt;code&gt;std::binary_function&amp;lt;&amp;gt;&lt;/code&gt;, alors &lt;code&gt;reference_wrapper&amp;lt;C1&amp;gt;&lt;/code&gt; doit dériver de ces deux types.&lt;/p&gt;


&lt;p&gt;Le paragraphe 2 nous renvoie à la section 3.3, paragraphe 3.&lt;/p&gt;


&lt;blockquote&gt;&lt;p&gt;3. If a call wrapper (&lt;a href=&quot;http://blog.emmanueldeloget.com/index.php?post/2008/09/01/3.1&quot;&gt;3.1&lt;/a&gt;) has a weak result type the type of its member type &lt;code&gt;result_type&lt;/code&gt; is based on the type T of the wrapper’s target object (&lt;a href=&quot;http://blog.emmanueldeloget.com/index.php?post/2008/09/01/3.1&quot;&gt;3.1&lt;/a&gt;):&lt;br /&gt;
-- if T is a function, reference to function, or pointer to function type, &lt;code&gt;result_type&lt;/code&gt; shall be a synonym for the return type of T;&lt;br /&gt;
-- if T is a pointer to member function, &lt;code&gt;result_type&lt;/code&gt; shall be a synonym for the return type of T;&lt;br /&gt;
-- if T is a class type with a member type &lt;code&gt;result_type&lt;/code&gt;, then &lt;code&gt;result_type&lt;/code&gt; shall be a synonym for &lt;code&gt;T::result_type&lt;/code&gt;;&lt;br /&gt;
-- otherwise result_type shall not be defined.&lt;/p&gt;&lt;/blockquote&gt;


&lt;p&gt;Puisque &lt;code&gt;std::unary_function&amp;lt;&amp;gt;&lt;/code&gt; et &lt;code&gt;std::binary_function&amp;lt;&amp;gt;&lt;/code&gt; définissent tous les deux le type &lt;code&gt;result_type&lt;/code&gt;, &lt;code&gt;C1&lt;/code&gt; hérite de ces types. Dans ce contexte, faire référence à &lt;code&gt;C1::result_type&lt;/code&gt; provoque une erreur du à l'ambiguïté. Dans ce contexte, il est normalement impossible de définir &lt;code&gt;reference_wrapper&amp;lt;C1&amp;gt;::result_type&lt;/code&gt;.&lt;/p&gt;


&lt;p&gt;Je suis rassuré par le fait suivant: l'implémentation du TR1 fournie par Microsoft dans Visual C++ 2008 SP1 butte sur ce problème. L'implémentation présente dans GCC élimine le problème en considérant que &lt;code&gt;C1&lt;/code&gt; ne définit pas de type &lt;code&gt;result_type&lt;/code&gt; (ce qui n'est pas illogique, mais la technique de découverte de cette information n'est pas portable de GCC à Visual C++ -- et le &lt;a href=&quot;http://www.comeaucomputing.com/&quot; hreflang=&quot;en&quot;&gt;compilateur Comeau&lt;/a&gt; se comporte encore de manière différente vis-à-vis de ce problème).&lt;/p&gt;


&lt;p&gt;Mon échec n'était donc pas si épique. Ou alors, il l'est encore plus que ce que j'imaginais (à savoir que le cas cité n'est même pas censé se présenter dans votre code si vous êtes un tant soit peu respectueux des autres personnes qui travaillent avec vous...).&lt;/p&gt;</description>
    
    
    
          <comments>http://blog.emmanueldeloget.com/index.php?post/2008/09/01/138-etude-du-c-technical-report-1-reference_wrapper-je-confirme-c-eest-tordu#comment-form</comments>
      <wfw:comment>http://blog.emmanueldeloget.com/index.php?post/2008/09/01/138-etude-du-c-technical-report-1-reference_wrapper-je-confirme-c-eest-tordu#comment-form</wfw:comment>
      <wfw:commentRss>http://blog.emmanueldeloget.com/index.php?feed/atom/comments/125</wfw:commentRss>
      </item>
    
</channel>
</rss>