<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>
<channel>
	<title>La Case de l&#039;Oncle Tom &#187; optimisation</title>
	<atom:link href="http://case.oncle-tom.net/tag/optimisation/feed/" rel="self" type="application/rss+xml" />
	<link>http://case.oncle-tom.net</link>
	<description>Développement Web, bonnes pratiques et performances</description>
	<lastBuildDate>Sun, 25 Dec 2011 19:33:29 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
<atom:link rel="search"
           href="http://case.oncle-tom.net/opensearch"
           type="application/opensearchdescription+xml"
           title="Content Search" />		<item>
		<title>Paris-Web 2010 : industrialiser l&#8217;artisanat de l&#8217;intégration HTML</title>
		<link>http://case.oncle-tom.net/2010/paris-web-industrialiser-integration-html/</link>
		<comments>http://case.oncle-tom.net/2010/paris-web-industrialiser-integration-html/#comments</comments>
		<pubDate>Mon, 20 Sep 2010 09:00:04 +0000</pubDate>
		<dc:creator>Oncle Tom</dc:creator>
				<category><![CDATA[Développement Web]]></category>
		<category><![CDATA[Standards du Web]]></category>
		<category><![CDATA[atelier]]></category>
		<category><![CDATA[blueprint]]></category>
		<category><![CDATA[bonnes pratiques]]></category>
		<category><![CDATA[css]]></category>
		<category><![CDATA[discussion]]></category>
		<category><![CDATA[html]]></category>
		<category><![CDATA[industrialisation]]></category>
		<category><![CDATA[oocss]]></category>
		<category><![CDATA[optimisation]]></category>
		<category><![CDATA[parisweb]]></category>
		<category><![CDATA[performances]]></category>
		<guid isPermaLink="false">http://case.oncle-tom.net/?p=17526</guid>
		<description><![CDATA[Je présente un nouvel atelier Paris-Web : "industrialiser l'artisanat de l'intégration HTML" le samedi 16 octobre 2010 à Télécom Paris. Présentation de l'atelier, pourquoi j'ai décidé de l'animer et comment il va s'organiser.
Une chose est sure : on va tous réfléchir ensemble !]]></description>
			<content:encoded><![CDATA[<p>J&#8217;ai le plaisir d&#8217;animer un atelier technique à <a href="http://www.paris-web.fr">Paris-Web</a> pour la troisième année consécutive. Mon premier atelier, en 2008, traitait des <strong>frameworks <acronym title="Cascading Style Sheets">CSS</acronym></strong> ; et en 2009, des capacités de Gears et d&#8217;HTML5 pour <strong>construire un site Web consultable hors-ligne</strong>.</p>
<p>Je reviens aux sources et à mon grand dada avec l&#8217;<strong>intégration <acronym title="HyperText Markup Language">HTML</acronym></strong> au sens large du terme. J&#8217;ai choisi d&#8217;intituler cet atelier : <a href="http://www.paris-web.fr/2010/programme/industrialiser-lartisanat-de-lintegration-html.php">industrialiser l&#8217;artisanat de l&#8217;intégration <acronym title="HyperText Markup Language">HTML</acronym></a>. Rendez-vous le samedi 16 octobre 2010 à 10h50 dans les locaux de <a href="http://www.telecom-paristech.fr/">Télécom Paris</a> pour en discuter &#8230; et maintenant, pour le préparer et en dessiner les contours.</p>
<p><img class="aligncenter size-medium wp-image-17530" title="Paris-Web" src="http://case.oncle-tom.net/images/2010/09/logotype-paris-web-300x203.png" alt="" width="300" height="203" /></p>
<p><span id="more-17526"></span></p>
<h3>Origine de l&#8217;atelier</h3>
<p>Juste après l&#8217;édition 2009 de Paris-Web, je me demandais sur quoi je pourrais parler en conférence ou en atelier. Cette manifestation a le mérite d&#8217;attirer des orateurs de qualité &#8230; et ce n&#8217;est pas évident de monter sur scène en se disant : que pourrais-je apporter au public, qui ne soit pas de la redite et suscite autant d&#8217;intérêt qu&#8217;une <a href="http://stephanietroeth.com/">Stéphanie Troeth</a>, <a href="http://www.la-grange.net/">Karl Dubost</a> ou <a href="http://icant.co.uk/">Christian Heilmann</a>.</p>
<p>Et là j&#8217;ai lu <a href="http://blog.temesis.com/post/2009/12/15/Ma-lettre-a-papa-ParisWeb">la lettre au papa Paris-Web d&#8217;Elie Sloïm</a>. J&#8217;ai de suite pensé à un sujet lié à l&#8217;<strong>intégration <acronym title="HyperText Markup Language">HTML</acronym></strong>. Cette spécialité connaît une effervescence d&#8217;outils depuis 2008 (<em>frameworks</em> <acronym title="Cascading Style Sheets">CSS</acronym>, pré-processeurs <acronym title="Cascading Style Sheets">CSS</acronym> et performances Web) &#8230; pourtant les méthodes de travail restent toujours très liées au développeur, à son tempérament et à ses connaissances d&#8217;outils capables d&#8217;améliorer la productivité. Quelque chose de tout sauf normalisé, industrialisé.</p>
<p>Comme il s&#8217;agit également d&#8217;une pratique ayant du mal à accepter les changements &#8211; je me souviens encore des réticences liées aux <em>frameworks</em>, alors que dans tout langage de programmation ces outils sont perçus comme du pain béni &#8211; je me suis dis qu&#8217;il y avait quelque chose à faire.</p>
<h3>Les axes initiaux de l&#8217;atelier</h3>
<p>En préparant l&#8217;appel à propositions de Paris-Web, j&#8217;avais convenu que cet atelier devrait tenter de répondre aux objectifs suivants :</p>
<ul>
<li>dresser un état de l&#8217;art de l&#8217;intégration <acronym title="HyperText Markup Language">HTML</acronym></li>
<li>offrir une large tribune à l&#8217;audience, notamment en partageant ses  propres retours d&#8217;expérience</li>
<li>déterminer ce dont on dispose et ce dont on manque en terme  d&#8217;outillage</li>
</ul>
<p>Par extension, je souhaitais répondre (au moins) à ces questions :</p>
<ul>
<li>comment bâtir des <acronym title="Cascading Style Sheets">CSS</acronym> indépendantes et réutilisables ?</li>
<li>quand et comment utiliser un préprocesseur <acronym title="Cascading Style Sheets">CSS</acronym> ?</li>
<li>comment dialoguer avec le graphiste ?</li>
<li>comment dialoguer avec le développeur ?</li>
<li>comment détecter les régressions et assurer une qualité de code en  <acronym title="Cascading Style Sheets">CSS</acronym> ?</li>
</ul>
<p>J&#8217;ai également repris l&#8217;historique des précédents Paris-Web pour voir que de précédents ateliers s&#8217;étaient déjà penchés sur la question de la chaine d&#8217;intégration. D&#8217;où mon souhait de ne pas forcément réinventer la roue.</p>
<p>Pour autant, les objectifs tout comme les questions ne sont pas figées dans le marbre. Cet article est également là pour <strong>capter vos avis et vos remarques</strong>, pour ajuster cela avant le jour de l&#8217;atelier.</p>
<h3>Discuter, échanger, et créer</h3>
<p>Enfin, mon évolution personnelle au long de cette année 2010 et certaines paroles de <a href="http://larlet.fr/">David Larlet</a> résonnaient dans ma tête.<br />
Un sujet de cette importance ne peut pas être magistral. Pourquoi ? Parce que tous les intégrateurs rencontrent une <strong>variété de conditions de travail différentes</strong>, et qu&#8217;il serait d&#8217;autant plus difficile d&#8217;obtenir un consensus en prodiguant cet atelier de manière magistrale.</p>
<p>D&#8217;où l&#8217;idée d&#8217;introduire l&#8217;atelier par un <strong>bref résumé de mes retours d&#8217;expérience</strong> sur les <em>frameworks</em> (existants, ou créés pour le besoin), les pré-processeurs <acronym title="Cascading Style Sheets">CSS</acronym>, leur combinaison ainsi que l&#8217;application de la philosophie <a href="http://oocss.org/">Object Oriented <acronym title="Cascading Style Sheets">CSS</acronym></a>. Quelque chose comme 10/15 minutes maximum.</p>
<p>Le reste du temps serait réparti de manière équitable sur chacune des questions, et <strong>animé sous forme de discussion</strong>. Chaque participant répondrait (<em>via</em> des post-it, je les fournirai <img src='http://case.oncle-tom.net/wp-includes/images/smilies/icon_wink.gif' alt=';-)' class='wp-smiley' /> ) par 1 ou plusieurs réponses, positives et négatives. En gros, ce qu&#8217;il faut faire, et ce qu&#8217;il ne faut pas faire.</p>
<p>Cette collecte en <em>live</em> des post-it, affichés au tableau, permettrait de dresser une <strong>cartographie des bonnes et mauvaises pratiques</strong>, des actions à mener et dont il faut se méfier.</p>
<p>A défaut de parler d&#8217;une industrialisation vidant l&#8217;intégration <acronym title="HyperText Markup Language">HTML</acronym> de son côté artisanal, on aurait une excellente occasion pour tous se poser ensemble les bonnes questions, et <strong>repartir avec des réponses et des idées pleins la tête</strong>.</p>
<h3>Conclusion</h3>
<p>Bref, si le sujet de l&#8217;intégration <acronym title="HyperText Markup Language">HTML</acronym> vous préoccupe, est au centre de vos intérêts et que vous souhaitez en améliorer sa pratique professionnelle (pour une meilleure reconnaissance de celle-ci ?), je vous invite à la fois à venir à l&#8217;atelier technique du samedi (<a href="http://inscriptions.paris-web.fr/">il reste quelques places ; ça ne coûte que 22€</a>) et à réagir en commentaires. Je ferai mon possible pour adapter l&#8217;animation de l&#8217;atelier à vos problématiques et questionnements.</p>
<p>Cet atelier serait ainsi à l&#8217;image de Paris-Web : une <strong>grande discussion conviviale, constructive et enrichissante</strong>.<br />
L&#8217;idée sera ensuite de concrétiser ces échanges soit par un ensemble de billets de blogs soit, si la matière le permet, en <strong>livre blanc</strong>.</p>
<p>Ne me demandez pas ce que je prévois pour 2011, je n&#8217;en ai aucune idée &#8230; <em>pour l&#8217;instant</em> <img src='http://case.oncle-tom.net/wp-includes/images/smilies/icon_wink.gif' alt=';-)' class='wp-smiley' /> </p>]]></content:encoded>
			<wfw:commentRss>http://case.oncle-tom.net/2010/paris-web-industrialiser-integration-html/feed/</wfw:commentRss>
		<slash:comments>16</slash:comments>
		</item>
		<item>
		<title>WordPress en tant que dépendance SVN</title>
		<link>http://case.oncle-tom.net/2008/wordpress-svn-external/</link>
		<comments>http://case.oncle-tom.net/2008/wordpress-svn-external/#comments</comments>
		<pubDate>Tue, 23 Dec 2008 06:00:59 +0000</pubDate>
		<dc:creator>Oncle Tom</dc:creator>
				<category><![CDATA[WordPress]]></category>
		<category><![CDATA[bonne pratique]]></category>
		<category><![CDATA[code]]></category>
		<category><![CDATA[codex]]></category>
		<category><![CDATA[htaccess]]></category>
		<category><![CDATA[i18n]]></category>
		<category><![CDATA[logiciels libres]]></category>
		<category><![CDATA[optimisation]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[plugins]]></category>
		<category><![CDATA[svn]]></category>
		<category><![CDATA[wordpress mu]]></category>
		<guid isPermaLink="false">http://case.oncle-tom.net/?p=1237</guid>
		<description><![CDATA[Mettre à jour WordPress était pénible jusqu&#8217;à l&#8217;arrivée de la version 2.7. On bénéficie désormais de la mise à jour automatique : un clic, ça télécharge et ça déploie. Il existe cependant une méthode alternative reposant sur Subversion (SVN). C&#8217;est la méthode idéale pour tout développeur WordPress ou gestionnaire de blogs. C&#8217;est celle que j&#8217;emploie [...]]]></description>
			<content:encoded><![CDATA[<p>Mettre à jour WordPress était pénible jusqu&#8217;à l&#8217;arrivée de la version 2.7. On bénéficie désormais de la mise à jour automatique : un clic, ça télécharge et ça déploie.</p>
<p><img class="aligncenter size-full wp-image-912" title="Logo WordPress" src="http://case.oncle-tom.net/images/2008/05/wordpress-logo.png" alt="" width="273" height="66" /></p>
<p>Il existe cependant une <strong>méthode alternative reposant sur Subversion</strong> (<acronym title="Subversion">SVN</acronym>). C&#8217;est la méthode idéale pour tout développeur WordPress ou gestionnaire de blogs. C&#8217;est celle que j&#8217;emploie depuis la version 2.6 grâce notamment à la constante WP_CONTENT.</p>
<p>Explications et application concrète.</p>
<p><span id="more-1237"></span></p>
<p>Avant toute chose, sachez que <strong>ce tutorial est optimisé pour les personnes qui versionnent entièrement leur projet</strong>. Il n&#8217;est pas question ici d&#8217;avoir une arborescence libre et de procéder à des <em>checkout</em> un peu partout. C&#8217;est possible mais pas du plus grand intérêt.</p>
<p>L&#8217;avantage évident ici est de pouvoir déployer son blog n&#8217;importe où en un rien de temps.</p>
<h3>Structure des fichiers</h3>
<p>Installer WordPress en tant que dépendance <acronym title="Subversion">SVN</acronym> revient à mélanger 2 techniques :</p>
<ul>
<li><a href="http://codex.wordpress.org/Giving_WordPress_Its_Own_Directory">Installer WordPress dans son propre répertoire<br />
</a></li>
<li><a href="http://codex.wordpress.org/Installing_WordPress_With_Clean_Subversion_Repositories">Installer WordPress proprement depuis <acronym title="Subversion">SVN</acronym></a></li>
</ul>
<p>Je suis pénible donc je n&#8217;ai pas spécialement envie de modifier un fichier <em>core</em> ou autre chose que <em>wp-config.php</em>. Tout le contraire de ce qu&#8217;indique la première méthode.</p>
<p>La seconde explication m&#8217;a toutefois posé légèrement problème puisqu&#8217;un peu brutale et posant soucis chez OVH.</p>
<img class="size-full wp-image-1254" title="Arborescence fichier avec WordPress SVN" src="http://case.oncle-tom.net/images/2008/12/wordpress-svn-basic-filetree.png" alt="Arborescence fichier avec WordPress SVN" width="329" height="298" />
<p>Celles et ceux qui voient la capture d&#8217;écran ci-dessus peuvent constater que <em>tout WordPress</em> a été déplacé dans un sous-répertoire <em>wordpress</em> au même niveau que wp-content.<br />
On ne garde à la racine que le fichier <em>.htaccess</em> et <em>wp-config.php</em>.</p>
<p>Sur le répertoire racine, j&#8217;ai appliqué ces propriétés pour WordPress 2.7 :</p>
<ul>
<li><kbd>svn:ignore</kbd> :<kbd><br />
</kbd></p>
<pre><code class="svn">wp-config.php</code></pre>
</li>
<li><kbd>svn:externals</kbd> :<kbd><br />
</kbd></p>
<pre><code class="svn">wordpress http://svn.automattic.com/wordpress/branches/2.7</code></pre>
</li>
</ul>
<p>Je ne versionne volontairement pas le fichier wp-config.php car c&#8217;est le seul fichier susceptible de changer d&#8217;une instance à une autre. Je le récupère depuis wordpress/wp-config-sample.php et je le personnalise selon mes besoins.<br />
Et puis versionner des mots de passe &#8230; qui y tient ?</p>
<h3>Configuration</h3>
<p>Après cette restructuration, on aura toutefois besoin de configurer 2-3 bricoles. Vraiment rien de méchant promis.</p>
<h4>Le .htaccess</h4>
<p>Voici ma configuration. Elle peut être aisément déportée dans votre déclaration de <em>Virtual Host</em> pour des raisons de performance. Sur un serveur mutualisé vous n&#8217;avez en général pas accès à ce dernier type de configuration.</p>
<pre><code>&lt;IfModule mod_rewrite.c&gt;
Options -Multiviews -Indexes +FollowSymlinks
RewriteEngine On
RewriteBase /
# Moving to dependency
RewriteRule ^(index.php|wp-[a-z0-9-]+\.php|xmlrpc.php)?$ wordpress/$1 [L]
RewriteRule ^(wp-admin|wp-includes)/(.*)$ wordpress/$1/$2 [QSA,L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . wordpress/index.php [L]
&lt;/IfModule&gt;
# BEGIN WordPress
# END WordPress</code></pre>
<p>Ce fichier est très inspiré de la <a href="http://codex.wordpress.org/Installing_WordPress_With_Clean_Subversion_Repositories">configuration <acronym title="Subversion">SVN</acronym> proposée sur le Codex WordPress</a>. Seulement voilà, cette renvoie tout sur <em>index.php</em> &#8230; et omet ainsi tous les accès aux fichiers situés à la racine, avec entre autre :</p>
<ul>
<li>wp-cron.php</li>
<li>wp-link-opml.php</li>
<li>wp-trackback.php</li>
<li>xmlrpc.php</li>
</ul>
<p>Je vous fais grâce des contrôleurs de flux (Atom, <acronym title="Really Simple Syndication">RSS</acronym> &amp; cie) et des appels en directs à <em>index.php</em> effectués par certains plugins.</p>
<p>Donc non on ne peut pas vraiment se passer de ces fichiers. D&#8217;où ces 2 règles :</p>
<ul>
<li>
<pre><code>RewriteRule ^(index.php|wp-[a-z0-9-]+\.php|xmlrpc.php)?$ wordpress/$1 [L]
</code></pre>
<p>On capte tous les fichiers <acronym title="Pre-Hypertext Processing">PHP</acronym> (les contrôleurs) originellement situés à la racine de WordPress.</li>
<li>
<pre><code>RewriteRule ^(wp-admin|wp-includes)/(.*)$ wordpress/$1/$2 [QSA,L]</code></pre>
<p>Et là c&#8217;est pour le confort de conserver les adresses initiales &#8230; mais aussi pour éviter de modifier un bout de paramétrage dans l&#8217;admin. Le jour où vous décidez de rebasculer à l&#8217;ancien système, ça se fera sans douleur <img src='http://case.oncle-tom.net/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' /> </li>
</ul>
<p>Enfin, pourquoi avoir poussé les commentaires WordPress vers le bas ? Tout simplement pour <strong>éviter que nos règles personnalisées soient écrasées par WordPress</strong> lors d&#8217;une mise à jour des permaliens. Nos règles primeront toujours ainsi.</p>
<h4>Le fichier wp-config.php</h4>
<p>Dans le fichier <em>wp-config.php</em>, nous n&#8217;allons rien modifier. Nous allons juste ajouter forcer 2 paramètres. Ils indiqueront à WordPress où se trouve le véritable répertoire <em>wp-content</em> (renommable mais je ne jouerai pas avec).</p>
<img class="size-full wp-image-1262" title="wp-config.php modifié pour WordPress SVN" src="http://case.oncle-tom.net/images/2008/12/wordpress-svn-wpconfig.png" alt="wp-config.php modifié pour WordPress SVN" width="600" height="266" />
<h4>Le blog</h4>
<p>Bon j&#8217;ai menti un peu toute à l&#8217;heure en indiquant qu&#8217;on ne toucherait qu&#8217;à <em>wp-config.php</em>. Cependant la modification est on ne peut plus mineure et ne concerne que l&#8217;upload de medias.</p>
<p>En effet si on ne touche pas à l&#8217;emplacement des fichiers envoyés, WordPress considère qu&#8217;ils sont uploadés dans wordpress/wp-content/uploads. C&#8217;est fort gênant mais heureusement, en préfixant le chemin par ../ ou en tapant un chemin absolu tout rentrera dans l&#8217;ordre.</p>
<img class="size-full wp-image-1261" title="Correction de chemin pour WordPress SVN" src="http://case.oncle-tom.net/images/2008/12/wordpress-svn-file-uploads-fix.png" alt="Correction de chemin pour WordPress SVN" width="600" height="74" />
<p>À noter qu&#8217;il s&#8217;agit du <strong>seul paramétrage hors d&#8217;un fichier</strong>. Si j&#8217;avais pu m&#8217;en passer je l&#8217;aurais fait.</p>
<h3>Dépendance <acronym title="Subversion">SVN</acronym> pour la traduction</h3>
<p>C&#8217;est en tombant sur un autre <a href="http://sunfox.org/blog/2007/05/28/installation-svn-de-wordpress-et-de-ses-plugins/">article traitant de svn:externals pour WordPress</a> que j&#8217;ai été interpelé sur la prise en charge des langues via <acronym title="Subversion">SVN</acronym> également.<br />
Le système n&#8217;est pas parfait puisqu&#8217;on ne peut gérer qu&#8217;une seule langue par ce biais là. Ça ne conviendra donc pas aux blogs multilingues.</p>
<img class="size-full wp-image-1260" title="Dépendance SVN pour les traductions WordPress" src="http://case.oncle-tom.net/images/2008/12/wordpress-i18n-svn-external.png" alt="Dépendance SVN pour les traductions WordPress" width="550" height="104" />
<p>La technique consiste à transformer <code>wp-content/languages</code> en <kbd>svn:externals</kbd>.<br />
Ça donnerait ceci pour la version française de WordPress 2.7, au niveau du <kbd>svn:externals</kbd> du répertoire <code>wp-content</code> :</p>
<pre><code class="svn">languages http://svn.automattic.com/wordpress-<acronym title="internationalisation">i18n</acronym>/fr_FR/branches/2.7/messages/</code></pre>
<p><strong>Simple et efficace</strong> mais ça reste encore de la bricole.</p>
<h3>Cas particulier : plugins et <acronym title="internationalisation">i18n</acronym></h3>
<p>Je vous expose le problème mais malheureusement vous ne pourrez pas y faire grand chose. Par contre ami développeurs, pour rendre votre code de plugin 100% portable, merci de prendre note <img src='http://case.oncle-tom.net/wp-includes/images/smilies/icon_wink.gif' alt=';-)' class='wp-smiley' /> </p>
<p>Le chargement des traductions s&#8217;effectue à l&#8217;aide de la fonction load_plugin_textdomain(). Elle prenait seulement 2 paramètres jusqu&#8217;à l&#8217;arrivée de WordPress 2.6. Ça n&#8217;a pas été crié sur les toits mais elle prend désormais 3 &#8230; et c&#8217;est du 3ème argument qu&#8217;il faut utiliser désormais :</p>
<ol>
<li><code class="php">$domain</code> : l&#8217;espace de nom des traduction (inchangé)</li>
<li><code class="php">$abs_rel_path</code> : chemin relatif par rapport à l&#8217;emplacement de WordPress (déprécié, on y mettait <code>PLUGINDIR.'/'.dirname(plugin_basename(__FILE__))</code> en général)</li>
<li><code class="php">$plugin_rel_path</code> :  chemin relatif par rapport à l&#8217;emplacement des plugins (c&#8217;est qui nous intéresse ; <code>dirname(plugin_basename(__FILE__))</code> nous suffira désormais)</li>
</ol>
<p>Vous trouverez un <a href="http://codex.wordpress.org/Writing_a_Plugin#Internationalizing_Your_Plugin">exemple sur le Codex, du côté de l&#8217;internationalisation des plugins</a>.<br />
Un exemple de code pérenne :</p>
<pre><code class="php">load_plugin_textdomain('votreplugin', dirname(plugin_basename(__FILE__)), dirname(plugin_basename(__FILE__)));</code></pre>
<p>Et si jamais vous utilisez votre plugin en lien symbolique ça ne fonctionnera pas &#8230; mais on s&#8217;éloigne du sujet <img src='http://case.oncle-tom.net/wp-includes/images/smilies/icon_wink.gif' alt=';-)' class='wp-smiley' /> </p>
<h3>Et pour WordPress Mu ?</h3>
<p>Je ne m&#8217;attarderai pas dessus mais les manipulations sont sensiblement les mêmes. Je n&#8217;ai pas encore eu l&#8217;occasion d&#8217;essayer mais j&#8217;ose imaginer qu&#8217;il n&#8217;y a pas tant de différences que ça <img src='http://case.oncle-tom.net/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' /> </p>
<h3>Conclusion</h3>
<p>Le jour où vous souhaitez migrer vers une autre version majeure de WordPress, c&#8217;est simple :<strong> il suffit de changer les externals vers le tag adéquat</strong>.</p>
<p>Pourquoi ne pas utiliser le <em>trunk</em> directement me demanderez-vous ? Le trunk de WordPress est plutôt instable puisque c&#8217;est là que se construit la prochaine version de manière systématique. L&#8217;utilisation des <strong>branches permet de bénéficier des correctifs</strong> sans avoir à modifier le moindre external.<br />
Si vous avez un grand besoin de stabilité, alors utilisez les <em>tags</em> qui sont en principe figés.</p>
<p>On remarquera aussi que malgré son âge, <strong>WordPress commence à peine à proposer des solutions d&#8217;industrialisation</strong>.<br />
Les liens symboliques sont en effet très mal gérés. Tentez d&#8217;utiliser un seul répertoire source pour plusieurs blogs avec des liens symboliques et tout s&#8217;effondre.</p>
<p>La preuve en est aussi avec le <strong>manque de ressources disponibles sur le Web</strong> et traitant ce sujet. Ça m&#8217;étonnerait d&#8217;être le premier à vouloir déployer du WordPress via <acronym title="Subversion">SVN</acronym>.<br />
Les choses s&#8217;améliorent mais pour le côté <cite>code is poetry</cite>, on en est encore loin.</p>]]></content:encoded>
			<wfw:commentRss>http://case.oncle-tom.net/2008/wordpress-svn-external/feed/</wfw:commentRss>
		<slash:comments>8</slash:comments>
		</item>
		<item>
		<title>High Performance Web Sites</title>
		<link>http://case.oncle-tom.net/2008/high-performance-web-sites/</link>
		<comments>http://case.oncle-tom.net/2008/high-performance-web-sites/#comments</comments>
		<pubDate>Tue, 15 Jul 2008 05:00:15 +0000</pubDate>
		<dc:creator>Oncle Tom</dc:creator>
				<category><![CDATA[Développement Web]]></category>
		<category><![CDATA[apache]]></category>
		<category><![CDATA[bonnes pratiques]]></category>
		<category><![CDATA[critique]]></category>
		<category><![CDATA[firebug]]></category>
		<category><![CDATA[gzip]]></category>
		<category><![CDATA[livre]]></category>
		<category><![CDATA[logiciels libres]]></category>
		<category><![CDATA[mod_deflate]]></category>
		<category><![CDATA[mod_expires]]></category>
		<category><![CDATA[mod_gzip]]></category>
		<category><![CDATA[optimisation]]></category>
		<category><![CDATA[oreilly]]></category>
		<category><![CDATA[yahoo]]></category>
		<category><![CDATA[yslow]]></category>
		<guid isPermaLink="false">http://case.oncle-tom.net/?p=943</guid>
		<description><![CDATA[High Performance Web Site, sous-titré Essential Knowledge for Frontend Engineers, est ce genre de livre à lire au moins une fois à défaut de le posséder. Il résume en à peu près 120 pages 14 points d&#8217;optimisation d&#8217;un site Web. C&#8217;est d&#8217;autant plus intéressant que l&#8217;approche se base sur les mécanismes et non sur de [...]]]></description>
			<content:encoded><![CDATA[<p style="text-align: center;"><img class="size-full wp-image-944" title="High Performance Web Sites (couverture)" src="http://case.oncle-tom.net/images/2008/07/livre-high-performance-web-sites.jpg" alt="High Performance Web Sites (couverture)" width="240" height="240" /></p>
<p><a href="http://www.amazon.fr/dp/0596529309/">High Performance Web Site</a>, sous-titré <em>Essential Knowledge for Frontend Engineers</em>, est ce genre de <strong>livre à lire au moins une fois</strong> à défaut de le posséder. Il résume en à peu près 120 pages 14 points d&#8217;optimisation d&#8217;un site Web.</p>
<p>C&#8217;est d&#8217;autant plus intéressant que l&#8217;<strong>approche se base sur les mécanismes</strong> et non sur de l&#8217;optimisation de code. Ainsi dans la plupart des cas, vous n&#8217;aurez &laquo;&nbsp;que&nbsp;&raquo; du paramétrage serveur à faire.</p>
<p><span id="more-943"></span></p>
<p>Ce livre fait étrangement penser aux <a href="http://developer.yahoo.com/performance/">conseils de haute performance</a> prodigués par le <a href="http://developer.yahoo.com">Yahoo! Developer Network</a> et repris par l&#8217;extension <a href="http://getfirebug.com">Firefox pour Firebug</a>, j&#8217;ai nommé <a href="http://developer.yahoo.com/yslow/">YSlow</a>.<br />
C&#8217;est normal : ce livre est écrit par un ingénieur de Yahoo!, probablement un de ceux qui ont participé à la rédaction du guide de performances.</p>
<h3>Pourquoi acheter High Performance Web Sites ?</h3>
<p>On serait tenté de ne pas acheter le livre puisqu&#8217;une bonne partie de ses conseils sont repris sur le guide de haute performance cité plus haut.</p>
<p>Sachez toutefois que <strong>cet ouvrage va plus loin dans le détail</strong>, prend bien le temps de présenter ses tests de performance pour illustrer et de justifier l&#8217;application de leurs méthodes. La plupart des relevés de mesure sont effectués sur une dizaine de sites allant de Google à Amazon.</p>
<p>J&#8217;achèterais ce livre si j&#8217;étais :</p>
<ul>
<li>un <strong>administrateur système</strong> chargé d&#8217;héberger 1 ou plusieurs sites Web</li>
<li>un <strong>technicien/webmaster</strong> en charge d&#8217;un site à plus ou moins fort trafic</li>
<li>un <strong>développeur Web</strong> soucieux des performances de ses productions</li>
<li>toute personne avare en kilo-octets superflus</li>
<li>toute personne voulant <strong>accélérer les temps de réponse</strong> de son ou ses sites Web</li>
</ul>
<p style="text-align:center"><a href="http://case.oncle-tom.net/images/2008/07/yslow-emunova-components.png"><img class="size-medium wp-image-945 aligncenter" title="YSLow sur Emu Nova : les composants" src="http://case.oncle-tom.net/images/2008/07/yslow-emunova-components-300x81.png" alt="YSLow sur Emu Nova : les composants" width="300" height="81" /></a></p>
<h3>Les 14 points d&#8217;optimisation</h3>
<p>High Performance Web Sites axe son discours sur 14 points :</p>
<ol>
<li><a href="http://developer.yahoo.com/performance/rules.html#num_http">Limiter le nombre de requêtes <acronym title="HyperText Transfer Protocol">HTTP</acronym></a></li>
<li><a href="http://developer.yahoo.net/blog/archives/2007/04/high_performanc_1.html">Utiliser un Content Delivery Network (CDN)</a></li>
<li><a href="http://developer.yahoo.net/blog/archives/2007/05/high_performanc_2.html">Utiliser une entête Expires</a></li>
<li><a href="http://developer.yahoo.net/blog/archives/2007/07/high_performanc_3.html">Compresser les composants avec Gzip ou Deflate</a></li>
<li><a href="http://developer.yahoo.net/blog/archives/2007/07/high_performanc_4.html">Placer les feuilles de style en début de page</a></li>
<li><a href="http://developer.yahoo.net/blog/archives/2007/07/high_performanc_5.html">Placer les scripts JavaScript en bas de page</a></li>
<li><a href="http://developer.yahoo.net/blog/archives/2007/07/high_performanc_6.html">Éviter les expressions <acronym title="Cascading Style Sheets">CSS</acronym></a> (Internet Explorer)</li>
<li><a href="http://developer.yahoo.net/blog/archives/2007/07/rule_8_make_jav.html">Placer les scripts JavaScript et les feuilles de style dans des fichiers externes</a></li>
<li><a href="http://developer.yahoo.com/performance/rules.html#dns_lookups">Réduire le nombre d&#8217;appels à des <acronym title="Domain Name Server">DNS</acronym> différents</a></li>
<li><a href="http://developer.yahoo.net/blog/archives/2007/07/rule_8_make_jav.html">Minifier le JavaScript et les <acronym title="Cascading Style Sheets">CSS</acronym></a></li>
<li><a href="http://developer.yahoo.com/performance/rules.html#redirects">Éviter les redirections</a></li>
<li><a href="http://developer.yahoo.net/blog/archives/2007/07/high_performanc_10.html">Supprimer les doublons de scripts</a></li>
<li><a href="http://developer.yahoo.net/blog/archives/2007/07/high_performanc_11.html">Configurer ETags</a></li>
<li><a href="http://developer.yahoo.com/performance/rules.html#cacheajax">Permettre la mise en cache des appels Ajax</a></li>
</ol>
<p>Il prend cependant le soin de bien expliquer les <strong>mécanismes d&#8217;<acronym title="HyperText Transfer Protocol">HTTP</acronym></strong> et les intérêts à améliorer les performances <em>frontend</em>.</p>
<p>Le livre termine sur un comparatif des 14 points sur 10 sites, notation YSLow comprise, dont Amazon, Google, CNN, eBay, Wikipédia et Yahoo!.</p>
<h3>La mise en pratique</h3>
<p>J&#8217;étais déjà sensibilité à presque tous les points pour avoir lu ces fameuses 14 règles en utilisant l&#8217;<a href="http://case.oncle-tom.net/2007/12/25/bonnes-pratiques-firebug-developpement-web/">extension YSlow et Firebug</a>. Cependant après la lecture du livre j&#8217;ai eu davantage de clés et des exemples probants pour me convaincre de les mettre en œuvre.</p>
<p>On peut <strong>appliquer la majorité des points et les points pertinents en 1 heure</strong>. En effet, tout site ne peut se permettre d&#8217;utiliser un CDN pour accélérer les temps de réponse autour du globe.</p>
<p>Personnellement j&#8217;ai mis en place une <strong>compression Gzip directement au niveau d&#8217;Apache</strong> au lieu d&#8217;utiliser une compression effectuée en <acronym title="Pre-Hypertext Processing">PHP</acronym> (avec Gzip aussi). J&#8217;ai couplé cet effort avec la <strong>minification JavaScript</strong> et la <strong>désactivation des ETags</strong>.</p>
<p>J&#8217;avais déjà au préalable externalisés mes <acronym title="Cascading Style Sheets">CSS</acronym> et JavaScript, placé au bon endroit (mais seulement les appels externes au <acronym title="Domain Name Server">DNS</acronym> principal en bas de page) et sans doublon.</p>
<p>C&#8217;est bête à dire mais <strong>le résultat s&#8217;est vraiment senti avec des chargements de page incroyablement plus rapides</strong>. <em>YSlow</em> est effectivement un compagnon idéal pour la mise en application de ces éléments avec son analyse des performances et des composants.</p>
<p style="text-align: center;"><img class="size-full wp-image-946" title="YSLow sur Emu Nova : les statistiques" src="http://case.oncle-tom.net/images/2008/07/yslow-emunova-stats.png" alt="YSLow sur Emu Nova : les statistiques" width="402" height="379" /></p>
<h3>Conclusion</h3>
<p>J&#8217;ai dévoré <strong>High Performance Web Sites</strong> grâce à sa simplicité de rédaction, les nombreux exemples et surtout, les explications enrichissantes. Elles sont mises en application sur Yahoo! et certes, même si on peut se dire qu&#8217;on n&#8217;a pas de site de leur envergure, leurs conseils sont toujours bons à prendre.</p>
<p><strong>High Performance Web Sites</strong> est un concentré de bonnes pratiques, simples à mettre en œuvre. Pourquoi s&#8217;en priver ?</p>
<p>Ces optimisations ne sont évidemment pas les seules à mettre en place pour que tout fonctionne bien : il faut aussi produire du code <acronym title="HyperText Markup Language">HTML</acronym> propre, du JavaScript optimisé, du code application qui ne soit pas redondant.</p>
<p><strong>C&#8217;est un bon début et des pratiques à généraliser</strong>.</p>
]]></content:encoded>
			<wfw:commentRss>http://case.oncle-tom.net/2008/high-performance-web-sites/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>Modifier l&#8217;emplacement des données d&#8217;un serveur MySQL</title>
		<link>http://case.oncle-tom.net/2008/modifier-emplacement-donnees-serveur-mysql/</link>
		<comments>http://case.oncle-tom.net/2008/modifier-emplacement-donnees-serveur-mysql/#comments</comments>
		<pubDate>Sun, 04 May 2008 09:25:57 +0000</pubDate>
		<dc:creator>Oncle Tom</dc:creator>
				<category><![CDATA[Développement Web]]></category>
		<category><![CDATA[apparmor]]></category>
		<category><![CDATA[datadir]]></category>
		<category><![CDATA[debian]]></category>
		<category><![CDATA[linux]]></category>
		<category><![CDATA[logiciels libres]]></category>
		<category><![CDATA[MySQL]]></category>
		<category><![CDATA[mysql5]]></category>
		<category><![CDATA[optimisation]]></category>
		<category><![CDATA[ubuntu]]></category>
		<guid isPermaLink="false">http://case.oncle-tom.net/?p=908</guid>
		<description><![CDATA[L&#8217;installation par défaut d&#8217;un serveur MySQL est suffisante pour être opérationnel dans la minute qui suit. Elle ne facilite en revanche pas la maintenance en laissant le répertoire contenant vos bases de données et tables hors de portée. L&#8217;intérêt de choisir soi-même l&#8217;emplacement de ce répertoire, le datadir, est double : regrouper les données en [...]]]></description>
			<content:encoded><![CDATA[<p style="text-align:center"><img src="http://case.oncle-tom.net/images/2007/08/powered-by-mysql-167x86.png" alt="Logo MySQL" /></p>
<p>L&#8217;installation par défaut d&#8217;un serveur MySQL est suffisante pour être opérationnel dans la minute qui suit. Elle ne facilite en revanche pas la maintenance en laissant le répertoire contenant vos bases de données et tables hors de portée.</p>
<p>L&#8217;intérêt de choisir soi-même l&#8217;emplacement de ce répertoire, le <em>datadir</em>, est double :</p>
<ul>
<li><strong>regrouper les données en un endroit connu</strong> (facilite les sauvegardes)</li>
<li>utiliser le partitionnement du disque pour <strong>ne pas avoir à craindre une perte de données</strong> en cas de réinstallation du système (facilite la maintenance)</li>
</ul>
<p>Nous allons voir comment procéder à ce changement tout en adaptant les sécurités des systèmes tels que <a href="http://fedoraproject.org/wiki/SELinux">SELinux</a> et <a href="http://www.novell.com/linux/security/apparmor/">AppArmor</a>. Ces derniers empêcheront en effet le serveur de démarrer.</p>
<p><span id="more-908"></span></p>
<p><strong class="highlight">Remarque importante</strong> : j&#8217;ai publié une <a href="http://case.oncle-tom.net/2008/12/11/configuration-apache-mysql-php-symlinks/">version améliorée du déplacement des données d&#8217;un serveur MySQL</a>. Je la recommande par rapport à cet article : elle implique moins de manipulations et est plus propre.</p>
<h3>Quelques généralités avant de commencer</h3>
<p>Quitte à changer l&#8217;emplacement du <em>datadir</em>, autant le déplacer sur une partition qui ne sera pas effacé lors de la réinstallation de votre système d&#8217;exploitation, que ça soit du Linux, MacOS ou Windows.</p>
<p>Personnellement, sous Ubuntu/Debian, je crée un répertoire dans /home qui s&#8217;appelle mysql. Mon répertoire /home est bien entendu monté sur une partition différente. Si ce n&#8217;est pas le cas chez vous, pensez à <a href="http://doc.ubuntu-fr.org/installation/deplacer_home">déplacer votre /home</a>.</p>
<pre><code class="shell">sudo mkdir /home/mysql
sudo chown mysql:mysql /home/mysql</code></pre>
<p>Enfin, dernier détail à connaître : l&#8217;emplacement de vos données MySQL :</p>
<ul>
<li>sous Linux, généralement : <code>/var/lib/mysql</code></li>
<li>sous Windows, avec WAMP : <code>C:Program FilesWampmysqldata</code></li>
</ul>
<h3>Méthode 1 : modifier la configuration MySQL</h3>
<p>C&#8217;est probablement la <strong>méthode la plus simple</strong> mais elle a l&#8217;inconvénient d&#8217;avoir à modifier un fichier de configuration. Il faut donc modifier la propriété <em>datadir</em> de votre <a href="http://dev.mysql.com/doc/refman/5.1/en/option-files.html">fichier de configuration MySQL</a> :</p>
<ul>
<li>sous Linux, généralement : <code>/etc/mysql/my.cnf</code></li>
<li>sous Windows, avec WAMP : <code>C:Program FilesWampmysqlconfmy.ini</code></li>
</ul>
<p>Dans ce fichier se trouve une section consacrée à la configuration générale du serveur mysql (<em>mysqld</em> pour <em>mysql daemon</em>) :</p>
<pre><code class="text">[mysqld]
user            = mysql
port            = 3306
basedir         = /usr
<strong>datadir</strong>         = <strong>/var/lib/mysql</strong>
tmpdir          = /tmp</code></pre>
<p>J&#8217;ai mis en gras la ligne qui nous intéresse, à savoir le <em>datadir</em>.<br />
Quelle valeur mettre ? Celle de l&#8217;emplacement souhaité pour vos données. Dans mon cas ça aurait été /home/mysql :</p>
<pre><code class="text"><strong>datadir</strong>         = <strong>/home/mysql</strong></code></pre>
<p>Vous vous assurerez d&#8217;avoir bien stoppé le service MySQL, d&#8217;avoir copié/collé vos données de l&#8217;ancien emplacement vers le nouveau et enfin de redémarrer MySQL. C&#8217;est seulement en cas de réussite que vous pourrez supprimer l&#8217;ancien répertoire <img src='http://case.oncle-tom.net/wp-includes/images/smilies/icon_wink.gif' alt=';-)' class='wp-smiley' /> </p>
<pre><code class="shell">sudo -s
/etc/init.d/mysql stop
cp -pr /var/lib/mysql/* /home/mysql
/etc/init.d/mysql start</code></pre>
<h3>Méthode 2 : utilisation d&#8217;un lien symbolique</h3>
<p>La <a href="http://dev.mysql.com/doc/refman/5.1/en/symbolic-links.html">documentation de MySQL explique l&#8217;utilisation des liens symboliques</a> pour tout, une base de données précises voire même les tables. Ceci dit nous allons voir l&#8217;exemple global : on déplace tout.</p>
<p>Concrètement cette méthode consiste à :</p>
<ol>
<li>stopper le service MySQL</li>
<li>déplacer le répertoire de données (au cas où)</li>
<li>créer le lien symbolique</li>
<li>copier les données dans le nouvel emplacement</li>
<li>relancer le service MySQL</li>
</ol>
<p>Concrètement, ça se traduit comme ceci :</p>
<pre><code class="shell">sudo -s
mv /var/lib/mysql /var/lib/mysql-old
ln -s /home/mysql /var/lib/mysql
cp -pr /var/lib/mysql-old/* /home/mysql
/etc/init.d/mysqld start</code></pre>
<p>Là encore, supprimez la copie de vos données (répertoire mysql-old) seulement en cas de succès. Ça facilite les retours en arrière en cas de pépin.</p>
<h3>Cas particulier : systèmes employant AppArmor ou SELinux</h3>
<p>Il y a cependant un hic possible si vous utilisez une distribution Fedora ou Ubuntu, surtout depuis sa version <a href="http://doc.ubuntu-fr.org/hardy">Hardy Heron (8.04)</a>. Celle-ci intègre une sécurité pour éviter à certains services critiques d&#8217;être altérés par une manipulation extérieure &#8230; comme la notre.</p>
<p>Il faut savoir que les 2 méthodes du haut échoueront si vous rentrez dans ce cas de figure : le <strong>service MySQL ne démarre pas</strong>.<br />
Pas de panique, il y a juste un fichier à modifier : <code>/etc/apparmor.d/usr.sbin.mysqld</code>. Il y a un passage ressemblant à ceci, <em>dans le cas d&#8217;AppArmor et Ubuntu</em> :</p>
<pre><code class="text">/etc/mysql/*.pem r,
/etc/mysql/conf.d/ r,
/etc/mysql/conf.d/* r,
/etc/mysql/my.cnf r,
/usr/sbin/mysqld mr,
/usr/share/mysql/** r,
<strong>/var/lib/mysql/</strong> r,
<strong>/var/lib/mysql/**</strong> rwk,
/var/log/mysql/ r,
/var/log/mysql/* rw,
/var/run/mysqld/mysqld.pid w,
/var/run/mysqld/mysqld.sock w,</code></pre>
<p>Vous voyez le loup venir. Il suffit de remplacer les occurences de /var/lib/mysql par le chemin de votre nouvel emplacement, /home/mysql dans notre cas :</p>
<pre><code class="text"><strong>/home/mysql/</strong> r,
<strong>/home/mysql/**</strong> rwk,</code></pre>
<p>La raison de cette modification est presque simple : AppArmor ne suit pas les liens symboliques. <strong>Il considère que /var/lib/mysql est différent de /home/mysql</strong> et que ce dernier ne concerne pas le service mysqld.<br />
<strong>Notre modification évite ce blocage</strong> et permet du même coup au serveur MySQL de démarrer ; les échecs étant dus au fait que le serveur ne trouvait pas de base à charger (dont la sienne, <em>mysql</em>).</p>
<p>Pour terminer, on peut relancer les 2 services, apparmor et mysqld :</p>
<pre><code class="shell">sudo /etc/init.d/apparmor restart
sudo /etc/init.d/mysqld restart</code></pre>
<h3>Conclusion</h3>
<p>Nous avons vu 2 méthodes pour rendre sa <strong>gestion des bases de données plus souple et plus sure</strong>. En cas de défaillance système &#8211; ça arrive même aux meilleurs &#8211; il faut pouvoir le réinstaller sans craindre de perdre des données vitales. Et les bases de données le sont.</p>
<p>On peut aussi constater que les <strong>nouveaux services de protection peuvent compliquer la vie</strong> si on ne les sait pas actifs et si on ne comprend pas leur fonctionnement. J&#8217;ai passé plusieurs heures à comprendre pourquoi le serveur MySQL ne se relançait pas alors qu&#8217;il me semblait avoir effectué la même manipulation sur les précédentes versions d&#8217;Ubuntu.</p>
<p>N&#8217;hésitez pas à partager votre méthode ou apporter vos suggestions sur votre gestion des <em>datadir</em>.</p>
]]></content:encoded>
			<wfw:commentRss>http://case.oncle-tom.net/2008/modifier-emplacement-donnees-serveur-mysql/feed/</wfw:commentRss>
		<slash:comments>36</slash:comments>
		</item>
		<item>
		<title>Bonnes pratiques de codage CSS</title>
		<link>http://case.oncle-tom.net/2008/bonnes-pratiques-codage-css/</link>
		<comments>http://case.oncle-tom.net/2008/bonnes-pratiques-codage-css/#comments</comments>
		<pubDate>Tue, 26 Feb 2008 06:00:18 +0000</pubDate>
		<dc:creator>Oncle Tom</dc:creator>
				<category><![CDATA[Développement Web]]></category>
		<category><![CDATA[Standards du Web]]></category>
		<category><![CDATA[aptana]]></category>
		<category><![CDATA[bonnes pratiques]]></category>
		<category><![CDATA[code]]></category>
		<category><![CDATA[coding standards]]></category>
		<category><![CDATA[compresseur]]></category>
		<category><![CDATA[conventions]]></category>
		<category><![CDATA[css]]></category>
		<category><![CDATA[CSSDoc]]></category>
		<category><![CDATA[eclipse]]></category>
		<category><![CDATA[feuille de style]]></category>
		<category><![CDATA[indentation]]></category>
		<category><![CDATA[logiciels libres]]></category>
		<category><![CDATA[optimisation]]></category>
		<guid isPermaLink="false">http://case.oncle-tom.net/2008/02/26/bonnes-pratiques-codage-css/</guid>
		<description><![CDATA[J&#8217;y songeais mais l&#8217;article «De l&#8217;ordre, que diable !» m&#8217;a incité à m&#8217;y atteler plus tôt que prévu. Il n&#8217;y a en effet pas de méthode universelle pour programmer les CSS mais après plusieurs années d&#8217;expérience, j&#8217;ai affiné ma réflexion que je vous livre aujourd&#8217;hui. Où l&#8217;on parlera de présentation en 1 ligne, de CSSDoc [...]]]></description>
			<content:encoded><![CDATA[<p style="text-align:center"><img src="http://case.oncle-tom.net/images/2008/02/css-url-import.png" alt="CSS URL @import" /></p>
<p>J&#8217;y songeais mais l&#8217;article «<a href="http://blog.alsacreations.com/2008/02/21/411-de-lordre-que-diable-">De l&#8217;ordre, que diable !</a>» m&#8217;a incité à m&#8217;y atteler plus tôt que prévu.<br />
Il n&#8217;y a en effet <strong>pas de méthode universelle pour programmer</strong> les <acronym title="Cascading Style Sheets"><acronym title="Cascading Style Sheets">CSS</acronym></acronym> mais après plusieurs années d&#8217;expérience, j&#8217;ai affiné ma réflexion que je vous livre aujourd&#8217;hui.</p>
<p>Où l&#8217;on parlera de présentation en 1 ligne, de CSSDoc mais aussi de <em>folding</em> et d&#8217;indentation. <strong>En clair, tout plein de bonnes pratiques</strong> de développement en <acronym title="Cascading Style Sheets">CSS</acronym> qui vous feront gagner du temps, vous éviterons de la sueur et sentent bon le travail de qualité.<br />
<span id="more-878"></span></p>
<h3>Halte là et retour à la ligne !</h3>
<p>J&#8217;ai utilisé pendant un moment la technique dite du <a href="http://orderedlist.com/articles/single-line-css">single line <acronym title="Cascading Style Sheets">CSS</acronym></a> ; à savoir 1 ligne par déclaration.<br />
Je n&#8217;hésiterai pas une seconde à dire que je déconseille fortement cette écriture pour les raisons suivantes :</p>
<ul>
<li>si on souhaite gagner de la place, il y a des compresseurs (je recommande <a href="http://developer.yahoo.com/yui/compressor/">YUI Compressor</a>): pas la peine de réaliser ce travail nous-même ;</li>
<li>l&#8217;ajout de commentaires n&#8217;en est que plus compliqué : on a tous besoin de commenter certains passages cruciaux, notamment les <em>hacks</em> et autres <em>fix</em> ;</li>
<li>c&#8217;est tout bonnement illisible dès qu&#8217;on s&#8217;y replonge quelques semaines plus tard : imaginez pour quelqu&#8217;un qui n&#8217;a pas écrit le code !</li>
</ul>
<p>Les arguments avancés pour cette technique ne tiennent pas la route : <strong>on recherche avant tout la qualité et la facilité de relecture</strong>. Les quelques kilo-octets à perdre se feront par le biais de programmes. Ça ne doit certainement pas entraver le développement.</p>
<h3>L&#8217;auto-documentation avec la syntaxe CSSDoc</h3>
<p>Les habitués de Java connaissent <a href="http://java.sun.com/j2se/javadoc/">JavaDoc</a>.<br />
Les habitués de <acronym title="Pre-Hypertext Processing">PHP</acronym> connaissent <a href="http://www.phpdoc.org/">PHPDoc</a>.<br />
Les habitués de JavaScript connaissent <a href="http://code.google.com/p/jsdoc-toolkit/">JsDoc Toolkit</a> (dérivé de <a href="http://jsdoc.sourceforge.net/">JsDoc</a>).</p>
<p>Il était donc tout naturel que cette syntaxe de commentaires et d&#8217;auto-documentation soit utilisable en <acronym title="Cascading Style Sheets">CSS</acronym> avec <a href="http://cssdoc.net">CSSDoc</a>. Il n&#8217;y a pas d&#8217;inconvénient à l&#8217;utiliser, au contraire, que des avantages :</p>
<ul>
<li>la syntaxe permet d&#8217;<strong>harmoniser les commentaires</strong> sur les projets impliquant plusieurs développeurs ;</li>
<li>sa syntaxe <strong>facilite la relecture</strong> puisqu&#8217;elle est connue et employée dans de nombreux langages, autres que les <acronym title="Cascading Style Sheets">CSS</acronym> ;</li>
<li>l&#8217;<strong>auto-documentation du code</strong> c&#8217;est faciliter la génération d&#8217;une documentation externe en automatisant le processus ;</li>
<li>documenter en même temps que l&#8217;on écrit c&#8217;est <strong>comprendre ce que l&#8217;on fait</strong> et gagner du temps en évitant une écriture <em>a posteriori</em> ;</li>
</ul>
<p><a href="http://cssdoc.net/wiki/CssdocDraft">La syntaxe CSSDoc est documentée</a>,  aisément reconnaissable et est supportée par les meilleurs éditeurs <acronym title="Cascading Style Sheets">CSS</acronym>, dont <a href="http://www.aptana.com/">Aptana IDE</a> :</p>
<pre><code class="css">/**
 * @author Oncle Tom
 * @lastmodified Fev, 26 2008
 * @media print, screen
 * @site http://www.oncle-tom.net/
 */
/**
 * Redéfinition des balises <acronym title="HyperText Markup Language">HTML</acronym>
 *
 * @section html
 * @todo utiliser un reset.css conforme
 */
html,
*{
  margin: 0;
  padding: 0;
}</code></pre>
<h3>L&#8217;organisation hiérarchique</h3>
<p>J&#8217;ai pour habitude de travailler avec une seule feuille de style par media. Comme je travaille sur des <strong>hiérarchies thématiques</strong>, leur découpage en plusieurs fichiers ne consiste qu&#8217;à du copier/coller. On peut ainsi facilement passer d&#8217;une mono-feuille à du multi-feuilles. Je ne suis pas un fervent utilisateur de ces dernières car un code bien lisible sur une seule page n&#8217;est pas problématique.<br />
Je ne l&#8217;emploie que pour faciliter la réutilisation des <acronym title="Cascading Style Sheets">CSS</acronym> sur plusieurs projets partageant la même base graphique.</p>
<p>Concrètement, je vais d&#8217;abord organiser ma feuille pour redéfinir les éléments <acronym title="HyperText Markup Language">HTML</acronym> génériques puis créer autant de sections qu&#8217;il n&#8217;y en a sur ma page (navigation, contenu, navigation de contenu, contenus annexes etc.).<br />
Plus je m&#8217;avancerai dans la profondeur du balisage <acronym title="HyperText Markup Language">HTML</acronym> et plus j&#8217;indenterai mon code. Cette indentation fait penser à celle utilisée par le <a href="http://www.python.org/">langage Python</a>.</p>
<p>On pourrait résumer cette convention à ceci :</p>
<ul>
<li><strong>pas de tabulation</strong>, que des espaces pour avoir le même affichage peu importe les éditeurs</li>
<li>2 espaces par tabulation</li>
<li><strong>attributs classés par ordre alphabétique</strong> (même logique pour tout le monde)</li>
<li>une ligne d&#8217;espace entre les définitions ; pas de ligne entre les définitions proches/liées</li>
</ul>
<p>C&#8217;est simple et voici un exemple de résultat :</p>
<pre><code class="css">/**
 * Redéfinition du <acronym title="HyperText Markup Language">HTML</acronym>
 */
a{
  text-decoration: underline;
}
  a img{
    border: none;
  }
p{
  line-height: 1.5em;
}
  p img{
    margin: 1.5em
  }
  p img.top{
    margin-top: 0;
  }
/**
 * Contenu
 */
#main-content{
  clear: both;
  width: 100%;
}
  /**
   * Articles
   */
  #articles{
    margin-bottom: 2em;
  }
    #articles h2{
      font-size: 1.5em;
      font-weight: bold;
    }</code></pre>
<p>Les mieux organisés d&#8217;entre vous ajouteront un <strong>tri par fréquence d&#8217;utilisation</strong> afin d&#8217;optimiser les va-et-vient : on met en haut ce qu&#8217;on est susceptible de modifier le plus souvent, en bas ce à quoi on touchera rarement. Je ne vais pas jusque là mais ça reste envisageable, pertinent et surtout adapté aux plus chevronnés de l&#8217;optimisation.</p>
<h3>Autres conseils et astuces</h3>
<h4>Utilisation de raccourcis</h4>
<p>Les <em>aficionados</em> de l&#8217;optimisation et du gain de temps apprécieront cette méthode, s&#8217;ils ne l&#8217;utilisent pas déjà. J&#8217;ai pour habitude de placer des raccourcis dans mes sections pour <strong>faciliter l&#8217;utilisation d&#8217;une recherche via le raccourci clavier</strong> <kbd>Control+F</kbd>.<br />
Je préfixe chaque raccourci d&#8217;un symbole <kbd>=</kbd> :</p>
<pre><code class="css">/**
 * Liens d'évitement
 * =evitement
 */</code></pre>
<p>Je trouve cette méthode très pratique pour atteindre des portions de code. On évite ainsi un appel à la touche <kbd>Alt Gr</kbd> pour appuyer sur le # d&#8217;un ID (pour peu que l&#8217;on n&#8217;ait que des ID en tant que sections). On évite aussi les collisions de nom ou les recherches infructueuses pour cause de changement de nom de classes ou d&#8217;ID.</p>
<h4>De la sémantique, que diable !</h4>
<p>Je suis particulièrement attaché à cette bonne pratique d&#8217;autant plus qu&#8217;elle ne tombe pas forcément sous le sens de tout le monde : <strong>nommez vos ID et classes en fonction de leur <em>signification</em>, pas de leur <em>représentation</em></strong>. C&#8217;est la suite logique de la séparation fond et forme du <acronym title="HyperText Markup Language">HTML</acronym> et des <acronym title="Cascading Style Sheets">CSS</acronym>.</p>
<p><strong>Mauvaise sémantique</strong> :</p>
<pre><code class="css">.rouge{
  color: red;
}
#sidebar{
  /* ... */
}
#top-links{
  /* ... */
}</code></pre>
<p><strong>Bonne/meilleure sémantique</strong> :</p>
<pre><code class="css">.important{
  color: red;
}
#alternate-navigation{
  /* ... */
}
#main-links{
  /* ... */
}</code></pre>
<p><code>#sidebar</code> pourra être renommé différemment selon son contenu, selon que l&#8217;encart contienne des éléments de navigation supplémentaires, des informations utilisateur (<code>#user-content</code>) ou encore des widgets (<code>#widgets</code>).<br />
En conservant votre <acronym title="HyperText Markup Language">HTML</acronym> intact et en jouant sur les <acronym title="Cascading Style Sheets">CSS</acronym>, la <code>#sidebar</code> peut en effet se retrouver tout en bas, à l&#8217;horizontale. Aurez-vous toujours envie de l&#8217;appeler pareil ? Pas forcément. <strong>Un bon nommage est un nommage qui se conserve peu importe l&#8217;aspect de la présentation</strong>.</p>
<h4>Du choix de la langue</h4>
<p>Cette bonne pratique s&#8217;applique aussi bien aux <acronym title="Cascading Style Sheets">CSS</acronym> qu&#8217;à d&#8217;autres langages. Il faut partir du principe qu&#8217;<strong>il ne faut pas mélanger les langues dans le code</strong>, tant dans les commentaires que dans le nommage des classes et ID. <strong>Choisissez-une langue et restez avec</strong>.<br />
Certaines contraintes peuvent faciliter le choix de la langue : le travail avec une équipe internationale ou la redistribution du code. Dans ce cas l&#8217;anglais sera à 99% votre langue de prédilection.</p>
<p>Il n&#8217;y a pas de choix idéal : certains préféreront le tout français, d&#8217;autres le tout anglais. L&#8217;essentiel est que ce <strong>choix soit motivé par des arguments objectifs, pas une préférence personnelle</strong>.</p>
<h4>Recours au <em>folding</em></h4>
<p>J&#8217;en parle succintement mais le <em>folding</em> consiste à utiliser votre éditeur <acronym title="Cascading Style Sheets">CSS</acronym> pour <strong>masquer une partie de code</strong>. Eclipse propose par exemple de masquer toutes les définitions et tous les commentaires : leur contenu n&#8217;est révélé qu&#8217;en le dépliant.</p>
<p>Je ne suis pas un fervent utilisateur de cette pratique bien que je respecte son utilisation. Je trouve qu&#8217;en utilisation les précédentes astuces (hiérarchie + recherche) on s&#8217;y retrouve très bien.</p>
<p style="text-align:center"><img src="http://case.oncle-tom.net/images/2008/02/css-folding.png" alt="Folding en CSS" /></p>
<h3>Conclusion</h3>
<p>Ma méthodologie n&#8217;est pas parfaite, peut être perfectible et ne conviendra pas à tout le monde, par goûts ou par habitudes. Ces dernières sont cependant à combattre pour améliorer son travail. <strong>Quoi de mieux qu&#8217;un code propre, bien documenté et où l&#8217;on trouvera facilement ce que l&#8217;on cherche</strong> ?</p>
<p>C&#8217;est ce qui importe. <strong>Il y a autant de façons de coder qu&#8217;il n&#8217;y a de développeurs</strong>. Le tout est d&#8217;être ouvert aux améliorations possibles, aux méthodes existantes et à l&#8217;intérêt de leurs utilisations. Je trouverai peut-être cet article obsolète dans 1 an mais il aura été un point de passage.</p>
<p>J&#8217;espère qu&#8217;il le sera au moins en partie pour vous, développeur en herbe ou féru des pseudo-classes <img src='http://case.oncle-tom.net/wp-includes/images/smilies/icon_wink.gif' alt=';-)' class='wp-smiley' /> </p>
]]></content:encoded>
			<wfw:commentRss>http://case.oncle-tom.net/2008/bonnes-pratiques-codage-css/feed/</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
		<item>
		<title>L&#8217;écrit Web : traitement de l&#8217;information sur Internet</title>
		<link>http://case.oncle-tom.net/2008/ecrit-web-traitement-information-sur-internet/</link>
		<comments>http://case.oncle-tom.net/2008/ecrit-web-traitement-information-sur-internet/#comments</comments>
		<pubDate>Tue, 08 Jan 2008 06:00:31 +0000</pubDate>
		<dc:creator>Oncle Tom</dc:creator>
				<category><![CDATA[Personnel]]></category>
		<category><![CDATA[bonnes pratiques]]></category>
		<category><![CDATA[html]]></category>
		<category><![CDATA[livres]]></category>
		<category><![CDATA[optimisation]]></category>
		<category><![CDATA[web]]></category>
		<category><![CDATA[xhtml]]></category>
		<guid isPermaLink="false">http://case.oncle-tom.net/2008/01/08/ecrit-web-traitement-information-sur-internet/</guid>
		<description><![CDATA[Je rédige sur ce blog depuis bientôt 3 ans, depuis plus de 5 ans sur Emu Nova et depuis quasiment 10 ans si on remonte à mon ancien site perso et mon site consacré à Star Wars. Ah l&#8217;époque des .fr.st . Ce bagage m&#8217;a permis d&#8217;affiner mon écriture sur le Web mais je cherchais [...]]]></description>
			<content:encoded><![CDATA[<p style="text-align:center"><img src='http://case.oncle-tom.net/images/2008/01/ecrit-web.jpg' alt='Couverture de l’écrit Web' /></p>
<p>Je rédige sur ce blog depuis bientôt 3 ans, depuis plus de 5 ans sur <a href="http://www.emunova.net/">Emu Nova</a> et depuis quasiment 10 ans si on remonte à mon <a href="http://web.archive.org/web/20010223234921/http://www.ifrance.com/the-jedi/" rel="nofollow">ancien site perso</a> et <a href="http://the-jedi.ifrance.com/starwars/" rel="nofollow">mon site consacré à Star Wars</a>. Ah l&#8217;époque des <a href="http://www.ulimit.com/">.fr.st</a> <img src='http://case.oncle-tom.net/wp-includes/images/smilies/icon_wink.gif' alt=';-)' class='wp-smiley' />  .<br />
Ce bagage m&#8217;a permis d&#8217;affiner mon écriture sur le Web mais je cherchais à l&#8217;améliorer. C&#8217;est précisément à ce moment qu&#8217;<a href="http://affordance.typepad.com/mon_weblog/2007/08/ronez-est-bon.html">Olivier Ertzscheid offre la dernière préface issue de sa plume</a> et qu&#8217;<a href="http://blog.temesis.com/2007/10/08/261-ecrit-web">Élie Sloïm recommande un obscur livre</a> : <strong><a href="http://ronez.typepad.com/lecritweb/">l&#8217;écrit Web</a></strong>.</p>
<p>J&#8217;apprécie ces hommes, entre autre, pour leur bonne parole donc il n&#8217;en fallait pas davantage pour me procurer cet ouvrage.<br />
<span id="more-830"></span></p>
<h3>Pourquoi le lire ?</h3>
<p><strong>L&#8217;écrit Web se destine à toute personne désireuse de perfectionner son écriture</strong>. Et plus particulièrement l&#8217;écriture sur le Web.<br />
Combien d&#8217;entre vous ou parmi vos connaissances n&#8217;ont jamais dis que <q>lire sur un écran c&#8217;est fatiguant, les livre c&#8217;est mieux</q> ? Une bonne majorité. Et c&#8217;est bien parce qu&#8217;on ne lit pas de la même manière un livre qu&#8217;un écran d&#8217;ordinateur qu&#8217;on doit impérativement adapter son écriture à un lectorat volatile, contraint par la technologie et difficile à capter.</p>
<p>L&#8217;écrit Web dispense ses bonnes pratiques pour mieux écrire sur le Web en suivant 6 grands axes :</p>
<ol>
<li><strong>organiser l&#8217;information</strong></li>
<li><strong>structurer son texte</strong></li>
<li><strong>adapter son style</strong></li>
<li><strong>soigner les microcontenus</strong></li>
<li>penser indexation et référencement</li>
<li>bloguer</li>
</ol>
<p>J&#8217;ai volontairement grassé les 4 axes les plus intéressants. Ils m&#8217;ont permis de conceptualiser beaucoup de pratiques que j&#8217;appliquais inconsciemment &#8230; et d&#8217;en découvrir d&#8217;autres.<br />
L&#8217;idée générale n&#8217;est pas d&#8217;apprendre à écrire mais de <em>réapprendre</em>. Les raisons sont simples :</p>
<ul>
<li>on lit moins vite sur un écran d&#8217;ordinateur ;</li>
<li>on lit en profondeur et non à plat, grâce aux liens hypertextes (qui ralentissent aussi la lecture).</li>
</ul>
<h3>Organiser et structurer</h3>
<p>En partant de ces principes là, il faut donc songer à réorganiser ses textes voire ses sites Web d&#8217;une part pour faciliter la vie de ses lecteurs (occasionnels ou pas) mais aussi pour capter plus facilement leur attention. Que faites-vous devant un gros pavé de texte ou un site mal organisé ? Vous zappez. Alors pensez qu&#8217;on fait de même avec ce que vous écrivez <img src='http://case.oncle-tom.net/wp-includes/images/smilies/icon_wink.gif' alt=';-)' class='wp-smiley' />  .</p>
<p>En fin de compte tout contenu, que ce soit une page ou du texte, s&#8217;organise en suivant le principe de la <strong>pyramide inversée</strong> à l&#8217;image du <a href="http://www.prweaver.fr/blog/images/google/golden-triangle.jpg">triangle d&#8217;or d&#8217;une page Web</a> si cher aux référenceurs. On commence par l&#8217;essentiel pour terminer sur du détail. Ça vaut également pour l&#8217;ordre des listes à afficher (chronologiques, géographiques, thématiques etc.).</p>
<p>Contrairement au papier où la lecture se fait à plat, on peut et on doit se servir de la navigation hypertexte pour désengorger les pavés de textes susceptibles de décourager la lecture. C&#8217;est ce qu&#8217;entend l&#8217;auteur par <em>navigation en profondeur</em>.<br />
Plutôt que d&#8217;accueillir un visiteur avec beaucoup de texte, mieux vaut donc plusieurs boites aux titres informatifs présentant le contenu en une poignée de lignes.</p>
<p>Autre conseil judicieux, respecter les 5W (ou <acronym title="">QQOQP</acronym> en français) :</p>
<ol>
<li><strong>Q</strong>ui ? (<em><strong>W</strong>ho</em>)</li>
<li><strong>Q</strong>uand ? (<em><strong>W</strong>hen</em>)</li>
<li><strong>O</strong>ù ? (<em><strong>W</strong>here</em>)</li>
<li><strong>Q</strong>uoi ? (<em><strong>W</strong>hat</em>)</li>
<li><strong>P</strong>ourquoi ? (<em><strong>W</strong>hy</em>)</li>
</ol>
<p>En y songeant lors de la rédaction et en respectant l&#8217;ordre, on se retrouve à construire des <strong>phrases informatives, bien structurées et plaisantes à lire</strong>. Cumulez avec la pyramide inversée et c&#8217;est le gros lot : votre lecteur sait tout et tout de suite.</p>
<h3>Comment mieux écrire pour le Web</h3>
<p>Maintenant que l&#8217;on connaît l&#8217;ordre de rédaction, écrivons mieux. Écrivons court en suivant les principes <q>1 idée par phrase</q> et <q>sujet, verbe, complément</q>. La lecture n&#8217;en est que fluidifiée. Si en plus il n&#8217;y a pas de fautes d&#8217;orthographe et que le style reste naturel, alors on touche presque au but.</p>
<p>Une des particularités du Web c&#8217;est la republication du contenu. On peut écrire un article pour un site mais le retrouver affiché sur d&#8217;autres sites, sur son téléphone portable, un agrégateur voire sur le même site mais sans son contenu (dans une liste par exemple).<br />
Cette particularité est une bonne raison pour <strong>donner des titres explicites</strong>. Ils pourront ainsi être compris déconnecté de leur contexte. <em>L&#8217;écrit Web</em> propose des exemples clairs et compréhensibles vous aideront à mieux en comprendre les subtilités.</p>
<p><strong>La construction des liens hypertexte</strong> était indispensable et mérite vraiment d&#8217;être lue par toute personne peu familière du référencement. Au-delà de cette pratique, ce sont tout simplement la compréhension et l&#8217;accessibilité qui sont en jeu. Pas de liens sur des <q>cliquez ici</q>, <q>ici</q> ou <q>là</q>. Je rajouterai même qu&#8217;il ne faut pas de liens ayant le même libellé pointant vers des <acronym title="Uniform Resource Locator">URL</acronym> différentes.<br />
Tout comme <a href="http://fr.opquast.com/bonnes-pratiques/fiche/167">le libellé du lien décrit le contenu vers lequel il pointe</a>, il vaut mieux englober plusieurs mots (plus facile à cliquer) et qu&#8217;ils soient soulignés surtout ! Combien de chartes graphiques je reçois sans aucun lien soulignés ; j&#8217;outrepasse systématiquement cette mauvaise pratique du graphiste, dans le contenu en tous cas.</p>
<h3>Conclusion</h3>
<p><strong>J&#8217;ai énormément apprécié et appris de ce livre</strong>, surtout les parties structurelles et organisationnelles. La pyramide inversée et les bonnes pratiques de rédaction sont des gros &laquo;&nbsp;plus&nbsp;&raquo; que j&#8217;ai rarement retrouvé ailleurs &#8230; ou tout du moins, pas concentré en si peu de pages.<br />
Il se lit très bien et rapidement. J&#8217;ai prévu de l&#8217;offrir à quelques collaborateurs rédacteurs qui seront susceptibles d&#8217;en tirer des leçons et ainsi améliorer leur qualité rédactionnelle. Un bon investissement.</p>
<p>J&#8217;ai en revanche moins appris (voire rien du tout) sur les 2 derniers chapitres concernant le référencement et les blogs. Étant donné la quantité d&#8217;informations à traiter sur ces sujets, le contenu du livre était forcément un peu léger mais pas dénué d&#8217;intérêt pour les néophytes.<br />
Ces parties étaient néanmoins plus techniques et à mon avis plus difficiles à comprendre pour des personnes survolant l&#8217;informatique.</p>
<p>Si vous ne saviez pas quoi faire de vos étrennes, que vous rédiger pour le Web et que le marketing vous intéresse, <strong>il y aura sûrement de bonnes idées à prendre</strong> <img src='http://case.oncle-tom.net/wp-includes/images/smilies/icon_wink.gif' alt=';-)' class='wp-smiley' /> </p>
<div style="text-align:center"><iframe src="http://rcm-fr.amazon.fr/e/cm?t=oncletom-21&#038;o=8&#038;p=8&#038;l=as1&#038;asins=2353070051&#038;fc1=000000&#038;IS2=1&#038;lt1=_blank&#038;lc1=0000FF&#038;bc1=000000&#038;bg1=FFFFFF&#038;f=ifr" style="width:120px;height:240px;" scrolling="no" marginwidth="0" marginheight="0" frameborder="0"></iframe></div>]]></content:encoded>
			<wfw:commentRss>http://case.oncle-tom.net/2008/ecrit-web-traitement-information-sur-internet/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>Firebug : bonnes pratiques pour le développement Web</title>
		<link>http://case.oncle-tom.net/2007/bonnes-pratiques-firebug-developpement-web/</link>
		<comments>http://case.oncle-tom.net/2007/bonnes-pratiques-firebug-developpement-web/#comments</comments>
		<pubDate>Tue, 25 Dec 2007 07:00:44 +0000</pubDate>
		<dc:creator>Oncle Tom</dc:creator>
				<category><![CDATA[Développement Web]]></category>
		<category><![CDATA[Standards du Web]]></category>
		<category><![CDATA[css]]></category>
		<category><![CDATA[dom]]></category>
		<category><![CDATA[firebug]]></category>
		<category><![CDATA[firefox]]></category>
		<category><![CDATA[logiciels libres]]></category>
		<category><![CDATA[optimisation]]></category>
		<category><![CDATA[performances]]></category>
		<category><![CDATA[yslow]]></category>
		<guid isPermaLink="false">http://case.oncle-tom.net/2007/12/25/bonnes-pratiques-firebug-developpement-web/</guid>
		<description><![CDATA[Firebug fait partie de mes extensions préférées depuis un bon moment. Je l&#8217;estime aujourd&#8217;hui même plus importante que l&#8217;extension Web Developer, c&#8217;est dire. J&#8217;ai pourtant constaté que la plupart de ses utilisateurs la sous-exploitait en se limitant à la console pour consulter les erreurs et éventuellement à l&#8217;inspecteur HTML pour remonter rapidement dans l&#8217;arborescence des [...]]]></description>
			<content:encoded><![CDATA[<p style="text-align:center"><img src="http://case.oncle-tom.net/images/2007/12/firebug-logo.gif" alt="Logo Firebug" /></p>
<p><a href="http://case.oncle-tom.net/2007/08/07/facebook-rock-your-firefox/">Firebug fait partie de mes extensions préférées</a> depuis un bon moment. Je l&#8217;estime aujourd&#8217;hui même plus importante que l&#8217;extension <a href="https://addons.mozilla.org/fr/firefox/addon/60">Web Developer</a>, c&#8217;est dire.</p>
<p>J&#8217;ai pourtant constaté que la plupart de ses utilisateurs la sous-exploitait en se limitant à la console pour consulter les erreurs et éventuellement à l&#8217;inspecteur <acronym title="HyperText Markup Language">HTML</acronym> pour remonter rapidement dans l&#8217;arborescence des balises en 1 clic. C&#8217;est bien mais pas assez.<br />
Firebug est tout simplement énorme ! Suffisamment énorme pour <strong>gagner un temps incroyable</strong> dans le développement d&#8217;applications JavaScript et pour <strong>mieux comprendre les incohérences</strong> des <acronym title="Cascading Style Sheets">CSS</acronym> dans une page, entre autre.</p>
<p>Je vous offre aujourd&#8217;hui mon cadeau de Noël pour gagner en productivité et maîtriser cet outil ô combien indispensable.<br />
<span id="more-819"></span><br />
Le plus amusant dans l&#8217;histoire c&#8217;est que le site officiel de Firebug dévoile (succinctement certes) tous les petits <em>plus</em> qui simplifient la vie. Je vais m&#8217;atteler à les éplucher en fonction des domaines d&#8217;utilisation :</p>
<ol>
<li><a href="#firebug-html">pour le <acronym title="HyperText Markup Language">HTML</acronym> et les <acronym title="Cascading Style Sheets">CSS</acronym></a></li>
<li><a href="#firebug-javascript">pour le JavaScript</a></li>
<li><a href="#firebug-performances">pour gagner en performances</a></li>
</ol>
<h3 id="firebug-html">Firebug pour le <acronym title="HyperText Markup Language">HTML</acronym></h3>
<h4>L&#8217;inspection <acronym title="HyperText Markup Language">HTML</acronym></h4>
<p style="text-align:center"><img src="http://case.oncle-tom.net/images/2007/12/firebug-html-inspector.png" alt="Inspecteur HTML Firebug" /></p>
<p>J&#8217;apprécie l&#8217;inspection <acronym title="HyperText Markup Language">HTML</acronym> car elle me permet de retrouver simplement le code lié au visuel. Après avoir activé l&#8217;inspecteur, je survole l&#8217;élément sur lequel je veux travailler, je clique dessus et le volet Firebug se fige dessus en m&#8217;indiquant <strong>toutes ses propriétés <acronym title="Cascading Style Sheets">CSS</acronym>, le modèle de boîte et ses propriétés <acronym title="Document Object Model">DOM</acronym></strong>. On en reparle tout de suite après.<br />
L&#8217;inverse est également possible. C&#8217;est à dire qu&#8217;en survolant le code, la correspondance visuelle dans la page est établie. C&#8217;est rudement pratique pour repérer des éléments qui sortent du flux. Ça l&#8217;est d&#8217;autant plus que les différentes marges (internes, externes, bordures) sont elles aussi mises en surbrillance.</p>
<p>Le gros atout de cet inspecteur c&#8217;est également l&#8217;<strong>édition à la volée de toutes les balises</strong> ! Idéal pour tester diverses classes d&#8217;un objet ayant un impact visuel fort sur son affichage. Cet outil présente un gain de temps énorme par rapport à la modification du code dans son éditeur et un petit coup de touche <kbd>F5</kbd> dans la foulée.</p>
<p>Il faut également retenir que <strong>toute balise est sélectionnable en cliquant sur son nom</strong> (<code>div</code>, <code>h3</code> etc.). Cela a a pour effet de mettre à jour le panneau latéral de Firebug. Panneau latéral qui est également fort utile.</p>
<h4>L&#8217;inspection <acronym title="Cascading Style Sheets">CSS</acronym>, Layout et <acronym title="Document Object Model">DOM</acronym></h4>
<p>Le panneau latéral de l&#8217;inspecteur <acronym title="HyperText Markup Language">HTML</acronym> se compose de 3 onglets, tous très utiles.</p>
<h5>Inspecteur <acronym title="Cascading Style Sheets">CSS</acronym></h5>
<p style="text-align:center"><img src="http://case.oncle-tom.net/images/2007/12/firebug-css-inspector.png" alt="Inspecteur CSS Firebug" /></p>
<p>Les propriétés <acronym title="Cascading Style Sheets">CSS</acronym> affichées concernent uniquement l&#8217;objet actif et c&#8217;est ce qui en fait sa force. Ce panneau indique en effet la <strong>cascade <acronym title="Cascading Style Sheets">CSS</acronym> en cours</strong> ce qui permet de comprendre rapidement pourquoi sa feuille de style n&#8217;est pas appliquée comme il faudrait. Elle a la bonne idée de mentionner quelle feuille de style est utilisée et quelle ligne. De quoi corriger ça dans son éditeur favori rapidement.</p>
<p>Ou pas. En effet l&#8217;inspecteur <acronym title="Cascading Style Sheets">CSS</acronym> permet, tout comme l&#8217;inspecteur <acronym title="HyperText Markup Language">HTML</acronym>, de <strong>modifier les propriétés à la volée et sans fioriture</strong>. Si je précise sans fioriture c&#8217;est parce que l&#8217;éditeur à la volée de <em>Web Developer</em> rend parfois l&#8217;affichage de la page bancale en décalant des éléments. Là vous pouvez totalement compter sur l&#8217;éditeur intégré et ce n&#8217;est pas un luxe !<br />
Désactiver, supprimer, modifier ou ajouter des propriétés sont quelques-unes des actions que vous pourrez effectuer à même la page.</p>
<p>Là encore c&#8217;est une des parties où les gains de temps sont énormes. On peut en effet <strong>modifier ses <acronym title="Cascading Style Sheets">CSS</acronym> et les tester tout en observant l&#8217;impact immédiat de ses modifications</strong>.</p>
<h5>Inspecteur du modèle de boîte (<em>Layout</em>)</h5>
<p style="text-align:center"><img src="http://case.oncle-tom.net/images/2007/12/firebug-layout-inspector.png" alt="Modèle de boîte avec Firebug" /></p>
<p>Le <a href="http://www.yoyodesign.org/doc/w3c/css2/box.html">modèle de boîte <acronym title="Cascading Style Sheets">CSS</acronym></a> peut vite devenir pénible à gérer et plus particulièrement quand on visualise mal le <strong>cumul des différentes marges</strong>.<br />
Dans tous les cas c&#8217;est appréciable de pouvoir constater les marges en présence et encore, de pouvoir <strong>modifier leurs dimensions à la volée</strong>. Firebug a la bonne idée de colorer les marges intérieures (<code>padding</code>), extérieures (<code>margin</code>) et les bordures (<code>border</code>) d&#8217;une couleur différente.</p>
<p>Il a également la bonne idée d&#8217;afficher une <strong>double règle millimétrée</strong> au survol du panneau <em>layout</em>. Très pratique dans le cas de design en grilles ou nécessitant un certain rythme de visualisation.</p>
<h5>Inspecteur <acronym title="Document Object Model">DOM</acronym></h5>
<p>Ah l&#8217;inspecteur <acronym title="Document Object Model">DOM</acronym> ! S&#8217;il n&#8217;existait pas il faudrait l&#8217;inventer. Firefox proposait déjà un tel outil à la différence près qu&#8217;il était moins pratique d&#8217;utilisation.<br />
L&#8217;inspecteur <acronym title="Document Object Model">DOM</acronym> m&#8217;est moyennement utile dans le cas d&#8217;une simple inspection du code <acronym title="HyperText Markup Language">HTML</acronym> bien que ce soit toujours pratique de visualiser la présence ou pas d&#8217;objets JavaScript dans tel ou tel élément. C&#8217;est fortement appréciable pour la <a href="http://www.prototypejs.org">librairie Prototype</a> étant donné les dégâts causés par son extension du <acronym title="Document Object Model">DOM</acronym> à gogo.</p>
<h3 id="firebug-javascript">Firebug pour le JavaScript</h3>
<h4>L&#8217;inspecteur JavaScript</h4>
<p style="text-align:center"><img src="http://case.oncle-tom.net/images/2007/12/firebug-javascript-watcher.png" alt="Inspecteur JavaScript Firebug" /></p>
<p>C&#8217;est l&#8217;autre <strong>outil indispensable de Firebug</strong>. Avec lui, c&#8217;en est fini des <code>alert(mavariable);</code>. L&#8217;inspecteur <acronym title="Document Object Model">DOM</acronym> prend avec lui toute son utilité.</p>
<p>J&#8217;illustre sur l&#8217;image ci-dessus l&#8217;utilisation des points d&#8217;arrêt (<em>breakpoints</em>). Il suffit d&#8217;un clic à gauche d&#8217;un numéro de ligne pour en placer/retirer un. Concrètement quand l&#8217;exécution du JavaScript arrivera au premier point d&#8217;arrêt, elle va se stopper.<br />
Quel intérêt ? Observer. En agissant ainsi, vous avez la main sur toutes les variables connues au sein de votre code/fonction. Très utile pour <strong>connaître les paramètres passées à la fonction et détecter les erreurs</strong>. C&#8217;est pour cette raison que les <code>alert()</code> deviennent inutiles : tout est à portée de main. Vous ne pesterez plus contre un <code>undefined</code> mal placé <img src='http://case.oncle-tom.net/wp-includes/images/smilies/icon_wink.gif' alt=';-)' class='wp-smiley' /> </p>
<p>En parallèle de ça, l&#8217;inspecteur <acronym title="Document Object Model">DOM</acronym> est à utiliser pour <strong>visualiser d&#8217;un coup d&#8217;œil les différentes variables actives ainsi que leur arborescence</strong>. Comme tout est cliquable, l&#8217;inspecteur vous transporte sur n&#8217;importe quel objet pour en étudier le contenu.</p>
<h4>La console Firebug <em>alias</em> <code>console.*</code></h4>
<p style="text-align:center"><img src="http://case.oncle-tom.net/images/2007/12/firebug-console.png" alt="Console Firebug" /></p>
<p><strong>La console Firebug est l&#8217;autre tueuse d&#8217;<code>alert()</code></strong> et s&#8217;utilise de deux manières.</p>
<p>La plus accessible est d&#8217;<strong>interagir avec</strong>. Vous saisissez votre code, la console l&#8217;exécute et retourne le ou les résultats. Encore une fois les objets sont cliquables et navigable au travers de l&#8217;inspecteur <acronym title="Document Object Model">DOM</acronym>.<br />
La console est utile pour utiliser des fonctions sorties du contexte de l&#8217;initialisation : il devient tout à fait possible de piloter des éléments après le chargement de la page. Ça évite encore une fois des <kbd>F5</kbd> inutiles et consommateurs de temps.</p>
<p>L&#8217;autre manière d&#8217;utiliser la console c&#8217;est de ne pas l&#8217;utiliser. Ou pas de manière active tout du moins puisqu&#8217;<strong>elle est également un objet JavaScript</strong> (<code>console</code>) utilisable dans votre code auquel sont rattachées plusieurs fonctions au nom explicite :</p>
<ul>
<li><code>console.log()</code> : affiche une information standard</li>
<li><code>console.info()</code> : affiche une information de type &laquo;&nbsp;information&nbsp;&raquo;</li>
<li><code>console.warn()</code> : affiche une information de type &laquo;&nbsp;avertissement&nbsp;&raquo;</li>
<li><code>console.error()</code> : affiche une information de type &laquo;&nbsp;erreur&nbsp;&raquo;</li>
<li><code>console.debug()</code> : débogue le contenu d&#8217;un objet directement dans la console</li>
</ul>
<p>Autrement dit, si l&#8217;inspecteur ne suffisait pas, au lieu de lancer un <code>alert(mavariable)</code> (potentiellement dangereux dans une grande boucle <img src='http://case.oncle-tom.net/wp-includes/images/smilies/icon_wink.gif' alt=';-)' class='wp-smiley' />  qui n&#8217;a jamais cliqué 50 fois sur &laquo;&nbsp;OK&nbsp;&raquo; à cause de ça ?), il vaudra mieux utiliser <code>console.log(mavariable)</code>. Il y a de quoi faire, surtout avec la possibilité de créer des groupes de messages et l&#8217;utilisation de la syntaxe <code>printf</code>.</p>
<p>Et top du top, en cas d&#8217;erreur JavaScript, la console affiche un petit cercle rouge qui rappelle fortement le point d&#8217;arrêt. Normal puisque c&#8217;en est un. Un clic et on évite de rechercher la ligne problématique dans le code. Encore une fois, du temps de gagné.</p>
<h3 id="firebug-performances">Firebug pour les performances</h3>
<p>Après avoir bien développé, Firebug propose de mieux développer. L&#8217;extension magique propose quelques outils sympathiques pour rapidement déceler les problèmes, notamment de scripts trop gourmands ou à optimiser.</p>
<h4>Le traceur réseau</h4>
<p style="text-align:center"><img src="http://case.oncle-tom.net/images/2007/12/firebug-net-tracer.png" alt="Traceur réseau Firebug" /></p>
<p>Avec le traceur réseau c&#8217;est simple, tout ce qui est chargé sur la page est chronométré. Si un élément est systématiquement long à charger en tête de liste, pourquoi ne pas essayer de le déplacer dans le bas de la pile ? Je pense notamment aux appels vers des fichiers JavaScripts externes. Les appeler en bas de page permet d&#8217;éviter des gels de page. C&#8217;est ce que YSlow nous recommandera <img src='http://case.oncle-tom.net/wp-includes/images/smilies/icon_wink.gif' alt=';-)' class='wp-smiley' /> </p>
<p>Outre une petite prévisualisation des contenus, le traceur affiche aussi les <strong>statuts des contenus</strong> s&#8217;ils sont différent du statut 200 (<em>found</em>). Et de surligner ça en rouge en cas de fichier introuvable.</p>
<p>J&#8217;aime beaucoup le traceur pour le <strong>suivi des requêtes XHR (appels <acronym title="Asynchronous JavaScript and XML">AJAX</acronym>)</strong>. Un clic sur un appel affiche à la fois les entêtes, les données transmises au serveur et sa réponse. Fini les requêtes <acronym title="Asynchronous JavaScript and XML">AJAX</acronym> qui ne produisent rien sans qu&#8217;on puisse savoir pourquoi. Le clic droit sera également un fidèle allié, notamment pour ouvrir l&#8217;appel <acronym title="Asynchronous JavaScript and XML">AJAX</acronym> dans un nouvel onglet. C&#8217;est plus lisible pour déboguer quand même <img src='http://case.oncle-tom.net/wp-includes/images/smilies/icon_wink.gif' alt=';-)' class='wp-smiley' /> </p>
<h4>Le profileur JavaScript</h4>
<p style="text-align:center"><img src="http://case.oncle-tom.net/images/2007/12/firebug-profiler.png" alt="Profileur JavaScript Firebug" /></p>
<p>Le profileur (<em>profiler</em>) JavaScript s&#8217;utilise un peu à la manière de la console : de manière active ou au travers de l&#8217;objet <code>console</code>.</p>
<p><strong>Le profileur enregistre tout ce qui se passe entre le moment où il est enclenché et le moment où il est stoppé</strong>. Il va ainsi dénombrer toutes les appels (<em>calls</em>), leur durée d&#8217;exécution et leur fichier d&#8217;origine, entre autre. L&#8217;idée est bien entendu de voir ce qui consomme le plus d&#8217;appels et de temps pour savoir si ce comportement est normal ou pas. À ce stade là, difficile de pousser la granularité du profileur plus loins.</p>
<p>Sauf en utilisant le profileur directement dans le code comme on a déjà pu le faire pour les <em>logs</em>. <code>console.profile()</code> et <code>console.profileEnd()</code> seront vos amis. C&#8217;est vraiment l&#8217;idéal pour <strong>profiler l&#8217;exécution d&#8217;une fonction</strong>, voire même les portions de code exécutée en son sein.</p>
<h4>L&#8217;extension YSlow</h4>
<p style="text-align:center"><img src="http://case.oncle-tom.net/images/2007/12/firebug-yslow.png" alt="Firebug YSlow" /></p>
<p>L&#8217;<a href="https://addons.mozilla.org/en-US/firefox/addon/5369">extension YSlow</a> est une extension pour Firefox mais elle nécessite toutefois la présence de Firebug. Elle s&#8217;articule autour de trois critères.</p>
<p>Il y&#8217; a d&#8217;une part la surveillance des performances. YSlow se base sur la <a href="http://developer.yahoo.com/performance/rules.html">liste des bonnes pratiques établies par Yahoo!</a> (14 à l&#8217;heure actuelle). YSlow passe ces critères en revue et accorde une note en conséquence. Si certaines sont difficiles à tenir, c&#8217;est un bon moyen de s&#8217;intéresser à de <strong>nouvelles pratiques d&#8217;optimisation et de performances</strong>.</p>
<p>Le second critère est affiché dans le panneau <em>stats</em>. Il s&#8217;agit de la capture d&#8217;écran ci-dessus. Certes il s&#8217;agit d&#8217;un simple tableau mais dont les chiffres sont intéressants à étudier. YSlow analyse la page pour un premier et un second chargement. La différence entre les deux ? C&#8217;est que le cache est passé par là et normalement, je dis bien normalement, <strong>le second chargement se doit d&#8217;être beaucoup plus rapide</strong>.<br />
Si ce n&#8217;est pas le cas, il y a de l&#8217;optimisation à faire et cela peut aussi signifier du côté serveur Web. Pas forcément du développement donc.</p>
<p>Enfin on termine sur une partie complémentaire aux stats : les composants (<em>components</em>). Elle distille des informations plus verbeuses que le traceur réseau de Firebug en se focalisant sur les E-Tag, la présence ou pas de compression, la date de validité du cache ainsi que la taille des objets.</p>
<h3>Conclusion</h3>
<p>J&#8217;espère avoir éclairé quelques lanternes sur l&#8217;utilisation de Firebug. Cette extension est suffisamment puissante pour gagner en confort de développement ; il serait dommage de s&#8217;en priver. <strong>On gagne du temps, du confort et surtout, de la qualité de développement</strong>.<br />
À noter qu&#8217;il existe aussi Firebug Lite. Il s&#8217;agit d&#8217;un script JavaScript compatible avec les principaux navigateurs du marché mais comme le <em>Lite</em> l&#8217;indique, les fonctionnalités sont plutôt limitées. Seule la console JavaScript persiste.</p>
]]></content:encoded>
			<wfw:commentRss>http://case.oncle-tom.net/2007/bonnes-pratiques-firebug-developpement-web/feed/</wfw:commentRss>
		<slash:comments>15</slash:comments>
		</item>
		<item>
		<title>jQuery : optimiser l&#8217;utilisation des sélecteurs CSS</title>
		<link>http://case.oncle-tom.net/2007/jquery-optimisation-selecteurs-css/</link>
		<comments>http://case.oncle-tom.net/2007/jquery-optimisation-selecteurs-css/#comments</comments>
		<pubDate>Tue, 18 Dec 2007 07:00:02 +0000</pubDate>
		<dc:creator>Oncle Tom</dc:creator>
				<category><![CDATA[Développement Web]]></category>
		<category><![CDATA[bonnes pratiques]]></category>
		<category><![CDATA[css]]></category>
		<category><![CDATA[css 3]]></category>
		<category><![CDATA[framework]]></category>
		<category><![CDATA[jquery]]></category>
		<category><![CDATA[optimisation]]></category>
		<category><![CDATA[performances]]></category>
		<guid isPermaLink="false">http://case.oncle-tom.net/2007/12/18/jquery-optimisation-selecteurs-css/</guid>
		<description><![CDATA[JQuery est une formidable librairie JavaScript car elle offre une grande souplesse et une utilisation simple. Il est cependant important de bien comprendre son fonctionnement pour éviter les débordements liés à une joie mal maîtrisée. S&#8217;il est très facile d&#8217;utiliser les sélecteurs CSS de jQuery, je constate de ci de là que leur utilisation n&#8217;est [...]]]></description>
			<content:encoded><![CDATA[<p style="text-align:center"><img src="http://case.oncle-tom.net/images/2007/12/jquery-logo.png" alt="Logo jQuery" /></p>
<p><a href="http://jquery.com">JQuery</a> est une formidable librairie JavaScript car elle offre une grande souplesse et une utilisation simple. <strong>Il est cependant important de bien comprendre son fonctionnement</strong> pour éviter les débordements liés à une joie mal maîtrisée.<br />
S&#8217;il est très facile d&#8217;utiliser les sélecteurs <acronym title="Cascading Style Sheets">CSS</acronym> de jQuery, je constate de ci de là que leur utilisation n&#8217;est pas toujours optimale &#8230; quand elle l&#8217;est déjà un tant soit peu.</p>
<p>Alors on se retrousse les manches et c&#8217;est parti pour un petit <strong>cas pratique sur les sélecteurs <acronym title="Cascading Style Sheets">CSS</acronym></strong> jQuery, plus une petite récap&#8217; pour grapiller du temps et des lignes de code <img src='http://case.oncle-tom.net/wp-includes/images/smilies/icon_wink.gif' alt=';-)' class='wp-smiley' /><br />
<span id="more-832"></span></p>
<h3>Le cas pratique</h3>
<p>J&#8217;ai pensé à une chose : plutôt que vous papillonniez en lisant cet article, j&#8217;ai fait en sorte que vous puissiez y prendre part. JQuery est très divertissant &#8211; certainement plus que votre voisine d&#8217;en face &#8211; alors tant qu&#8217;à me lire, autant optimiser la compréhension <img src='http://case.oncle-tom.net/wp-includes/images/smilies/icon_wink.gif' alt=';-)' class='wp-smiley' /><br />
Pour cela il vous faut 2 choses :</p>
<ol>
<li>un <a title="Sandbox HTML / jQuery" href="http://case.oncle-tom.net/images/2007/12/sandbox-oncletom-20071217.htm">bac à sable <acronym title="HyperText Markup Language">HTML</acronym> / jQuery</a> concocté par mes soins</li>
<li>l&#8217;inévitable <a href="https://addons.mozilla.org/fr/firefox/addon/1843">extension Firebug</a> pour bénéficier d&#8217;une console digne de ce nom (entre autre)</li>
</ol>
<h3>Principe de la sélection <acronym title="Cascading Style Sheets">CSS</acronym> de jQuery</h3>
<p>Que celui qui s&#8217;est lancé corps et âme dans jQuery sans lire la <a title="documentation jQuery" href="http://docs.jquery.com/Selectors">documentation</a> lâche un com&#8217; ! Elle est suffisamment complète pour éviter la plupart des questions du genre <q>comment je fais pour &#8230;</q>.</p>
<p>Maintenant que vous avez le document en main, nous allons jouer avec jQuery pour récupérer ce que nous voulons. Les personnes n&#8217;ayant pas Firebug comprendront la logique du code sans même avoir à le regarder :</p>
<pre><code class="javascript">// Récupération du premier paragraphe
$('body p:first-child');
// Récupération du nœud des continents
$('ul.continents');
// Récupération de la liste des capitales
$('.capitale');
// Récupération du dernier élément du body
$('body :last');
// Compter le nombre de pays
$('.pays &gt; li').length;
</code></pre>
<p>Magique non ?</p>
<h3>Comprendre la sélection <acronym title="Cascading Style Sheets">CSS</acronym> de jQuery</h3>
<p>Les résultats sont propres mais n&#8217;est pas parce que ça marche que c&#8217;est bien. La preuve, tous les exemples ci-dessus ne sont pas du tout optimisés.<br />
Alors <strong>comment savoir si un sélecteur est optimisé</strong> ou pas ? La réponse n&#8217;est pas systématique car elle dépend exclusivement de votre rigueur et du <acronym title="Document Object Model"><acronym title="Document Object Model">DOM</acronym></acronym> à interroger. Plus il sera touffu et plus votre sens aigü de la performance sera sollicité.</p>
<p>Reprenons les exemples ci-dessus pour le transposer en JavaScript <em>old-school</em>. C&#8217;est le meilleur moyen de sentir le piège &#8230; ou pas.</p>
<pre><code class="javascript">// Récupération du premier paragraphe
$('body p:first-child');
// équivaut à
document.getElementsByTagName('body')[0].getElementsByTagName('p')[0];</code></pre>
<p>Il y a 2 erreurs dans cette sélection :</p>
<ol>
<li>sélectionner <code>body</code>. <code>getElementsByTagName()</code> oblige à parcourir tous les nœuds du document (1000 s&#8217;il y en a 1000) alors qu&#8217;on n&#8217;en veut qu&#8217;un &#8230; et qu&#8217;il ne peut y en avoir d&#8217;un ;</li>
<li>on sélectionne ensuite tous les <code>p</code> du body. Autant le faire dès la première fois car là encore c&#8217;est tous les nœuds contenus dans <code>body</code> qui sont parcourus &#8230; y compris l&#8217;énorme liste à puces !</li>
</ol>
<pre><code class="javascript">// Récupération du nœud des continents
$('ul.continents');
// équivaut à
var continents = [];
var el = document.getElementsByTagName('ul');
for (i in el)
{
  if (el[i].className.match(/(^| )continents( |$)/);
  {
     continents.push(el[i]);
  }
}</code></pre>
<p>La sélection est ici trop générique. On voit bien que l&#8217;on est obligé de charger tous les éléments <code>ul</code> du <acronym title="Document Object Model">DOM</acronym> pour les filtrer.</p>
<pre><code class="javascript">// Récupération de la liste des capitales
$('.capitale');
// équivaut à
var capitales = [];
var el = document.getElementsByTagName('*');
for (i in el)
{
  if (el[i].className.match(/(^| )capitale( |$)/);
  {
     capitales.push(el[i]);
  }
}</code></pre>
<p>C&#8217;est probablement la dernière chose à faire. Cassez les genoux de toute personne écrivant un tel sélecteur : il mérite d&#8217;animer le BigDill rien de plus !<br />
Dans ce cas de figure, c&#8217;est TOUT le <acronym title="Document Object Model">DOM</acronym> qui est chargé (75 éléments) pour ensuite boucler sur un filtre. Cette boucle n&#8217;est pas optimisée mais ce n&#8217;est pas ce que l&#8217;on souhaite travailler aujourd&#8217;hui <img src='http://case.oncle-tom.net/wp-includes/images/smilies/icon_wink.gif' alt=';-)' class='wp-smiley' /> </p>
<pre><code class="javascript">// Récupération du dernier élément du body
$('body :last');
// équivaut à
var el = document.getElementsByTagName('body')[0].lastChild;</code></pre>
<p>Comme dans le premier cas, le <code>document.getElementsByTagName()</code> charge tout le <acronym title="Document Object Model">DOM</acronym> pour le filtrer, ne récupérer que le premier élément et, seule opération non coûteuse, utiliser son dernier enfant.<br />
Ce n&#8217;est pas la pire des exemples mais là encore on peut optimiser les choses.</p>
<pre><code class="javascript">// Compter le nombre de pays
$('.pays &gt; li').length;
// équivaut à
var pays = 0;
var el = document.getElementsByTagName('*');
for (i in el)
{
  if (el[i].className.match(/(^| )pays( |$)/);
    {
      var continent = el[i];
      for (j in continent.childNodes)
      {
        pays += continent.childNodes[j].nodeName == 'li' ? 1 : 0;
      }
    }
  }
}</code></pre>
<p>Un sélecteur par classe ne devrait être qu&#8217;un cas extrême, quand on ne peut se fier à une balise donnée. Car de manière générale, le <code>getElementsByTagName('*')</code> est à bannir. Charger tout le <acronym title="Document Object Model">DOM</acronym> est une folie furieuse.<br />
La bonne idée ici est l&#8217;utilisation du symbole <code>&gt;</code>. Cela se traduit par <code>.childNodes</code> et nous verrons plus bas pourquoi c&#8217;est mieux.</p>
<h3>Et maintenant, optimisons</h3>
<p>S&#8217;il fallait <strong>résumer l&#8217;optimisation en 3 points</strong>, voici ce que je donnerai :</p>
<ol>
<li>jamais de sélecteur vague</li>
<li>toujours un ID (#&lt;ID&gt;) en tête de sélecteur</li>
<li>utiliser au maximum les objets natifs (<code>firstChild</code>, <code>childNodes</code> etc.) : ils évitent d&#8217;interroger tout le <acronym title="Document Object Model">DOM</acronym></li>
</ol>
<p><strong>L&#8217;ennemi des sélecteurs <acronym title="Cascading Style Sheets">CSS</acronym> ce sont les boucles</strong>. Plus elles ont à brasser d&#8217;éléments, plus elles sont longues. <code>getElementsByTagName()</code> cache une boucle : JavaScript scanne tout le <acronym title="Document Object Model">DOM</acronym> pour trouver un nœud ayant un <code>tagName</code> correspondant.<br />
<strong>S&#8217;il faut l&#8217;utiliser, c&#8217;est en aval d&#8217;un sélecteur ayant déjà trié une bonne partie du document.</strong></p>
<p><strong>Votre meilleur ami est <code>getElementById()</code></strong>. Comme son nom l&#8217;indique il ne retourne qu&#8217;un seul élément et surtout, il est incroyablement rapide. Utilisez-le dans un maximum de cas mais attention tout de même : trop d&#8217;ID nuit à la structure du document le rendant ainsi trop rigide.<br />
Il en est de même du parcours des objets natifs des nœuds du <acronym title="Document Object Model">DOM</acronym>. Cela signifie que dès que vous changer la tête de votre <acronym title="HyperText Markup Language">HTML</acronym>, le JavaScript peut en pâtir.</p>
<p>Des fois <strong>il faudra faire quelques concessions de performances pour éviter de réécrire votre code</strong> au moindre changement &#8230; ou parce que la génération est dynamique et difficilement maîtrisable.</p>
<p>Grâce à ces informations, nous pouvons reprendre nos exemples mais de manière optimisée :</p>
<pre><code class="javascript">// Récupération du premier paragraphe
$('body p:first-child');
// version optimisée
$('#sandbox &gt; p:first');
// Récupération du nœud des continents
$('ul.continents');
// version optimisée
$('#geoliste');
// Récupération de la liste des capitales
$('.capitale');
// version optimisée (mais fortement liée à la structure du document)
$('#geoliste &gt; li &gt; ul ul &gt; li.capitale');
// Récupération du dernier élément du body
$('body :last');
// version optimisée
$('#sandbox :last');
// Compter le nombre de pays
$('.pays &gt; li').length;
// version optimisée (mais liée à la structure du document)
$('#geoliste &gt; li &gt; ul &gt; li').length;
</code></pre>
<h3>Évitons les doublons : chaînons !</h3>
<p>Les <acronym title="Cascading Style Sheets">CSS</acronym> c&#8217;est un peu fatiguant alors terminons sur une autre utilisation de jQuery parfois sous-employée à cause d&#8217;un manque de compréhension : les chaînes. jQuery renvoie des objets et permet de réutiliser/filtrer les résultats avec un seul sélecteur.</p>
<p>Voici un extrait de code largement optimisable :</p>
<pre><code class="javascript">$('#intro').addClass('jevaisdisparaitre');
$('#intro').append(' &lt;strong&gt;Je vais disparaître&lt;/strong&gt;.');
$('#intro code').html('Goodbye World');
$('#intro').css('cursor', 'pointer');
$('#intro').one('click', function(){ alert("Bye bye"); $(this).remove(); });
</code></pre>
<p>Tout est correct sauf qu&#8217;on répète plusieurs fois le même sélecteur au lieu d&#8217;utiliser la chaîne disponible. jQuery optimise la sélection d&#8217;un élément déjà sélectionné au préalable mais n&#8217;empêche, au lieu d&#8217;interroger 5 fois <code>#intro</code>, nous n&#8217;allons plus le faire qu&#8217;une seule fois :</p>
<pre><code class="javascript">$('#intro')
  .addClass('jevaisdisparaitre')
  .append(' &lt;strong&gt;Je vais disparaître&lt;/strong&gt;.')
  .one('click', function(){
    alert("Bye bye");
    $(this).remove();
  })
  .children('code')
  .html('Goodbye World');
</code></pre>
<p>Tout se suit jusqu&#8217;à la fonction <code>children()</code> qui modifie le sélecteur de départ et applique la suite de la chaîne à cette nouvelle sélection.<br />
Une autre optimisation consiste à déplacer la déclaration <acronym title="Cascading Style Sheets">CSS</acronym> <code>cursor</code> dans la classe <code>.jevaisdisparaitre</code> de l&#8217;hypothétique feuille de style. <strong>Essayez de dissocier au mieux fond et forme</strong> : ça évite <em>BEAUCOUP</em> de modifications de code pour des ajustements esthétiques.</p>
<h3>Conclusion</h3>
<p><strong>Optimiser ses sélecteurs n&#8217;est finalement pas si difficile que ça quand on comprend comment fonctionnent les rouages internes</strong>. Il est évident que les gains peuvent être minimes sur de petites pages. Il s&#8217;agit cependant d&#8217;une gymnastique à maîtriser : ce n&#8217;est pas en arrivant sur de gros volumes qu&#8217;il faudra apprendre à sélectionner proprement.</p>
<p>Et comme <q>les petites rivières font les grands fleuves</q>, ces petites économies pourraient vous sauver la vie sur des applications full-<acronym title="Asynchronous JavaScript and XML">AJAX</acronym> ou qui sait, quand vous travaillerez chez Netvibes <img src='http://case.oncle-tom.net/wp-includes/images/smilies/icon_wink.gif' alt=';-)' class='wp-smiley' /> </p>
]]></content:encoded>
			<wfw:commentRss>http://case.oncle-tom.net/2007/jquery-optimisation-selecteurs-css/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>MySQL : tris personnalisés et aléatoires</title>
		<link>http://case.oncle-tom.net/2007/mysql-tri-personnalises-aleatoires/</link>
		<comments>http://case.oncle-tom.net/2007/mysql-tri-personnalises-aleatoires/#comments</comments>
		<pubDate>Tue, 21 Aug 2007 11:00:12 +0000</pubDate>
		<dc:creator>Oncle Tom</dc:creator>
				<category><![CDATA[Développement Web]]></category>
		<category><![CDATA[logiciels libres]]></category>
		<category><![CDATA[MySQL]]></category>
		<category><![CDATA[optimisation]]></category>
		<category><![CDATA[order by]]></category>
		<category><![CDATA[tris]]></category>
		<guid isPermaLink="false">http://case.oncle-tom.net/2007/08/21/mysql-tri-personnalises-aleatoires/</guid>
		<description><![CDATA[La majorité des systèmes de bases de données permettent de trier une sélection de données en fonction de nos besoins, souvent de manière simple. La majorité des besoins courants impliquent des tris ascendants ou descendants (comprendre &#171;&#160;par ordre alphabétique croissant ou descendant&#160;&#187;) sur une plusieurs colonnes (des dates, des titres ou des codes particuliers) mais [...]]]></description>
			<content:encoded><![CDATA[<p style="text-align:center"><img src="http://case.oncle-tom.net/images/2007/08/powered-by-mysql-167x86.png" alt="Logo MySQL" /></p>
<p>La majorité des systèmes de bases de données permettent de trier une sélection de données en fonction de nos besoins, souvent de manière simple. La majorité des besoins courants impliquent des tris ascendants ou descendants (comprendre &laquo;&nbsp;par ordre alphabétique croissant ou descendant&nbsp;&raquo;) sur une plusieurs colonnes (des dates, des titres ou des codes particuliers) mais de temps à autre, il arrive que les  besoins soient plus complexes puisque l&#8217;on voudra soit :</p>
<ul>
<li>un <strong>ordre aléatoire</strong></li>
<li>un <strong>ordre bien précis</strong>, ni ascendant ni descendant</li>
</ul>
<p><span id="more-743"></span></p>
<h3>Le mécanisme de tri (<code>ORDER BY</code>)</h3>
<p>Pour bien comprendre comment fonctionne en détail la commande <code>ORDER BY</code>, je vous invite à lire la documentation concernant les <a href="http://dev.mysql.com/doc/refman/5.1/en/order-by-optimization.html">optimisations relatives à ORDER BY</a>. Ce que l&#8217;on doit en retenir :</p>
<ol>
<li><strong>le tri est effectué sur les données filtrées</strong> par un éventuel <code>WHERE</code> ;</li>
<li><strong>il y a 2 algorithmes de tri</strong> : l&#8217;un utilisant <em>deux passes</em>, l&#8217;autre n&#8217;utilisant qu&#8217;<em>une passe</em> mais davantage de mémoire ;</li>
<li>l&#8217;algorithme en une passe n&#8217;est pas valable pour des tris sur des données de type <code>TEXT</code> ou <code>BLOB</code> ;</li>
<li><strong>un tri sur un index est largement plus rapide</strong> et plus performant que sur des valeurs non-indexées</li>
</ol>
<p>Lorsqu&#8217;on veut trier des données, il vaut donc mieux <em>écrémer au mieux la plage de données</em> grâce à de judicieux filtres <code>WHERE</code> et de préférence, sur des colonnes indexées.</p>
<p>Mais revenons à nos moutons.</p>
<h3>Tri aléatoire (<code>ORDER BY RAND()</code>)</h3>
<p><strong>Deux solutions s&#8217;offrent au développeur pour effectuer un tri aléatoire</strong> : recueillir les données voulues et les trier <em>via</em> langage de programmation (<code>sort()</code>, <code>ksort()</code> etc.) ou alors trier directement à la source <em>via</em> la base de données.<br />
Si les bases de données portent leur nom, c&#8217;est bien parce qu&#8217;elles sont performantes dans leur travail donc autant leur laisser celui-là, celui du tri aléatoire, qui sera bien plus rapide et performant, surtout sur des volumes importants de données.</p>
<p>Cette solution est relativement connue, <code>ORDER BY RAND()</code> mélange les données recueillies de manière totalement aléatoire, sans tenir compte des index ni de quoi que ce soit d&#8217;autre. Pensez à utiliser une clause <code>LIMIT</code> si vous ne voulez récupérer qu&#8217;un nombre défini de lignes.</p>
<pre><code class="sql">SELECT * FROM `ma_table` ORDER BY RAND() LIMIT 1 ;</code></pre>
<p>Cette instruction prendra une ligne et une seule, au hasard. Rapide, concis et efficace.</p>
<h3>Tri personnalisé (<code>ORDER BY FIELD()</code>)</h3>
<p>Pire que le tri aléatoire, il y a celui du tri personnalisé, celui qui n&#8217;est <em>ni</em> ascendant, <em>ni</em> descendant, <em>ni</em> aléatoire : on veut un ordre précis. Imaginons que nous nous trouvions avec la table  suivante :</p>
<table class="code sql" border="0">
<thead>
<tr>
<th>jour_id</th>
<th>jour_nom</th>
</tr>
</thead>
<tbody>
<tr>
<th>ven</th>
<td>Vendredi</td>
</tr>
<tr>
<th>lun</th>
<td>Lundi</td>
</tr>
<tr>
<th>dim</th>
<td>Dimanche</td>
</tr>
<tr>
<th>mer</th>
<td>Mercredi</td>
</tr>
<tr>
<th>sam</th>
<td>Samedi</td>
</tr>
<tr>
<th>jeu</th>
<td>Jeudi</td>
</tr>
<tr>
<th>mar</th>
<td>Mardi</td>
</tr>
</tbody>
</table>
<p>Comment faire pour récupérer la liste des jours de semaine dans l&#8217;ordre de notre choix ? Tout simplement en utilisant la <a href="http://dev.mysql.com/doc/refman/5.1/en/string-functions.html#function_field">fonction FIELD()</a> (depuis MySQL 4) :</p>
<pre><code class="sql">SELECT jour_nom
FROM `dates_semaine`
ORDER BY FIELD( <em>jour_id</em>, 'lun', 'mar', 'mer', 'jeu', 'ven', 'sam', 'dim' ) ;</code></pre>
<p>J&#8217;aurais tendance à dire que la requête parle d&#8217;elle-même : on spécifie un tri sur le champ <em>jour_id</em> dans l&#8217;ordre passé dans les paramètres suivants.<br />
Ce qui est intéressant dans notre cas c&#8217;est qu&#8217;on peut donc gérer des semaines débutant le jeudi, le samedi, le dimanche ou le lundi (histoire de coller avec tous les calendriers existants). Seuls les paramètres à donner à la requête changeraient.<br />
C&#8217;est également intéressant pour <strong>trier le résultat d&#8217;une requête en fonction de l&#8217;ordre des lignes d&#8217;un fichier</strong> qui aurait été uploadé sur un serveur.</p>
<h3>Conclusion</h3>
<p>La clause <code>ORDER BY</code> est plus puissante qu&#8217;il n&#8217;y paraît. <strong>Elle est garante de l&#8217;ordre des résultats retournés</strong>. Si dans certains cas l&#8217;ordre n&#8217;a pas d&#8217;importance, le contraire peut également être valable. Et c&#8217;est précisément dans ce cas que l&#8217;on aime à pouvoir manipuler les données comme on l&#8217;entend.<br />
Il existe d&#8217;autres possibilités intéressantes en combinant par exemple le tri et les recherches <em>FULLTEXT</em> pour <strong>récupérer les lignes par ordre de pertinence</strong> ou pourquoi pas sur des <strong>résultats de calcul</strong>.</p>
]]></content:encoded>
			<wfw:commentRss>http://case.oncle-tom.net/2007/mysql-tri-personnalises-aleatoires/feed/</wfw:commentRss>
		<slash:comments>16</slash:comments>
		</item>
		<item>
		<title>Rock your Firefox : mes extensions Firefox préférées</title>
		<link>http://case.oncle-tom.net/2007/facebook-rock-your-firefox/</link>
		<comments>http://case.oncle-tom.net/2007/facebook-rock-your-firefox/#comments</comments>
		<pubDate>Tue, 07 Aug 2007 11:00:26 +0000</pubDate>
		<dc:creator>Oncle Tom</dc:creator>
				<category><![CDATA[Développement Web]]></category>
		<category><![CDATA[dom]]></category>
		<category><![CDATA[facebook]]></category>
		<category><![CDATA[firefox]]></category>
		<category><![CDATA[microformats]]></category>
		<category><![CDATA[mozilla]]></category>
		<category><![CDATA[optimisation]]></category>
		<guid isPermaLink="false">http://case.oncle-tom.net/2007/08/07/facebook-rock-your-firefox/</guid>
		<description><![CDATA[Read/WriteWeb fait partie de mes sources d&#8217;informations quotidiennes. Je suis tombé aujourd&#8217;hui sur un article concernant le lancement d&#8217;une nouvelle application Facebook permettant de recommander ses extensions favorites : Rock your Firefox. Ca tombe bien puisque je songeais depuis quelques jours à parler des extensions que j&#8217;utilise quotidiennement dans Firefox. Certaines n&#8217;intéresseront que les développeurs, [...]]]></description>
			<content:encoded><![CDATA[<p style="text-align:center"><img src='http://case.oncle-tom.net/images/2007/08/rock-your-firefox.gif' alt='Rock your Firefox logo' /></p>
<p><a href="http://www.readwriteweb.com/">Read/WriteWeb</a> fait partie de mes sources d&#8217;informations quotidiennes. Je suis tombé aujourd&#8217;hui sur un article concernant le <a href="http://www.readwriteweb.com/archives/firefox_launches_facebook_app.php">lancement d&#8217;une nouvelle application Facebook permettant de recommander ses extensions favorites</a> : <a href="http://www.facebook.com/apps/application.php?api_key=b342b55715483ad3ff6a5495b9368702">Rock your Firefox</a>.</p>
<p>Ca tombe bien puisque je songeais depuis quelques jours à parler des extensions que j&#8217;utilise quotidiennement dans Firefox. Certaines n&#8217;intéresseront que les développeurs, d&#8217;autres les amateurs de praticité.<br />
<span id="more-735"></span></p>
<h3>Extensions Firefox</h3>
<p>Avant toute chose, si jamais vous vous posiez la question <q>où trouver de nouvelles extensions pour Firefox</q> (ou <em>Thunderbird</em> ou d&#8217;autres produits <em>Mozilla</em>), rendez-vous sur <a href="https://addons.mozilla.org/fr/">Mozilla Add-ons</a>.<br />
L&#8217;application Facebook <strong>Rock your Firefox</strong> reprend la liste des extensions et des thèmes en vous proposant de choisir vos préférées et de les partager sur votre profil. C&#8217;est un bon moyen pour afficher votre qualité d&#8217;utilisation de ce navigateur libre et gratuit.</p>
<h3>Extensions &laquo;&nbsp;Pratiques&nbsp;&raquo;</h3>
<h4><a href="https://addons.mozilla.org/fr/firefox/addon/10">Adblock</a></h4>
<p>Certains sites sont envahis de publicités qui gênent affreusement la navigation. Plutôt que de se passer d&#8217;un contenu intéressant, autant supprimer les nuisances. <strong>Adblock</strong> est là pour ça. Que ça soit des images,des animations Flash ou bien encore des scripts JavaScript, <strong>Adblock liste le contenu des ressources bloquables</strong> et permet même de créer des filtres génériques à l&#8217;aide du caractère <code>*</code> (<em>wildcard</em>, remplace un à plusieurs caractères, peu importe lesquels).<br />
<strong>Attention</strong> toutefois, la <em>publicité est vitale pour de nombreux sites</em> donc bloquez avec intelligence.</p>
<h4><a href="https://www.google.com/tools/firefox/browsersync/">Google Browser Sync</a></h4>
<p>C&#8217;est certainement l&#8217;extension que j&#8217;installe en premier et pour cause : <strong>Google Browser Sync sauvegarde tous mos favoris, cookies et historique de navigation de manière sécurisée</strong>.<br />
Je l&#8217;utilise sur plusieurs ordinateurs et plusieurs installations de Firefox ce qui me permet de retrouver tous mes favoris peu importe où je me trouve, à partir du moment où il y a une connexion Internet. A utiliser pour vos sauvegardes ou vos besoins de mobilité.</p>
<h4><a href="https://addons.mozilla.org/fr/firefox/addon/636"><acronym title="Portable Document Format">PDF</acronym> Download</a></h4>
<p>Je n&#8217;aime pas que les documents <acronym title="Portable Document Format"><acronym title="Portable Document Format">PDF</acronym></acronym> s&#8217;ouvrent directement dans un onglet ou une fenêtre de mon navigateur Web. Surtout quand les plus lourds le font planter. <strong><acronym title="Portable Document Format">PDF</acronym> Download</strong> affiche systématiquement plusieurs choix tels que <q>Afficher dans la page</q>, <q>Ouvrir en tant que <acronym title="Portable Document Format">PDF</acronym></q> ou encore <q>Télécharger directement</q>.</p>
<h4><a href="https://addons.mozilla.org/fr/firefox/addon/1146">Screengrab!</a></h4>
<p><strong>Screengrab</strong> est une <strong>solution propre pour effectuer une capture d&#8217;écran</strong> de sa portion visible, d&#8217;une page Web complète ou bien d&#8217;une portion d&#8217;écran bien définie. Vous l&#8217;aurez compris, pas besoin de faire 10 000 captures pour une page étalée en hauteur et pas besoin d&#8217;avoir <em>Photoshop</em> ou <em>The Gimp</em> d&#8217;installé pour s&#8217;en sortir.</p>
<h4><a href="https://addons.mozilla.org/fr/firefox/addon/1122">Tab Mix Plus</a></h4>
<p><strong>Tab Mix Plus</strong> apporte un <strong>lot considérable d&#8217;options pour mieux régler le comportement de vos onglets</strong>. Personnellement je l&#8217;utilise pour que toute nouvelle fenêtre se charge obligatoirement dans un nouvel onglet <em>sans me déranger</em> (chargement en arrière-plan). Je profite aussi de son indicateur de chargement allant de 0 à 100%.<br />
En revanche j&#8217;évite son système de récupération en cas de plantage, il fonctionne moins bien que celui intégré à Firefox (pour les rares cas où cela s&#8217;est produit chez moi).</p>
<p style="text-align:center"><img src='http://case.oncle-tom.net/images/2007/08/firefox-extensions.gif' alt='Extensions Firefox' /></p>
<h3>Extensions &laquo;&nbsp;Développeur Web&nbsp;&raquo;</h3>
<h4><a href="https://addons.mozilla.org/fr/firefox/addon/271">ColorZilla</a></h4>
<p><strong>ColorZilla</strong> est une simple <strong>pipette colorimétrique</strong> mais ô combien efficace. Un clic sur un endroit de la page mémorise automatiquement le code couleur associé et permet de l&#8217;utiliser sous plusieurs formats dans n&#8217;importe quel autre programme dont <em>Photoshop</em> ou votre éditeur <acronym title="Cascading Style Sheets"><acronym title="Cascading Style Sheets">CSS</acronym></acronym> favori.</p>
<h4><acronym title="Document Object Model">DOM</acronym> Inspector</h4>
<p>C&#8217;est la seule extension qui ne se télécharge pas/plus (jusqu&#8217;à la version 1.5 c&#8217;était encore possible). L&#8217;inspecteur <acronym title="Document Object Model"><acronym title="Document Object Model">DOM</acronym></acronym> s&#8217;installe en même temps que Firefox (si vous cochez la case adéquate) et permet comme son nom l&#8217;indique, d&#8217;<strong>inspecter les noeuds de votre document</strong> (<acronym title="HyperText Markup Language"><acronym title="HyperText Markup Language">HTML</acronym></acronym> ou <acronym title="eXtensible Markup Language"><acronym title="eXtensible Markup Language">XML</acronym></acronym>), d&#8217;en voir leurs attributs, fonctions et ce de <em>manière récursive</em>.<br />
L&#8217;analyse en temps réel permet même de voir les modifications apportées à l&#8217;arbre <acronym title="Document Object Model">DOM</acronym> par le biais du JavaScript.</p>
<h4><a href="https://addons.mozilla.org/fr/firefox/addon/1843">Firebug</a></h4>
<p><strong>Firebug</strong> est obligatoire lorsqu&#8217;on souhaite <strong>explorer avec aisance la structure <acronym title="HyperText Markup Language">HTML</acronym></strong> d&#8217;un document, <strong>exécuter du JavaScript à même la page</strong> ou <strong>déboguer efficacement son code</strong>, ne serait-ce qu&#8217;en se rendant compte des temps de chargement des différents fichiers (<acronym title="Cascading Style Sheets">CSS</acronym>, JavaScript, Flash etc.).<br />
Ca incite notamment à taper son code directement dans sa console plutôt qu&#8217;à le modifier et recharger la page pour déceler des erreurs ou étudier le comportement de la page. On gagne du temps et votre employeur de l&#8217;argent.</p>
<h4><a href="https://addons.mozilla.org/fr/firefox/addon/5369">Firebug : YSlow</a></h4>
<p><strong>YSlow</strong> est une extension Firefox mais dédiée à Firebug. Une petite première <em>made in Yahoo!</em> très utile. Cette extension permet de calculer les <strong>performances de la page</strong>, <strong>suggère des optimisations</strong> et <strong>analyse les différents composants</strong> ainsi que leurs caractéristiques (<acronym title="Uniform Resource Locator">URL</acronym>, poids, temps de réponse et ETag).<br />
Indispensable pour les phases d&#8217;<strong>optimisation</strong> et de <em>fine tuning</em> comme dirait l&#8217;autre.</p>
<h4><a href="https://addons.mozilla.org/fr/firefox/addon/4106">Operator</a></h4>
<p>Je vous ai déjà parlé de l&#8217;<a href="http://case.oncle-tom.net/2007/07/31/semantique-microformats-internet/">intérêt des microformats</a> ? <strong>Operator</strong> est un outil notifiant des microformats actifs sur les pages que vous visitez. Outre la navigation interactive procurée, Operator signale dans la console de débogage d&#8217;éventuelles erreurs (élément absent, malformé ou invalidant un microformat).</p>
<h4><a href="https://addons.mozilla.org/fr/firefox/addon/2063">TimeStamp Converter</a></h4>
<p>Le nombre 1198533599 vous dit quelque chose ? Avec <strong>TimeStamp Converter</strong> ça sera le cas. Cette extension convertit les temps Unix en heure humainement compréhensible et vice-versa. Elle le fait également à partir de sélections de texte, évitant ainsi toute saisie pénible.</p>
<h4><a href="https://addons.mozilla.org/fr/firefox/addon/60">Web Developer</a></h4>
<p>Le Saint-Graal du développeur Web. Triturer la page, modifier ses mécanismes, débloquer des champs en lecture seule, afficher les champs masqués, topographie de la page, modifier la résolution et afficher l&#8217;arborescence en cascade de la page jusqu&#8217;à un élément pointé de la souris sont le genre d&#8217;outils fournis par <strong>Web Developer</strong>. Couplée avec Firebug, vous transformez un &laquo;&nbsp;simple&nbsp;&raquo; navigateur Web en machine de guerre du développement Web propre et efficace.</p>]]></content:encoded>
			<wfw:commentRss>http://case.oncle-tom.net/2007/facebook-rock-your-firefox/feed/</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
		<item>
		<title>Utilisation de variables dans MySQL</title>
		<link>http://case.oncle-tom.net/2007/utilisation-variables-mysql/</link>
		<comments>http://case.oncle-tom.net/2007/utilisation-variables-mysql/#comments</comments>
		<pubDate>Fri, 13 Jul 2007 11:00:30 +0000</pubDate>
		<dc:creator>Oncle Tom</dc:creator>
				<category><![CDATA[Développement Web]]></category>
		<category><![CDATA[astuce]]></category>
		<category><![CDATA[code]]></category>
		<category><![CDATA[MySQL]]></category>
		<category><![CDATA[optimisation]]></category>
		<guid isPermaLink="false">http://case.oncle-tom.net/2007/07/13/utilisation-variables-mysql/</guid>
		<description><![CDATA[MySQL, depuis la version 3.23.6, permet de déclarer des variables dans ses requêtes. Il est d&#8217;ailleurs possible de scripter ses requêtes mais c&#8217;est une autre histoire. Ca peut sembler inutile à première vue lorsqu&#8217;on utilise MySQL au travers d&#8217;API d&#8217;autres langages (PHP, Perl, C# etc.). Et pourtant ça peut vous être très utile pour économiser [...]]]></description>
			<content:encoded><![CDATA[<p><strong>MySQL</strong>, depuis la version <em>3.23.6</em>, permet de déclarer des variables dans ses requêtes. Il est d&#8217;ailleurs possible de scripter ses requêtes mais c&#8217;est une autre histoire.</p>
<p>Ca peut sembler inutile à première vue lorsqu&#8217;on utilise MySQL au travers d&#8217;<acronym title="Application Programming Interface"><acronym title="Application Programming Interface">API</acronym></acronym> d&#8217;autres langages (<acronym title="PHP : Hypertext Processor"><acronym title="Pre-Hypertext Processing">PHP</acronym></acronym>, <acronym title="Practical Extraction and Report Language">Perl</acronym>, C# etc.). Et pourtant ça peut vous être très utile pour économiser des requêtes, du temps à programmer ces boucles et puis surtout, <strong>par flemme</strong>.</p>
<p>Oui, la flemme est pour moi la <strong>qualité numéro un</strong> du développeur car <em>le flemmard a pour but d&#8217;arriver à ses fins en un minimum d&#8217;efforts</em>.<br />
<span id="more-618"></span></p>
<h3>Déclaration de variables</h3>
<p>On peut déclarer une variable de deux façons dans MySQL.<br />
La première méthode consiste à utiliser l&#8217;opérateur <code>SET</code>.</p>
<pre><code class="sql">SET @pierre = 3, @feuille = 3 + 2, @ciseau = @pierre % @feuille ;</code></pre>
<p>On peut également consister une variable à partir d&#8217;une requête.</p>
<pre><code class="sql">SELECT @nb_total := COUNT(*) FROM `ma_table` ;</code></pre>
<p><strong>Note</strong> : dans ce cas là, on préfixe l&#8217;opérateur <code>=</code> de <code>:</code> (deux points).</p>
<h3>Utilisation simple des variables</h3>
<p>L&#8217;utilisation première qui peut en être faite c&#8217;est d&#8217;assainir vos requêtes <acronym title="Structured Query Language">SQL</acronym> en évitant au maximum l&#8217;apparition de variables issues d&#8217;autres langages.<br />
<strong>Avant</strong> :</p>
<pre><code class="sql">SELECT * FROM `ma_table` WHERE colonne1 = {$variable1}, colonne2 = '{$variable2}' LIMIT 1;</code></pre>
<p><strong>Après</strong> :</p>
<pre><code class="sql">SET @variable1 = {$variable1}, @variable2 = '{$variable2}';
SELECT * FROM `ma_table` WHERE colonne1 = @variable1, colonne2 = @variable2 LIMIT 1;</code></pre>
<p>Comme les variables sont effectives pour la connexion courante, une variable MySQL peut être réutilisée à tout moment. De quoi décomplexifier certains scripts pas forcément bien structurés.</p>
<h3>Utilisation complexe des variables</h3>
<p><strong>Les variables peuvent également être modifiées à même la requête</strong>. C&#8217;est à dire qu&#8217;à chaque itération effectuée par MySQL, le moteur va réévaluer le contenu de la variable. J&#8217;ai notamment eu besoin de ça pour ajouter de nouveaux éléments à la suite d&#8217;autres tout en renumérotant leur ordre. Je souhaitais <strong>éviter une boucle récursive en <acronym title="Pre-Hypertext Processing">PHP</acronym></strong> qui aurait occasionné de multiples requêtes.</p>
<p>Je dispose d&#8217;une table (<code>item_liste</code>) avec plusieurs éléments, une clé primaire sur deux champs (<code>item_id</code> et <code>item_cat</code>) ainsi qu&#8217;un autre champ indexé permettant de les trier dans un ordre donné (<code>item_ordre</code>). Le but : prendre des éléments de la catégorie 1 pour les mettre à la suite de la catégorie 2.</p>
<p>Voici en gros ce que ça donne au final :</p>
<pre><code class="sql">SELECT @ordre := IFNULL(MAX(item_ordre), 0) FROM `item_liste` WHERE item_cat = 2 ;
UPDATE `item_liste` SET item_ordre = @ordre := @ordre+1, item_cat = 2 WHERE item_cat = 1 ;</code></pre>
<ol>
<li>On compte la borne supérieure de la catégorie 2. Pourquoi un <code>IFNULL</code> ? Parce <code>MAX()</code> retournera <code>NULL</code> si un des <code>item_ordre</code> en contient un. C&#8217;est une sécurité ;</li>
<li>On met à jour les éléments de la catégorie 1 avec leur nouvel ordonnancement et leur nouvelle catégorie.</li>
</ol>
<p><strong>Alors pourquoi ça fonctionne</strong> ? La commande <code>UPDATE</code> balaie les lignes <strong>une par une</strong> et du coup, <strong>met à jour la variable <code>@ordre</code> à chaque ligne</strong>. Nous retrouvons ainsi l&#8217;effet désiré : incrémenter chaque ligne déplacée dans la nouvelle catégorie.</p>
<p>Il existe des utilisations plus compliquées que celles-là mais je pense que c&#8217;est un bon départ pour se faire une idée de ce qui est faisable par ce biais là. L&#8217;imagination et les besoins feront le reste <img src='http://case.oncle-tom.net/wp-includes/images/smilies/icon_wink.gif' alt=';-)' class='wp-smiley' /> </p>
]]></content:encoded>
			<wfw:commentRss>http://case.oncle-tom.net/2007/utilisation-variables-mysql/feed/</wfw:commentRss>
		<slash:comments>9</slash:comments>
		</item>
		<item>
		<title>IN() et GROUP_CONCAT() sont dans un bateau</title>
		<link>http://case.oncle-tom.net/2007/in-et-group_concat-sont-dans-un-bateau/</link>
		<comments>http://case.oncle-tom.net/2007/in-et-group_concat-sont-dans-un-bateau/#comments</comments>
		<pubDate>Mon, 09 Apr 2007 11:00:31 +0000</pubDate>
		<dc:creator>Oncle Tom</dc:creator>
				<category><![CDATA[Développement Web]]></category>
		<category><![CDATA[astuce]]></category>
		<category><![CDATA[MySQL]]></category>
		<category><![CDATA[optimisation]]></category>
		<guid isPermaLink="false">http://case.oncle-tom.net/2007/04/09/in-et-group_concat-sont-dans-un-bateau/</guid>
		<description><![CDATA[Il m&#8217;arrive fréquemment d&#8217;avoir à sélectionner des lignes de données à partir d&#8217;un ou plusieurs critères. C&#8217;est le cas dès que l&#8217;on souhaite récupérer une liste. C&#8217;est également très pratique pour mettre à jour ces dites-lignes. Seulement voilà, des fois on pourrait éviter quelques boucles et quelques complications avec l&#8217;utilisation de deux fonctions magiques de [...]]]></description>
			<content:encoded><![CDATA[<p>Il m&#8217;arrive fréquemment d&#8217;avoir à sélectionner des lignes de données à partir d&#8217;un ou plusieurs critères. C&#8217;est le cas dès que l&#8217;on souhaite récupérer une liste. C&#8217;est également très pratique pour mettre à jour ces dites-lignes. Seulement voilà, des fois on pourrait éviter quelques boucles et quelques complications avec l&#8217;utilisation de deux fonctions magiques de MySQL : <a href="http://dev.mysql.com/doc/refman/4.1/en/comparison-operators.html">IN()</a> et <a href="http://dev.mysql.com/doc/refman/4.1/en/group-by-functions.html">GROUP_CONCAT()</a>.<br />
<span id="more-550"></span></p>
<h3>Sélection optimisée avec IN()</h3>
<p><code>IN()</code> devrait être utilisé dès lors que l&#8217;on a plusieurs critères sur un même colonne. L&#8217;écriture suivante ne devrait pas apparaitre dans votre code :</p>
<pre><code class="sql">SELECT * FROM `ma_table` WHERE id = 3 OR id = 5;</code></pre>
<p>A la place, il devrait y avoir ceci :</p>
<pre><code class="sql">SELECT * FROM `ma_table` WHERE id IN (3, 5);</code></pre>
<p>C&#8217;est une habitude à prendre car elle permettra d&#8217;automatiser bien des choses. Imaginez qu&#8217;on ne fasse plus cette sélection &laquo;&nbsp;en dur&nbsp;&raquo; mais à partir d&#8217;un tableau <acronym title="Pre-Hypertext Processing">PHP</acronym>. Trois façons d&#8217;écrire la requête, vous verrez vite laquelle sera la plus pratique à réutiliser :</p>
<pre><code class="php">
$tableau = array(3, 5);
/* Méthode 1 : vite-fait mal fait */
$separateur = '';
$sql = "SELECT * FROM `ma_table` WHERE ";
foreach( $tableau as $id )
{
	$sql .= $separateur." id = ".$id;
	$separateur = ' OR ';
}
/* Méthode 2 : utilisation "optimisée" avec des OR dans la requête */
$sql = "SELECT * FROM `ma_table` WHERE id = ".implode(' OR id = ', $tableau);
/* Méthode 3 : passe-partout */
$sql = "SELECT * FROM `ma_table` WHERE id IN (".implode(',', $tableau).")";
</code></pre>
<p>Le gros avantage de la dernière méthode c&#8217;est le retraitement des données. Il est facile et plus logique d&#8217;<a href="http://fr.php.net/implode">imploser</a> et d&#8217;<a href="http://fr.php.net/manual/fr/function.explode.php">exploser</a> une chaine composée de <em>séparateurs virgule</em> (ou autre caractère employé aux mêmes fins).</p>
<pre><code class="php">$tableau = array(3, 5);
$tableau = implode(',', $tableau);
/* du code nécessitant $tableau en tant que chaîne */
$tableau = explode(',', $tableau);
/* du code nécessitant $tableau en tant que tableau */</code></pre>
<h3>Aggrégats avec GROUP_CONCAT()</h3>
<p>Dans les exemples précédents, <code>$tableau</code> était rempli &laquo;&nbsp;en dur&nbsp;&raquo;. Dans la vraie vie, ça ne se passe pas comme ça : on récupère des identifiants (clés et/ou index) pour valider les sélections. L&#8217;exemple basique : <em>on veut mettre à jour une table de configuration avec les ID d&#8217;articles présents dans une ou plusieurs catégories</em>.</p>
<pre><code class="php">$tableau = array();
/* Sélection des ID */
$query = mysql_query("SELECT id FROM `ma_table` WHERE cat_id IN ('fromage', 'tortues');");
while( $ligne = mysql_fetch_assoc($query) )
{
	$tableau[] = $ligne['id'];
}
/* On met à jour notre table de configuration */
$tableau = implode(',', $tableau);
mysql_query("REPLACE INTO `table_config` (config_id, config_valeur) ".
	"('cache_articles', '{$tableau}')");</code></pre>
<p>C&#8217;est simple, propre et on se dit qu&#8217;on a bien bossé. Et pourtant, l&#8217;utilisation de la fonction d&#8217;agrégation <code>GROUP_CONCAT()</code> de MySQL nous épargnera quelques lignes. On appréciera :</p>
<pre><code class="php">$tableau = array();
/* Sélection des ID */
$query = mysql_query("SELECT GROUP_CONCAT(id) AS cache_articles FROM `ma_table` WHERE cat_id IN ('fromage', 'tortues');");
$tableau = mysql_fetch_assoc($query);
/* On met à jour notre table de configuration */
mysql_query("REPLACE INTO `table_config` (config_id, config_valeur) ".
	"('cache_articles', '{$tableau['cache_articles']}'");</code></pre>
<p>Bref, on a gagné une boucle (le <code>while</code>), des lignes de résultats MySQL (autant de ressources d&#8217;économisées) et un traitement <acronym title="Pre-Hypertext Processing">PHP</acronym> en moins (<code>implode</code>). Et devinez quoi ? Le résultat retourné par le <code>GROUP_CONCAT</code> s&#8217;intègre très bien dans le &#8230; <code>IN()</code>.</p>
]]></content:encoded>
			<wfw:commentRss>http://case.oncle-tom.net/2007/in-et-group_concat-sont-dans-un-bateau/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>Prenez des raccourcis</title>
		<link>http://case.oncle-tom.net/2007/prenez-des-raccourcis/</link>
		<comments>http://case.oncle-tom.net/2007/prenez-des-raccourcis/#comments</comments>
		<pubDate>Thu, 22 Feb 2007 12:00:42 +0000</pubDate>
		<dc:creator>Oncle Tom</dc:creator>
				<category><![CDATA[Développement Web]]></category>
		<category><![CDATA[astuce]]></category>
		<category><![CDATA[bonnes pratiques]]></category>
		<category><![CDATA[clavier]]></category>
		<category><![CDATA[optimisation]]></category>
		<guid isPermaLink="false">http://case.oncle-tom.net/2007/02/22/prenez-des-raccourcis/</guid>
		<description><![CDATA[Quand on utilise régulièrement les mêmes logiciels, on aime à pouvoir gagner du temps tout en se simplifiant la vie. Les seuls pré-requis sont 2 doigts et un peu de mémoire. Autant dire que tout le monde (ou presque) est concerné. Voyons ensemble 10 combinaisons de touches avec Control, facilement mémorisables. Ces combinaisons se retrouvent [...]]]></description>
			<content:encoded><![CDATA[<p>Quand on utilise régulièrement les mêmes logiciels, on aime à pouvoir gagner du temps tout en se <em>simplifiant la vie</em>. Les seuls pré-requis sont 2 doigts et un peu de mémoire. Autant dire que tout le monde (ou presque) est concerné.</p>
<p>Voyons ensemble 10 combinaisons de touches avec <kbd>Control</kbd>, facilement mémorisables. Ces combinaisons se retrouvent sur la plupart des logiciels Windows, Linux et Mac <acronym title="Operating System">OS</acronym> X à la différence près que pour ce dernier, c&#8217;est la touche <kbd>Pomme</kbd> qui interagit.<br />
<span id="more-467"></span><br />
Sur la première rangée de votre clavier :</p>
<ul>
<li><kbd>Control + A</kbd> (<strong>A</strong>ll, tous) : sélectionner tout le contenu d&#8217;une zone active (document, zone de texte etc.) ;</li>
<li><kbd>Control + Z</kbd> : annule un changement et revient à l&#8217;état précédent. Très pratique dans les éditeurs de texte pour corriger rapidement une phrase ;</li>
<li><kbd>Control + T</kbd> (<strong>T</strong>ab, onglet) : crée un nouvel onglet dans les applications gérant ce mécanisme (Firefox, Internet Explorer 7, GAIM etc.) ;</li>
</ul>
<p>Sur la deuxième rangée de votre clavier :</p>
<ul>
<li><kbd>Control + Q</kbd> (<strong>Q</strong>uit, quitter) : ferme entièrement une application ;</li>
<li><kbd>Control + S</kbd> (<strong>S</strong>ave, sauvegarder) : enregistre le document actif. <strong>Indispensable</strong> avec les éditeurs de texte ;</li>
</ul>
<p>Sur la troisième rangée de votre clavier :</p>
<ul>
<li><kbd>Control + W</kbd> (<strong>W</strong>indow, fenêtre) : ferme l&#8217;onglet actif dans les applications gérant ce mécanisme ;</li>
<li><kbd>Control + X</kbd> (<strong>Cross</strong>, Cut, couper) : coupe la sélection (texte, documents) en attendant d&#8217;être collée ;</li>
<li><kbd>Control + C</kbd> (<strong>C</strong>opy, copier) : copie la sélection (texte, documents) en attendant d&#8217;être collée ;</li>
<li><kbd>Control + V</kbd> : colle la sélection (texte, documents) ;</li>
<li><kbd>Control + N</kbd> (<strong>N</strong>ew, nouveau): crée un nouveau document au sein de l&#8217;application (fenêtre, fichier etc.).</li>
</ul>
<p>Ca peut paraître barbare à première vue et pourtant. Regardez votre clavier : ce sont systématiquement des touches placées en début de rangée et allant vers la droite. Toutes ces combinaisons s&#8217;effectuent facilement avec une seule mains et 2 doigts.<br />
Pour faire simple et efficace : appuyez sur la touche <kbd>Control</kbd> avec votre auriculaire puis sur son complément avec votre index <em>OU</em> votre majeur pour les touches les plus proches de <kbd>Control</kbd>. Ca évite les contorsions inconfortables.</p>
<p>Personnellement je préfère <strong>largement abuser</strong> du <kbd>Control + S</kbd> que faire confiance aux sauvegardes automatiques (surtout quand on connaît la capacité de <em>Microsoft Office</em> à détruire vos fichiers). Vous économisez des clics, votre poignet et du temps tout en gagnant en confort d&#8217;utilisation.</p>]]></content:encoded>
			<wfw:commentRss>http://case.oncle-tom.net/2007/prenez-des-raccourcis/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
	</channel>
</rss>

