<?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>The Tech Guy FR &#187; code</title>
	<atom:link href="http://blog.juliencrouzet.fr/tag/code/feed/" rel="self" type="application/rss+xml" />
	<link>http://blog.juliencrouzet.fr</link>
	<description>Le blog de Julien CROUZET</description>
	<lastBuildDate>Thu, 01 Jul 2010 19:38:12 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0</generator>
		<item>
		<title>Zoom sur les méthodes magiques de PHP</title>
		<link>http://blog.juliencrouzet.fr/565/les-methodes-magiques-de-php/</link>
		<comments>http://blog.juliencrouzet.fr/565/les-methodes-magiques-de-php/#comments</comments>
		<pubDate>Wed, 23 Jun 2010 01:03:11 +0000</pubDate>
		<dc:creator>c2c</dc:creator>
				<category><![CDATA[Web]]></category>
		<category><![CDATA[code]]></category>
		<category><![CDATA[geek]]></category>
		<category><![CDATA[php]]></category>

		<guid isPermaLink="false">http://blog.juliencrouzet.fr/?p=565</guid>
		<description><![CDATA[
Warning: call_user_func_array() expects parameter 1 to be a valid callback, first array member is not a valid class name or object in /home/www/blog.juliencrouzet.fr/wp-includes/plugin.php on line 166

Call Stack:
    0.0001     623440   1. {main}() /home/www/blog.juliencrouzet.fr/index.php:0
    0.0002     628968   2. require('/home/www/blog.juliencrouzet.fr/wp-blog-header.php') /home/www/blog.juliencrouzet.fr/index.php:17
    0.2053   38133272   3. require_once('/home/www/blog.juliencrouzet.fr/wp-includes/template-loader.php') /home/www/blog.juliencrouzet.fr/wp-blog-header.php:16
    0.2062   38136192   4. do_feed() /home/www/blog.juliencrouzet.fr/wp-includes/template-loader.php:14
    0.2062   38136472   5. do_action() /home/www/blog.juliencrouzet.fr/wp-includes/functions.php:1721
    0.2063   38138496   6. call_user_func_array() /home/www/blog.juliencrouzet.fr/wp-includes/plugin.php:395
    0.2063   38138552   7. do_feed_rss2() /home/www/blog.juliencrouzet.fr/wp-includes/plugin.php:0
    0.2063   38138744   8. load_template() /home/www/blog.juliencrouzet.fr/wp-includes/functions.php:1753
    0.2064   38200936   9. require_once('/home/www/blog.juliencrouzet.fr/wp-includes/feed-rss2.php') /home/www/blog.juliencrouzet.fr/wp-includes/theme.php:1087
    0.2114   38205008  10. the_excerpt_rss() /home/www/blog.juliencrouzet.fr/wp-includes/feed-rss2.php:46
    0.2316   38208544  11. apply_filters() /home/www/blog.juliencrouzet.fr/wp-includes/feed.php:177
    0.2318   38211216  12. call_user_func_array() /home/www/blog.juliencrouzet.fr/wp-includes/plugin.php:166

]]></description>
			<content:encoded><![CDATA[<div id="attachment_567" class="wp-caption aligncenter" style="width: 150px"><a href="http://blog.juliencrouzet.fr/wp-content/uploads/2010/06/025-magician-01.png" rel="lightbox[565]"><img class="size-full wp-image-567" title="025-magician-01" src="http://blog.juliencrouzet.fr/wp-content/uploads/2010/06/025-magician-01.png" alt="" width="140" height="140" /></a><p class="wp-caption-text">Abracadabra...</p></div>
<p style="text-align: center;">
<p>Les objets en PHP possèdent 14 méthodes « magiques », reconnaissables à leurs noms qui commencent par deux <em>underscores</em> « __ » : __construct, __destruct, __call, __callStatic, __get, __set, __isset, __unset, __sleep, __wakeup, __toString, __invoke, __set_state, __clone.</p>
<p>Une méthode « magique » en PHP, c’est une méthode dont le nom est réservé (vous ne pouvez pas utiliser ces noms pour appeler vos propres méthodes, d’une manière générale, ne nommez jamais une méthode avec un nom qui commence par « __ »), que le moteur PHP va tenter d’appeler dans lors de certains évènements propres à votre classe si celles-ci existe.</p>
<p>Par exemple, si vous avez une méthode appelée « __construct » dans votre classe, celle-ci sera appelée lorsque l’on instancie une instance de votre classe : <em>new MaClasse().</em></p>
<p>Dans la plupart des cas (sauf si précisé), ces méthodes doivent être définie comme publique et non statiques (ex : <em>public function __construct()</em>).</p>
<p>Voyons-les en détails …</p>
<p><span id="more-565"></span><br />
<h3>__construct</h3>
<p>La plus connue d’entre elles ; beaucoup l’utilisent sans savoir qu’il s’agit d’une méthode « magique ». __construct est ce qui s’apparente à un constructeur en C++, c’est-à-dire qu’elle est appelée à  chaque instanciation de votre objet. Par exemple, si j’appelle <em>new MaClasse(</em><code><em>"test"</em></code><em>, 5 ) ;</em>, la méthode __construct de MaClasse va être appelée avec comme argument <code>"test"</code> et 5. Il est inutile de retourner une valeur dans cette méthode, ce retour serait ignoré.</p>
<p>Par convention, on place dans la méthode __construct toutes les initialisations nécessaires à l’utilisation d’un objet, comme par exemple la connexion à une base de données, les valeurs par défaut des variables, etc.</p>
<p>A noter qu’en cas d’instanciation d’une classe fille (qui hérite de la classe), __construct ne sera pas appelé, si la classe fille (ou une des classe dans l’héritage) implémente une fonction __construct ; il faudra alors appeler <em>parent::__construct(…)</em> dans la méthode __construct de cette classe fille.</p>
<h3>__destruct</h3>
<p>__destruct est appelé lorsque qu’une instance de notre classe est détruite (elle n’est plus utilisée, ou la fin du script est arrivée par exemple), elle n’a aucun argument.</p>
<p>A l’inverse de __construct, on place dans cette méthode tout ce qui est nécessaire à la fin de vie de notre objet, comme par exemple la déconnexion d’une socket, la libération de mémoire cache, etc.</p>
<p>Attention, l’utilisation de cette méthode est souvent très sensible :</p>
<ul>
<li>Souvent, celle-ci est appelée en fin de script, c’est-à-dire à un moment ou les en-têtes (headers) sont déjà envoyés ;</li>
<li>Si une exception est levée pendant l’exécution de cette méthode, une erreur fatale PHP est levée et le reste (de la fin) du script ne sera pas exécuté ;</li>
<li>Beaucoup de ressources (instances d’autres classes, connexion à des bases de données) dont probablement déjà plus disponibles.</li>
</ul>
<h3>__call</h3>
<p>__call est appelé lorsque l’on essaye d’appeler une méthode qui n’existe pas dans la classe. Par exemple, si j’essayer d’appeler <em>$objet-&gt;fooBar(</em><code><em>"test"</em></code><em>, 5) ;</em> que <em>fooBar</em> n’est pas une méthode définie dans ma classe et que j’ai une méthode __call définie, celle-ci va être appelée avec comme arguments  <code><em>"fooBar"</em></code><code> (</code>le nom de la méthode appelée) et un tableau contenant <code><em>"test"</em></code> et<em> 5</em> (les arguments).</p>
<h3>__callStatic</h3>
<p>__callStatic fait la même chose que __call, mais est appelée lorsque l’on essaye d’appeler une méthode statique qui n’existe pas ; par exemple <em>MaClasse::fooBar(</em><code><em>"test"</em></code><em>, 5) ;</em> appellera __callStatic  avec comme arguments  <code><em>"fooBar"</em></code><code> (</code>le nom de la méthode appelée) et un tableau contenant <code><em>"test"</em></code> et<em> 5</em> (les arguments).</p>
<p>Attention, comme callStatic est appelé dans un contexte statique, il faut définir la méthode de manière publique et statique (<em>public static function __callStatic($name, $args) { </em>).</p>
<h3>__set</h3>
<p>__set est appelé lorsque l’on essaye de définir une propriété qui n’existe pas.</p>
<p>Par exemple <em>$object-&gt;fooBar = 5;</em> appellera __set  avec comme arguments  <code><em>"fooBar"</em></code><code> (</code>le nom de la propriété) et un <em>5</em> (la nouvelle valeur). Cependant, cette propriété ne sera pas créée pour autant !</p>
<p>A noter que __set est appelée lorsque l’on essaye de modifier la valeur d’une propriété privée ou protégée depuis l’extérieur de la classe.</p>
<h3>__get</h3>
<p>__get est appelé lorsque l’on essaye de récupérer la valeur d’une propriété qui n’existe pas.</p>
<p>Par exemple echo <em>$object-&gt;fooBar;</em> appellera __get  avec comme argument  <code><em>"fooBar"</em></code>. La valeur alors retournée par la méthode __get sera retournée à l’appel (<em>echo</em> dans l’exemple).</p>
<p>A noter que __get est appelée lorsque l’on essaye de récupérer la valeur d’une propriété privée ou protégée depuis l’extérieur de la classe.</p>
<h3>__isset</h3>
<p>__isset est appelé lorsque l’on essaye de savoir si une propriété qui n’existe pas est définie, avec <em>isset()</em> par exemple.</p>
<p>Par exemple  isset(<em>$object-&gt;fooBar)</em> appellera __isset  avec comme argument  <code><em>"fooBar"</em></code>. La valeur alors retournée par la méthode __get sera retournée à l’appel, celle-ci doit donc de préférence retourner <em>true</em> ou <em>false</em>.</p>
<p>A noter que __isset est appelée lorsque l’on essaye de savoir si la valeur d’une propriété privée ou protégée est définie depuis l’extérieur de la classe.</p>
<h3>__unset</h3>
<p>__unset fait à peu près la même chose que __isset, donc vous avez tout deviné … J</p>
<p><strong>__sleep et __wakeup</strong></p>
<p>Ces anciennes méthodes permettent de linéariser et délinéariser des objets d’une classe. La linéarisation permet à un objet d’être enregistré (comme par exemple dans une base de données ou une mémoire cache) dans un état défini (comprendre les valeurs des méthodes par exemple). Ceci peut être très utile par exemple si l’on veut enregistrer un objet de session.</p>
<p>Par défaut, les objets linéarisés le sont à l’aide de la fonction serialize() de PHP, mais cela peut s’avérer insuffisant, comme par exemple si l’on doit avant se déconnecter d’une base de données ou faire du nettoyage.</p>
<p>Deux méthodes magiques existent pour cela, __sleep et __wakeup, mais il est fortement déconseillé de les utiliser car il est impossible alors d’accéder au nom des propriétés privées ou protégées des classes parentes, il faut alors utiliser l’interface Serializable. Ce n’est pas une méthode magique, mais elle les « remplace », je vais donc en parler ici.</p>
<p>Serializable définit deux méthodes : serialize et unserialize :</p>
<ul>
<li>serialize() est appelé lorsque l’on appelle la fonction PHP <em>serialize($objet)</em> ;. Elle doit alors retourner une chaîne qui pourra être récupérée pour réinitialiser l’objet dans l’état actuel ;</li>
<li>unserialize($string) est appelé lorsque l’on appelle la fonction PHP $object = <em>unserialize($string)</em> ;. Elle doit alors récupérer la chaîne $string pour réinitialiser l’objet dans l’état décrit par celle-ci. Dans ce cas, $object sera alors une instance de la classe réinitialisé, mais <em>__construct()</em> ne sera pas appelé. Elle doit modifier l’objet mais ne rien retourner (comme __construct).</li>
</ul>
<p>Voici un exemple de classe pour être plus clair :</p>
<pre name="code" class="php">
/**
 * Classe mere
 */
class					Compteur {
	/**
	 * Somme
	 *
	 * @var	int
	 */
	protected			$_sum;
}
/**
 * Une classe tout bête qui compte le nombre de fois
 * qu'on l'a appelée et fait une somme
 */
class					CompteurBete extends Compteur implements Serializable {
	/**
	 * Nombre de fois qu'on l'a appellé
	 *
	 * @var	int
	 */
	private				$_calls;	

	/**
	 * Constructeur
	 */
	public function		__construct() {
		$this->_sum = 0;
		$this->_calls = 0;
		echo "Constructeur appellé !\n";
	}
	/**
	 * On ajoute un nombre a la somme
	 *
	 * @param	int			Nombre
	 */
	public function			add($number) {
		$this->_sum += intval($number);
		$this->_calls++;
	}
	/**
	 * Quelle est la somme ?
	 *
	 * @return	int
	 */
	public function			getSum() {
		return($this->_sum);
	}
	/**
	 * Combien de fois ai-je été appelé
	 *
	 * @return	int
	 */
	public function			getCalls() {
		return($this->_calls);
	}
	/**
	 * La méthode qui fait la sérialisation
	 *
	 * @return	string		Chaîne qui représente l'état de l'objet
	 */
	public function			serialize() {
		return("{$this->_sum}|{$this->_calls}");
	}
	/**
	 * La méthode qui réinitialise l'objet dans l'état sérialisé
	 *
	 * @param	string		Chaîne retournée par serialize()
	 */
	public function			unserialize($serialized) {
		if (preg_match("/^([\-\d]+)\|([\-\d]+)$/", $serialized, $parts)) {
			$this->_sum = intval($parts[1]);
			$this->_calls = intval($parts[2]);
		} else {
			throw new Exception("La chaîne ne représente pas une instance de CompteurBete : " . $serialized);
		}
	}
}
</pre>
<p>Si on exécute le code suivant :</p>
<pre name="code" class="php">
/**
 * On cree notre objet
 */
$object = new CompteurBete();
/**
 * On joue avec
 */
$object->add(5);
$object->add(10);
$object->add(-25);
/**
 * On le serialize
 */
$serialized = serialize($object);

echo "Nombre d'appels : " . $object->getCalls() . "\n";
echo "Somme : " . $object->getSum() . "\n";
echo "Chaîne sérialisée : " . $serialized . "\n";
</pre>
<p>On obtient le résultat :</p>
<pre name="code" class="php">
Constructeur appellé !
Nombre d'appels : 3
Somme : -10
Chaîne sérialisée : C:12:"CompteurBete":5:{-10|3}
</pre>
<p>La chaîne « <em>C:12:&nbsp;&raquo;CompteurBete&nbsp;&raquo;:5:{-10|3}</em> » peut être traduite par « Une instance de la classe &laquo;&nbsp;CompteurBete&nbsp;&raquo; que l’on peut désérialiser avec la chaîne  &laquo;&nbsp;{-10|3}&nbsp;&raquo; ».</p>
<p>Donc si l’on exécute maintenant le code :</p>
<pre name="code" class="php">
/**
 * On passe la chaîne récupérée
 */
$newObject = unserialize('C:12:"CompteurBete":5:{-10|3}');
echo "Nombre d'appels : " . $object->getCalls() . "\n";
echo "Somme : " . $object->getSum() . "\n";
</pre>
<p>On obtient :</p>
<pre name="code" class="php">
Nombre d'appels : 3
Somme : -10
Magnifique ! Le même résultat ! Notre objet est donc bien réinitialisé !
</pre>
<p>Vous noterez que j’ai « implémenté » un système maison de sérialisation/désérialisation maison mais il est souvent préférable de se baser sur des systèmes tels que <em>serialize()/unserialize()</em> de PHP…</p>
<h3>__toString</h3>
<p>__toString est appelé lorsque l’on essaye d’utiliser une classe comme une chaîne de caractères, par exemple lorsque l’on appelle <em>echo $object ;</em>.La méthode __toString est alors appelée, sans argument, et doit retourner une chaîne qui sera à son tour retournée à l’appelant.</p>
<p>C’est très utile lorsque l’on crée des classes qui représentent des balises HTML, on peut alors travailler avec ces classes avec des appels du type :</p>
<pre name="code" class="php">
$tag = new HTMLTag('ul');
$tag->setClass('maClasse')->setId('monId')->html('Hello');
echo $tag;  // Va afficher
<ul class="maClasse" id="monId">Hello</ul>
</pre>
<h3>__invoke</h3>
<p>__invoke est appelé lorsque l’on essaye d’appeler un objet comme une fonction. Par exemple, si l’on effectue <em>$object(&laquo;&nbsp;buuum&nbsp;&raquo;) ;</em>, la méthode __invoke va être appelée avec comme argument <em>&laquo;&nbsp;buuum&nbsp;&raquo;</em>.</p>
<p>Cela peut être utile notamment lorsque l’on souhaite utiliser une fonction de PHP qui utilise une fonction comme argument, comme <em>usort()</em>, à laquelle on peut passer comme argument l’objet.</p>
<p>A noter, pour tester si une instance d’une classe implémente __invoke, on peut utiliser <em>is_callable()</em>.</p>
<h3>__set_state</h3>
<p>__set_state est un peu complexe à définir, et à mon avis pas très utile, mais essayons quand même. Pour comprendre __set_state, il faut d’abord connaitre la fonction PHP <em>var_export()</em>.<em>var_export()</em> c’est le même principe que <em>var_dump()</em>, c’est-à-dire afficher des informations sur une variable, mais avec deux différences :</p>
<ul>
<li>· var_export peut retourner les infos plutôt que de les afficher si on précise <em>true</em> en deuxième argument ;</li>
<li>· var_export retourne du code PHP valide.</li>
</ul>
<p>Si l’on prend le code suivant par exemple :</p>
<pre name="code" class="php">
$number = 5;
$string = "ouech";
$array = array(1, "t'as vu", false);
class test {
	public				$property = 5;
	private				$_property = "ok";
	public function		method() { /**/ }
}
$object = new test();
echo var_export($number) . "\n";
echo var_export($string) . "\n";
echo var_export($array) . "\n";
echo var_export($object) . "\n";
</pre>
<p>On obtient le résultat suivant :</p>
<pre name="code" class="php">
5
'ouech'
array (
	0 =&gt; 1,
	1 =&gt; 't\'as vu',
	2 =&gt; false,
)
test::__set_state(array(
	'property' =&gt; 5,
	'_property' =&gt; 'ok',
))
</pre>
<p>Penchons-nous donc sur le dernier résultat, concernant l’objet. <em>var_export()</em> retourne un code qui est un appel à une méthode __set_state sur la classe <em>test</em>. On y est dont, à cette méthode.</p>
<p>En fait, cette méthode prend en argument un tableau qui représente la liste des propriétés de l’instance de la classe. La méthode doit normalement récupérer créer une instance de la classe, assigner les propriétés récupérées et retourner cet objet, afin de pouvoir faire quelque chose comme <em>eval(‘$newInstance =’ . var_export($oldInstance, true) . ‘;’) ;</em></p>
<p>Donc :</p>
<ul>
<li>· La méthode __set_state est une méthode publique statique, on a donc pas accès aux propriétés protégées et publique de l’objet qu’on doit réinitialiser, il faut donc faire des méthodes « setter » ;</li>
<li>· C’est ignoble, immonde et lent comme code (et oui eval()…) ;</li>
<li>· C’est pas très sécurisé, voire pas du tout (et oui eval()…) ;</li>
<li>· La méthode peut en fait faire n’importe quoi et retourner n’importe quoi…</li>
</ul>
<p>Si quelqu’un à compris quelle est l’utilité de __set_state, donc, qu’il se manifeste !</p>
<h3>__clone</h3>
<p>__clone est appelé lorsque l’on souhaite cloner une instance de la classe avec la fonction PHP <em>clone()</em>. En effet, on peut dans certains cas vouloir contrôler le clonage d’une instance de notre classe pour par exemple partager des ressources (base de données, etc.), voir l’empecher.</p>
<p>Lorsque l’on appelle clone() sur un objet et que la méthode __clone est implémentée, celle-ci sera invoquée alors sur le nouvel objet cloné juste après sa création.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.juliencrouzet.fr/565/les-methodes-magiques-de-php/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Rendez vos textarea sexy avec tx-content-assist</title>
		<link>http://blog.juliencrouzet.fr/558/rendez-vos-textarea-sexy-avec-tx-content-assist/</link>
		<comments>http://blog.juliencrouzet.fr/558/rendez-vos-textarea-sexy-avec-tx-content-assist/#comments</comments>
		<pubDate>Tue, 22 Jun 2010 14:02:28 +0000</pubDate>
		<dc:creator>c2c</dc:creator>
				<category><![CDATA[Web]]></category>
		<category><![CDATA[code]]></category>
		<category><![CDATA[javascript]]></category>

		<guid isPermaLink="false">http://blog.juliencrouzet.fr/?p=558</guid>
		<description><![CDATA[
Warning: call_user_func_array() expects parameter 1 to be a valid callback, first array member is not a valid class name or object in /home/www/blog.juliencrouzet.fr/wp-includes/plugin.php on line 166

Call Stack:
    0.0001     623440   1. {main}() /home/www/blog.juliencrouzet.fr/index.php:0
    0.0002     628968   2. require('/home/www/blog.juliencrouzet.fr/wp-blog-header.php') /home/www/blog.juliencrouzet.fr/index.php:17
    0.2053   38133272   3. require_once('/home/www/blog.juliencrouzet.fr/wp-includes/template-loader.php') /home/www/blog.juliencrouzet.fr/wp-blog-header.php:16
    0.2062   38136192   4. do_feed() /home/www/blog.juliencrouzet.fr/wp-includes/template-loader.php:14
    0.2062   38136472   5. do_action() /home/www/blog.juliencrouzet.fr/wp-includes/functions.php:1721
    0.2063   38138496   6. call_user_func_array() /home/www/blog.juliencrouzet.fr/wp-includes/plugin.php:395
    0.2063   38138552   7. do_feed_rss2() /home/www/blog.juliencrouzet.fr/wp-includes/plugin.php:0
    0.2063   38138744   8. load_template() /home/www/blog.juliencrouzet.fr/wp-includes/functions.php:1753
    0.2064   38200936   9. require_once('/home/www/blog.juliencrouzet.fr/wp-includes/feed-rss2.php') /home/www/blog.juliencrouzet.fr/wp-includes/theme.php:1087
    0.2531   38225232  10. the_excerpt_rss() /home/www/blog.juliencrouzet.fr/wp-includes/feed-rss2.php:46
    0.2545   38227920  11. apply_filters() /home/www/blog.juliencrouzet.fr/wp-includes/feed.php:177
    0.2548   38230408  12. call_user_func_array() /home/www/blog.juliencrouzet.fr/wp-includes/plugin.php:166

]]></description>
			<content:encoded><![CDATA[<div id="attachment_559" class="wp-caption aligncenter" style="width: 290px"><a href="http://blog.juliencrouzet.fr/wp-content/uploads/2010/06/2010-06-22_1558.png" rel="lightbox[558]"><img class="size-full wp-image-559" title="tx-content-assist" src="http://blog.juliencrouzet.fr/wp-content/uploads/2010/06/2010-06-22_1558.png" alt="" width="280" height="113" /></a><p class="wp-caption-text">Classe !</p></div>
<p style="text-align: left;">
<p style="text-align: left;">Pouvoir faire de la complétion dans un &lt;textarea&gt;, c&#8217;est possible, avec <a href="http://github.com/sergeche/tx-content-assist/">tx-content-assist</a>, c&#8217;est possible !</p>
<p style="text-align: left;">C&#8217;est en fait une réécriture du moteur d&#8217;assistance de code de Eclipse, et c&#8217;est même possible de le déclencher avec &laquo;&nbsp;Ctrl+Espace&nbsp;&raquo; / &laquo;&nbsp;Alt + Espace&nbsp;&raquo; (enfin, certains navigateurs l&#8217;ont déjà reservé).</p>
<p style="text-align: left;">Pour une petite démo, c&#8217;est par <a href="http://media.chikuyonok.ru/content-assist/">ici</a>, pour les sources, c&#8217;est sur <a href="http://github.com/sergeche/tx-content-assist/">github</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.juliencrouzet.fr/558/rendez-vos-textarea-sexy-avec-tx-content-assist/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>redis : Le système de cache parfait</title>
		<link>http://blog.juliencrouzet.fr/484/redis-le-systeme-de-cache-parfait/</link>
		<comments>http://blog.juliencrouzet.fr/484/redis-le-systeme-de-cache-parfait/#comments</comments>
		<pubDate>Sat, 29 Aug 2009 17:11:14 +0000</pubDate>
		<dc:creator>c2c</dc:creator>
				<category><![CDATA[cache]]></category>
		<category><![CDATA[code]]></category>
		<category><![CDATA[geek]]></category>
		<category><![CDATA[Tech]]></category>

		<guid isPermaLink="false">http://blog.juliencrouzet.fr/?p=484</guid>
		<description><![CDATA[
Warning: call_user_func_array() expects parameter 1 to be a valid callback, first array member is not a valid class name or object in /home/www/blog.juliencrouzet.fr/wp-includes/plugin.php on line 166

Call Stack:
    0.0001     623440   1. {main}() /home/www/blog.juliencrouzet.fr/index.php:0
    0.0002     628968   2. require('/home/www/blog.juliencrouzet.fr/wp-blog-header.php') /home/www/blog.juliencrouzet.fr/index.php:17
    0.2053   38133272   3. require_once('/home/www/blog.juliencrouzet.fr/wp-includes/template-loader.php') /home/www/blog.juliencrouzet.fr/wp-blog-header.php:16
    0.2062   38136192   4. do_feed() /home/www/blog.juliencrouzet.fr/wp-includes/template-loader.php:14
    0.2062   38136472   5. do_action() /home/www/blog.juliencrouzet.fr/wp-includes/functions.php:1721
    0.2063   38138496   6. call_user_func_array() /home/www/blog.juliencrouzet.fr/wp-includes/plugin.php:395
    0.2063   38138552   7. do_feed_rss2() /home/www/blog.juliencrouzet.fr/wp-includes/plugin.php:0
    0.2063   38138744   8. load_template() /home/www/blog.juliencrouzet.fr/wp-includes/functions.php:1753
    0.2064   38200936   9. require_once('/home/www/blog.juliencrouzet.fr/wp-includes/feed-rss2.php') /home/www/blog.juliencrouzet.fr/wp-includes/theme.php:1087
    0.2591   38229136  10. the_excerpt_rss() /home/www/blog.juliencrouzet.fr/wp-includes/feed-rss2.php:46
    0.2650   38231752  11. apply_filters() /home/www/blog.juliencrouzet.fr/wp-includes/feed.php:177
    0.2653   38234168  12. call_user_func_array() /home/www/blog.juliencrouzet.fr/wp-includes/plugin.php:166

]]></description>
			<content:encoded><![CDATA[<div id="attachment_485" class="wp-caption aligncenter" style="width: 171px"><a href="http://blog.juliencrouzet.fr/wp-content/uploads/2009/08/bolt.jpg" rel="lightbox[484]"><img class="size-medium wp-image-485" title="bolt" src="http://blog.juliencrouzet.fr/wp-content/uploads/2009/08/bolt-300x243.jpg" alt="Il les surpasse tous !" width="161" height="131" /></a><p class="wp-caption-text">Il les surpasse tous !</p></div>
<p>Après 3 ans d&#8217;une histoire d&#8217;amour fidèle avec <a href="http://www.danga.com/memcached/">Memcached</a> ; le serveur de cache notamment utilisé par <a href="http://www.facebook.com/note.php?note_id=39391378919">Facebook</a>, <a href="http://video.google.com/videoplay?docid=-6304964351441328559">Youtube</a> ou <a href="http://blog.twitter.com/2008/05/its-not-rocket-science-but-its-our-work.html">Twitter </a>; je suis au bord de la rupture après avoir rencontré <a href="http://code.google.com/p/redis/">redis</a>.<br />
<span id="more-484"></span></p>
<h2>redis, A persistent key-value <em>database</em></h2>
<p>Oui, <strong>database</strong>. En fait, redis, c&#8217;est les avantage d&#8217;un système de cache sans les inconvénients.</p>
<p>D&#8217;habitude avec les systèmes de caches comme Memcached, les données mises en cache sont volatiles. Elles sont stockées en mémoire pendant un certain temps ; passé ce délais elles sont supprimées.</p>
<p>Ce point n&#8217;est pas bloquant, une données mise en cache doit pouvoir être recalculée ou récupérée à tout moment, mais cela consomme des ressources en plus (pour récupérer cette donnée, justement).</p>
<p><a href="http://code.google.com/p/redis/">redis</a> est conçu sur un autre modèle. Les données sont dans un premier temps stockées en mémoire de la même manière que les autres, mais elles sont de manière cycliques (tout les X écritures ou après X temps) écrites sur le disque dur. On peut donc stocker une donnée de manière permanente !</p>
<p>A noter cependant que Memcache existe en version persistante (<a href="http://memcachedb.org/">MemcachedDB</a>), cependant on il ne fait QUE du stockage persistant, on perd donc en performance.</p>
<h2>Des performances impressionnantes</h2>
<p>Afin de comparer les performances de Memcached, réputé et reconnu pour sa rapidité, et celles de redis, j&#8217;ai fait un simple test pour Memcache :</p>
<p>Et pour redis :</p>
<p>Résultat : Avec redis on est en moyenne à 2,507 secondes pour 10 000 itérations, pour Memcached on est à 3,669 secondes.</p>
<p>redis est donc plus rapides que Memcached sur des opérations de bases (écriture, lecture) il fallait le faire !</p>
<p>Sinon pour être un peu plus complet, une page de <a href="http://code.google.com/p/redis/wiki/Benchmarks">benchmark </a>est présente sur le site.</p>
<h2>Au delà du stockage <em>&laquo;&nbsp;clé-chaîne&nbsp;&raquo;</em></h2>
<p>Un autre inconvénient de Memcached ou d&#8217;autres système de cache, c&#8217;est qu&#8217;il fonctionne sur un modèle &laquo;&nbsp;<em>clé-chaîne de caractère</em>&laquo;&nbsp;, il ne peut donc stocker que des combinaisons du type (&#8216;clé de cache&#8217;, &#8216;valeur à stocker&#8217;).</p>
<p>Lorsque l&#8217;on doit enregistrer des données plus complexes comme des tableaux, on est alors obligé de passer par une mécanique de <a href="http://fr.wikipedia.org/wiki/S%C3%A9rialisation">sérialisation des données ou Mashalling</a>, comme <a href="http://fr3.php.net/serialize">serialize</a>() en PHP.</p>
<p>redis permet en plus du mode de stockage &laquo;&nbsp;<em>clé-chaîne</em>&nbsp;&raquo; un mode de stockage &laquo;&nbsp;<em>clé-liste</em>&nbsp;&raquo; qui permet de stocker des listes. Il est donc possible, au delà de stocker et récupérer des valeurs, d&#8217;utiliser les fonctions classiques de listes, comme changer une valeur dans cette liste, récupérer une valeur ou un ensemble de valeur dans la liste, la modifier etc. et ce sans avoir à récupérer la liste, la modifier et la renvoyer comme c&#8217;est le cas avec les autres systèmes.</p>
<p>Ceci est un gain énorme de ressources système et de temps tout en simplifiant la gestion du cache !</p>
<h2>Multiple bases de donnée</h2>
<p>Un même serveur de cache peut être utilisé par plusieurs systèmes de cache. Souvent cela est problématique car les données ne sont pas séparées par application. On utilise alors souvent un système de préfixage des clés, par exemple la clé &#8216;UsersCount&#8217; sera nommée &#8216;MyApplication_UsersCount&#8217; pour éviter d&#8217;écraser une clé d&#8217;une autre application.</p>
<p>redis offre une gestion par &laquo;&nbsp;base de donnée&nbsp;&raquo; comme le font les base de données classiques ; ce qui permet entre autre de vider le cache d&#8217;une application sans effacer les autres données ou de lister rapidement les données en cache d&#8217;une application donnée.</p>
<h2>Implémentation langages</h2>
<p>Pour utiliser redis il existe des libraries ou classe en Ruby, Python, PHP, Perl, Java, etc. ; la liste est présente sur le <a href="http://code.google.com/p/redis/">site du projet</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.juliencrouzet.fr/484/redis-le-systeme-de-cache-parfait/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Adoptez une ligne de code !</title>
		<link>http://blog.juliencrouzet.fr/458/adoptez-une-ligne-de-code/</link>
		<comments>http://blog.juliencrouzet.fr/458/adoptez-une-ligne-de-code/#comments</comments>
		<pubDate>Mon, 03 Aug 2009 11:53:23 +0000</pubDate>
		<dc:creator>c2c</dc:creator>
				<category><![CDATA[Web]]></category>
		<category><![CDATA[code]]></category>
		<category><![CDATA[open source]]></category>
		<category><![CDATA[video]]></category>

		<guid isPermaLink="false">http://blog.juliencrouzet.fr/?p=458</guid>
		<description><![CDATA[
Warning: call_user_func_array() expects parameter 1 to be a valid callback, first array member is not a valid class name or object in /home/www/blog.juliencrouzet.fr/wp-includes/plugin.php on line 166

Call Stack:
    0.0001     623440   1. {main}() /home/www/blog.juliencrouzet.fr/index.php:0
    0.0002     628968   2. require('/home/www/blog.juliencrouzet.fr/wp-blog-header.php') /home/www/blog.juliencrouzet.fr/index.php:17
    0.2053   38133272   3. require_once('/home/www/blog.juliencrouzet.fr/wp-includes/template-loader.php') /home/www/blog.juliencrouzet.fr/wp-blog-header.php:16
    0.2062   38136192   4. do_feed() /home/www/blog.juliencrouzet.fr/wp-includes/template-loader.php:14
    0.2062   38136472   5. do_action() /home/www/blog.juliencrouzet.fr/wp-includes/functions.php:1721
    0.2063   38138496   6. call_user_func_array() /home/www/blog.juliencrouzet.fr/wp-includes/plugin.php:395
    0.2063   38138552   7. do_feed_rss2() /home/www/blog.juliencrouzet.fr/wp-includes/plugin.php:0
    0.2063   38138744   8. load_template() /home/www/blog.juliencrouzet.fr/wp-includes/functions.php:1753
    0.2064   38200936   9. require_once('/home/www/blog.juliencrouzet.fr/wp-includes/feed-rss2.php') /home/www/blog.juliencrouzet.fr/wp-includes/theme.php:1087
    0.2737   38234680  10. the_excerpt_rss() /home/www/blog.juliencrouzet.fr/wp-includes/feed-rss2.php:46
    0.2748   38237224  11. apply_filters() /home/www/blog.juliencrouzet.fr/wp-includes/feed.php:177
    0.2750   38239608  12. call_user_func_array() /home/www/blog.juliencrouzet.fr/wp-includes/plugin.php:166

]]></description>
			<content:encoded><![CDATA[<div id="attachment_459" class="wp-caption aligncenter" style="width: 206px"><a href="http://blog.juliencrouzet.fr/wp-content/uploads/2009/07/miro-logo.png" rel="lightbox[458]"><img class="size-full wp-image-459" title="miro-logo" src="http://blog.juliencrouzet.fr/wp-content/uploads/2009/07/miro-logo.png" alt="Adoptez une ligne de code de Miro !" width="196" height="79" /></a><p class="wp-caption-text">Adoptez une ligne de code de Miro !</p></div>
<p>Les projets Open Source et gratuits ont souvent du mal à se financer, et souvent en arrivent au même point : la cyber-quête !</p>
<p>Le player Open Source <a href="http://www.getmiro.com/">Miro</a> n&#8217;échappe pas à la règle mais propose une méthode assez originale : il vous est proposé d&#8217;<a href="https://www.getmiro.com/adopt/">adopter une ligne de code</a> du player. Sympa non ?</p>
<p>J&#8217;ai personnellement adopté <a href="http://getmiro.com/adopt/adoptee/388/4745d0/">January</a> <img src='http://blog.juliencrouzet.fr/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
]]></content:encoded>
			<wfw:commentRss>http://blog.juliencrouzet.fr/458/adoptez-une-ligne-de-code/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>Aptana Studio : Retour d&#039;expérience</title>
		<link>http://blog.juliencrouzet.fr/460/aptana-studio-retour-dexperience/</link>
		<comments>http://blog.juliencrouzet.fr/460/aptana-studio-retour-dexperience/#comments</comments>
		<pubDate>Mon, 03 Aug 2009 09:54:47 +0000</pubDate>
		<dc:creator>c2c</dc:creator>
				<category><![CDATA[aptana]]></category>
		<category><![CDATA[code]]></category>
		<category><![CDATA[ide]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[Tech]]></category>

		<guid isPermaLink="false">http://blog.juliencrouzet.fr/?p=460</guid>
		<description><![CDATA[
Warning: call_user_func_array() expects parameter 1 to be a valid callback, first array member is not a valid class name or object in /home/www/blog.juliencrouzet.fr/wp-includes/plugin.php on line 166

Call Stack:
    0.0001     623440   1. {main}() /home/www/blog.juliencrouzet.fr/index.php:0
    0.0002     628968   2. require('/home/www/blog.juliencrouzet.fr/wp-blog-header.php') /home/www/blog.juliencrouzet.fr/index.php:17
    0.2053   38133272   3. require_once('/home/www/blog.juliencrouzet.fr/wp-includes/template-loader.php') /home/www/blog.juliencrouzet.fr/wp-blog-header.php:16
    0.2062   38136192   4. do_feed() /home/www/blog.juliencrouzet.fr/wp-includes/template-loader.php:14
    0.2062   38136472   5. do_action() /home/www/blog.juliencrouzet.fr/wp-includes/functions.php:1721
    0.2063   38138496   6. call_user_func_array() /home/www/blog.juliencrouzet.fr/wp-includes/plugin.php:395
    0.2063   38138552   7. do_feed_rss2() /home/www/blog.juliencrouzet.fr/wp-includes/plugin.php:0
    0.2063   38138744   8. load_template() /home/www/blog.juliencrouzet.fr/wp-includes/functions.php:1753
    0.2064   38200936   9. require_once('/home/www/blog.juliencrouzet.fr/wp-includes/feed-rss2.php') /home/www/blog.juliencrouzet.fr/wp-includes/theme.php:1087
    0.2792   38238584  10. the_excerpt_rss() /home/www/blog.juliencrouzet.fr/wp-includes/feed-rss2.php:46
    0.2855   38241240  11. apply_filters() /home/www/blog.juliencrouzet.fr/wp-includes/feed.php:177
    0.2857   38243696  12. call_user_func_array() /home/www/blog.juliencrouzet.fr/wp-includes/plugin.php:166

]]></description>
			<content:encoded><![CDATA[<div id="attachment_461" class="wp-caption aligncenter" style="width: 114px"><a href="http://blog.juliencrouzet.fr/wp-content/uploads/2009/08/aptana.png" rel="lightbox[460]"><img class="size-full wp-image-461" title="aptana" src="http://blog.juliencrouzet.fr/wp-content/uploads/2009/08/aptana.png" alt="Retour d&quot;expérience sur Aptana Studio" width="104" height="104" /></a><p class="wp-caption-text"> Aptana Studio</p></div>
<p>Un <a href="http://fr.wikipedia.org/wiki/Environnement_de_d%C3%A9veloppement_int%C3%A9gr%C3%A9">I.D.E.</a> pour un développeur, c&#8217;est l&#8217;une des choses primordiales. C&#8217;est une façon de travailler, des habitudes de développement et souvent, c&#8217;est presque une impératif. Bien sur, certains diront qu&#8217;un vrai développeur peut travailler avec n&#8217;importe lequel et c&#8217;est souvent vrai, mais avouons-le, nous avons tous nos petites habitudes !</p>
<p>Depuis quelques années, je travaillais avec <a href="http://www.zend.com/fr/products/studio">Zend Studio</a>, que j&#8217;avais adopté plus par contrainte de mon employeur au début, mais depuis l&#8217;évolution de celui-ci vers <a href="http://fr.wikipedia.org/wiki/Eclipse_%28logiciel%29">Eclipse</a>, j&#8217;avais lâché le train en route n&#8217;ayant le temps de m&#8217;y mettre et je suis resté cloitré sur l&#8217;ancienne version (5.2), que certes je maitrisais jusqu&#8217;au bout des menus, mais commençait sérieusement à vieillir.</p>
<p>J&#8217;ai donc décidé d&#8217;essayer <a href="http://www.aptana.com/">Aptana Studio</a>, dont on me parlait en bien depuis quelque temps et qui sur le papier, me séduisait fortement.</p>
<p>Après 1 mois, voici mes retours d&#8217;expérience.</p>
<p><span id="more-460"></span></p>
<h2>Ce que j&#8217;ai aimé :</h2>
<h3>Le support de jQuery</h3>
<p>Aptana est livré avec le support prépackagé de plusieurs librairies / frameworks Javascripts, dont jQuery.</p>
<p>A la clé, des templates de codes, de la complétion, de la coloration syntaxique adaptée, et caetera.</p>
<h3>Le support de Smarty</h3>
<p>Je suis depuis plusieurs années, un gran fan de <a href="http://www.smarty.net/">Smarty </a>(non pas les bonbons, quoique), que je continues à utiliser comme Vue dans mes développements <a href="http://fr.wikipedia.org/wiki/Mod%C3%A8le-Vue-Contr%C3%B4leur">MVC </a>sur Zend Framework.</p>
<p>Et la, encore une exclusivité, Aptana Studio nous offre un complétion de code, un coloration syntaxique et tout le toutim pour les fichiers de gabarits smarty, y compris sur vos propres fonctions !</p>
<h3>En bref, les complétions multilangage</h3>
<p>En plus des deux éléments cités, Aptana Studio offre une complétion très bien faite sur tout ce qui est possible : HTML, PHP, XML, JSON, CSS, etc. Et ca marche plutôt bien !</p>
<h2>Ce que je n&#8217;ai pas aimé :</h2>
<h3>Des bugs en pagaille dans le formatage</h3>
<p>Au fur et à mesure que je configurais des fonctionnalités, j&#8217;ai eu de plus en plus de fil à retordre avec des bugs, plus ou moins génants.</p>
<p>Le plus embêtants se trouvent au niveau du formatage de code. Aptana Studio, comme la plupart des I.D.E. basés sur Eclipse vous propose de formater votre code selon les règles que vous avez configurées, comme les retour à la ligne, les indentations, les espaces après les virgules, etc.</p>
<p>Force est de constater que par exemple, les retours à la ligne dans la déclarations de tableaux (array()) ou ceux des déclarations CSS qui commencent par un identifiant (#monDiv .maClasse) ont des comportements complètement aléatoire !</p>
<h3>Des bugs aussi dans la gestion &laquo;&nbsp;remote&nbsp;&raquo;</h3>
<p>Eclipse (ce n&#8217;est qu&#8217;un point de vue&#8230;) n&#8217;est pas pratique pour développer &#8216;en remote&#8217; ; c&#8217;est à dire que vous modifiez et testez sur un serveur distant via FTP ou SFTP par exemple.</p>
<p>Un bout de scotch est malgré tout là pour parer à cette problématique dans Aptana c&#8217;est un petit script bien nommé &laquo;&nbsp;Upload file on save&nbsp;&raquo; qui est censé envoyer vos fichiers via FTP / SFTP lorsque vous les sauvegarder.</p>
<p>Première mauvaise impression : il faut modifier le script pour l&#8217;activer !</p>
<p>Deuxième : il ne marche pas une fois sur trois, et tout est désynchronisé.</p>
<h3>Des fonctionnalités mal finies</h3>
<p>J&#8217;ai été impressionné lorsque j&#8217;ai vu un onglet &laquo;&nbsp;iPhone view&nbsp;&raquo;. Pensez donc ! Un émulateur iPhone intégré à un I.D.E !</p>
<p>En fait, il ne s&#8217;agit que d&#8217;une preview HTML de votre navigateur classique rétrécie au dimensions du mobile et entourée d&#8217;une photo d&#8217;iPhone &#8230; arf !</p>
<h3>Une complétion PHP de votre projet mal pensée</h3>
<p>Si vous souhaitez avoir une complétion sur vos propre classes (évidemment !) en PHP. Beaucoup de manipulations nécessaires : il va falloir définir la nature primaire de votre projet en PHP et ajoutez les répertoires ou sont vos classes dans une liste. Et ce pour chaque projet.</p>
<p>Bien sur, il va falloir après à la main les supprimer, sinon vous atteindrez les 45 secondes à l&#8217;ouverture de chaque projet des les 5 projets (~ 1 Mo de code) atteint &#8230;</p>
<h2>Conclusion</h2>
<p>Malgré une première impression, Aptana Studio semble très utile, très prometteur, mais pas assez stable et mature pour que je l&#8217;adopte. Dommage.</p>
<p>Je vais maintenant me pencher sérieusement sur <a href="http://www.zend.com/fr/products/studio/">Zend Studio 7</a> (qui gère PHP5.3 !)&#8230; Retours dans quelques semaine, sauf incident majeur <img src='http://blog.juliencrouzet.fr/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /> </p>
]]></content:encoded>
			<wfw:commentRss>http://blog.juliencrouzet.fr/460/aptana-studio-retour-dexperience/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Le DOM, c&#039;est le bordel !</title>
		<link>http://blog.juliencrouzet.fr/277/le-dom-cest-le-bordel/</link>
		<comments>http://blog.juliencrouzet.fr/277/le-dom-cest-le-bordel/#comments</comments>
		<pubDate>Mon, 09 Mar 2009 11:13:09 +0000</pubDate>
		<dc:creator>c2c</dc:creator>
				<category><![CDATA[code]]></category>
		<category><![CDATA[geek]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[Tech]]></category>

		<guid isPermaLink="false">http://blog.juliencrouzet.fr/?p=277</guid>
		<description><![CDATA[
Warning: call_user_func_array() expects parameter 1 to be a valid callback, first array member is not a valid class name or object in /home/www/blog.juliencrouzet.fr/wp-includes/plugin.php on line 166

Call Stack:
    0.0001     623440   1. {main}() /home/www/blog.juliencrouzet.fr/index.php:0
    0.0002     628968   2. require('/home/www/blog.juliencrouzet.fr/wp-blog-header.php') /home/www/blog.juliencrouzet.fr/index.php:17
    0.2053   38133272   3. require_once('/home/www/blog.juliencrouzet.fr/wp-includes/template-loader.php') /home/www/blog.juliencrouzet.fr/wp-blog-header.php:16
    0.2062   38136192   4. do_feed() /home/www/blog.juliencrouzet.fr/wp-includes/template-loader.php:14
    0.2062   38136472   5. do_action() /home/www/blog.juliencrouzet.fr/wp-includes/functions.php:1721
    0.2063   38138496   6. call_user_func_array() /home/www/blog.juliencrouzet.fr/wp-includes/plugin.php:395
    0.2063   38138552   7. do_feed_rss2() /home/www/blog.juliencrouzet.fr/wp-includes/plugin.php:0
    0.2063   38138744   8. load_template() /home/www/blog.juliencrouzet.fr/wp-includes/functions.php:1753
    0.2064   38200936   9. require_once('/home/www/blog.juliencrouzet.fr/wp-includes/feed-rss2.php') /home/www/blog.juliencrouzet.fr/wp-includes/theme.php:1087
    0.2945   38242488  10. the_excerpt_rss() /home/www/blog.juliencrouzet.fr/wp-includes/feed-rss2.php:46
    0.2971   38245056  11. apply_filters() /home/www/blog.juliencrouzet.fr/wp-includes/feed.php:177
    0.2974   38247336  12. call_user_func_array() /home/www/blog.juliencrouzet.fr/wp-includes/plugin.php:166

]]></description>
			<content:encoded><![CDATA[<p>Une super présentation par John Resig (le jeune créateur de jQuery, entre autres) qui nous explique avec le sourire pourquoi le DOM, c&#8217;est le bordel <img src='http://blog.juliencrouzet.fr/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<p style="text-align: center;"><object width="425" height="355" data="http://static.slideshare.net/swf/ssplayer2.swf?doc=yahoodom-1233608138666908-3&amp;stripped_title=the-dom-is-a-mess-yahoo" type="application/x-shockwave-flash"><param name="allowFullScreen" value="true" /><param name="allowScriptAccess" value="always" /><param name="src" value="http://static.slideshare.net/swf/ssplayer2.swf?doc=yahoodom-1233608138666908-3&amp;stripped_title=the-dom-is-a-mess-yahoo" /><param name="allowfullscreen" value="true" /></object></p>
<div id="__ss_981615" style="width: 425px; text-align: left;"><a style="font:14px Helvetica,Arial,Sans-serif;display:block;margin:12px 0 3px 0;text-decoration:underline;" title="The DOM is a Mess @ Yahoo" href="http://www.slideshare.net/jeresig/the-dom-is-a-mess-yahoo?type=presentation">The DOM is a Mess @ Yahoo</a></div>
<div id="__ss_981615" style="width: 425px; text-align: left;"></div>
<p><span id="more-277"></span></p>
<p style="text-align: center;"><object width="512" height="322" data="http://d.yimg.com/static.video.yahoo.com/yep/YV_YEP.swf?ver=2.2.34" type="application/x-shockwave-flash"><param name="allowFullScreen" value="true" /><param name="AllowScriptAccess" value="always" /><param name="bgcolor" value="#000000" /><param name="flashVars" value="id=11812238&amp;vid=4403981&amp;lang=en-us&amp;intl=us&amp;thumbUrl=http%3A//l.yimg.com/a/p/i/bcst/videosearch/899/79387316.jpeg&amp;embed=1" /><param name="src" value="http://d.yimg.com/static.video.yahoo.com/yep/YV_YEP.swf?ver=2.2.34" /><param name="flashvars" value="id=11812238&amp;vid=4403981&amp;lang=en-us&amp;intl=us&amp;thumbUrl=http%3A//l.yimg.com/a/p/i/bcst/videosearch/899/79387316.jpeg&amp;embed=1" /><param name="allowfullscreen" value="true" /></object></p>
<p style="text-align: left;">
<div><a href="http://video.yahoo.com/watch/4403981/11812238">John Resig: &laquo;&nbsp;The DOM Is a  Mess&nbsp;&raquo;</a> @ <a href="http://video.yahoo.com">Yahoo! Video</a></div>
]]></content:encoded>
			<wfw:commentRss>http://blog.juliencrouzet.fr/277/le-dom-cest-le-bordel/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>[PHP] Les sessions</title>
		<link>http://blog.juliencrouzet.fr/263/php-les-sessions/</link>
		<comments>http://blog.juliencrouzet.fr/263/php-les-sessions/#comments</comments>
		<pubDate>Mon, 09 Mar 2009 09:00:32 +0000</pubDate>
		<dc:creator>c2c</dc:creator>
				<category><![CDATA[code]]></category>
		<category><![CDATA[geek]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[Tech]]></category>

		<guid isPermaLink="false">http://blog.juliencrouzet.fr/?p=263</guid>
		<description><![CDATA[
Warning: call_user_func_array() expects parameter 1 to be a valid callback, first array member is not a valid class name or object in /home/www/blog.juliencrouzet.fr/wp-includes/plugin.php on line 166

Call Stack:
    0.0001     623440   1. {main}() /home/www/blog.juliencrouzet.fr/index.php:0
    0.0002     628968   2. require('/home/www/blog.juliencrouzet.fr/wp-blog-header.php') /home/www/blog.juliencrouzet.fr/index.php:17
    0.2053   38133272   3. require_once('/home/www/blog.juliencrouzet.fr/wp-includes/template-loader.php') /home/www/blog.juliencrouzet.fr/wp-blog-header.php:16
    0.2062   38136192   4. do_feed() /home/www/blog.juliencrouzet.fr/wp-includes/template-loader.php:14
    0.2062   38136472   5. do_action() /home/www/blog.juliencrouzet.fr/wp-includes/functions.php:1721
    0.2063   38138496   6. call_user_func_array() /home/www/blog.juliencrouzet.fr/wp-includes/plugin.php:395
    0.2063   38138552   7. do_feed_rss2() /home/www/blog.juliencrouzet.fr/wp-includes/plugin.php:0
    0.2063   38138744   8. load_template() /home/www/blog.juliencrouzet.fr/wp-includes/functions.php:1753
    0.2064   38200936   9. require_once('/home/www/blog.juliencrouzet.fr/wp-includes/feed-rss2.php') /home/www/blog.juliencrouzet.fr/wp-includes/theme.php:1087
    0.3024   38246392  10. the_excerpt_rss() /home/www/blog.juliencrouzet.fr/wp-includes/feed-rss2.php:46
    0.3178   38249024  11. apply_filters() /home/www/blog.juliencrouzet.fr/wp-includes/feed.php:177
    0.3181   38251448  12. call_user_func_array() /home/www/blog.juliencrouzet.fr/wp-includes/plugin.php:166

]]></description>
			<content:encoded><![CDATA[<div id="attachment_264" class="wp-caption aligncenter" style="width: 188px"><a href="http://blog.juliencrouzet.fr/wp-content/uploads/2009/03/800px-php-n_logosvg1_2.png" rel="lightbox[263]"><img class="size-medium wp-image-264" title="800px-php-n_logosvg1_2" src="http://blog.juliencrouzet.fr/wp-content/uploads/2009/03/800px-php-n_logosvg1_2-300x157.png" alt="Les sessions PHP" width="178" height="93" /></a><p class="wp-caption-text">Les sessions PHP</p></div>
<p>Les <a href="http://fr.php.net/manual/fr/book.session.php">sessions</a> sont présentes dans PHP depuis PHP4 (1998) et font partie des première choses que l&#8217;ont apprend à utiliser, cependant, elles sont souvent très mal utilisées car mal comprises ; l&#8217;occasion de revenir sur ce sujet et me lancer dans un premier article &laquo;&nbsp;pédagogique&nbsp;&raquo;.</p>
<p><span id="more-263"></span></p>
<h2>Pourquoi utiliser des sessions</h2>
<p>Comprendre ce point, c&#8217;est éviter pas mal de bourdes. Qu&#8217;est-ce qu&#8217;une session exactement ?</p>
<p>Une session, comme son nom l&#8217;indique, représente un temps <strong>défini</strong> d&#8217;utilisation d&#8217;un site par un internaute donné. Cette session à donc un début et une fin et représente un temps logique d&#8217;utilisation.</p>
<p>Les sites Web reposent sur un protocole : <a href="http://fr.wikipedia.org/wiki/Hypertext_Transfer_Protocol">HTTP</a>, qui est de nature très volatile =&gt; <strong>Je me connecte, j&#8217;envoi une requête, le serveur me répond, je me déconnecte.</strong> Impossible de savoir qui vous êtes !Pour pallier à ce problème ont été inventés les <a href="http://fr.wikipedia.org/wiki/Cookie_(informatique)">cookies</a>. Un cookie est un &laquo;&nbsp;témoin&nbsp;&raquo; que laisse un serveur Web dans votre navigateur, cela permet de mettre en place un historique de la communication.</p>
<p>Les sessions ont le même but, garder un historique des communications entre le serveur Web et votre navigateur. Ce n&#8217;est ni un espace de stockage temporaire, ni une base de données.</p>
<h2>Comment fonctionnent les sessions</h2>
<p>Côté PHP, rien de plus simple :</p>
<pre lang="PHP">/**
 * Création de la session
 */
session_start();
/**
 * Créer / Modifier une donnée de session
 */
$_SESSION['user_id'] = 125;
/**
 * Supprimer une donnée de session
 */
unset($_SESSION['user_id']);
/**
 * Détruire une session
 */
session_destroy();</pre>
<p>Je vous laisse consulter <a href="http://fr2.php.net/manual/fr/ref.session.php">la liste des fonctions</a> complète &#8230;</p>
<p>Mais comment cela fonctionne-t-il concrètement ? Analysons le fonctionnement <strong>par défaut</strong> :</p>
<p>Lors du premier appel à <em>session_create()</em>, PHP va créer un fichier temporaire dont le nom est un <a href="http://fr2.php.net/uniqid">identifiant unique</a>. Cet identifiant est également l&#8217;identifiant de le session. Il va également envoyer un cookie au navigateur nommé <em>PHPSESSID</em> contenant cet identifiant unique.</p>
<p>Une fois ce fichier créé, PHP va alors rendre disponible un variable <a href="http://fr2.php.net/manual/fr/language.variables.superglobals.php">superglobale</a> (disponible quel que soit le contexte) <em>$_SESSION</em>. Le développeur peut alors utiliser ce tableau comme n&#8217;importe lequel pour y stocker, lire et supprimer des données.</p>
<p>A la fin de l&#8217;execution du script, PHP va écrire dans le fichier temporaire créé lors de la première étape le contenu du tableau <em>$_SESSION</em> <a href="http://fr2.php.net/serialize">linéarisé</a>.</p>
<p>Lors des prochaines requêtes, le navigateur va envoyer l&#8217;identifiant de la session (stocké dans le cookie <em>PHPSESSID</em>), <em>session_create()</em> ne créera pas alors de fichier mais <a href="http://fr2.php.net/unserialize">délinéarisera</a> le contenu de ce fichier et le stockera dans <em>$_SESSION</em>, le développeur pourra alors récupérer les données stockées lors de la requête précédente et les modifier à nouveau. Ce jusqu&#8217;a l&#8217;appel de <em>session_destroy()</em> qui effacera le fichier temporaire et le cookie.</p>
<p>Comme l&#8217;on vient de le voir, le système des sessions est basé sur les cookies. Un cookie est donné du serveur Web au navigateur par une <a href="http://fr.wikipedia.org/wiki/Header_(informatique)">en-tête </a>HTTP. Il est donc impératif de placer l&#8217;appel à <em>session_start()</em> le plus haut possible dans votre script, car toute information envoyée (<a href="http://fr2.php.net/echo">echo()</a>, <a href="http://fr2.php.net/imagejpeg">imagejpeg()</a>, &#8230;) provoquera l&#8217;envoi définif des en-tête standard et il sera trop tard pour envoyer le cookie de session !</p>
<h2>Ce qu&#8217;une session doit contenir</h2>
<p>Maintenant que nous avons une nouvelle opportunité, à savoir stocker des données entre deux requête d&#8217;un utilisateur, on pourrait avoir le reflexe d&#8217;y enregistrer tout un tas de chose, comme l&#8217;historique de navigation de l&#8217;internaute sur le site, ses précédents achats, etc.</p>
<p>STOP.</p>
<p>Une session n&#8217;est pas un espace de stockage ou une mémoire cache. Le fonctionnement décrit ci-dessus est très pratique mais très gourmand en ressources :</p>
<ul>
<li>Les données sont à chaque requête <a href="http://fr2.php.net/serialize">linéarisée</a> et <a href="http://fr2.php.net/unserialize">délinéarisées</a>. Si cette fonction est très pratique pour enregistrer une données complexe facilement (transformée en une chaîne), elle est très couteuse en ressources</li>
<li>Les données linéarisées sont stockées sur un fichier. Il y a donc pour chaque requête une écriture et une lecture sur le disque dur. Les opérations sur le disque dur sont les première opérations à minimiser si l&#8217;on veut optimiser son site</li>
<li>Le tableau <em>$_SESSION</em> est une superglobale, ce qui veut dire qu&#8217;il sera accessible de partout mais aussi qu&#8217;il sera présent en mémoire tout au long de l&#8217;execution du script. Garder beaucoup d&#8217;informations en mémoire quand elles ne sont pas utilisées est un non sens. Celles-ci doivent être présente que lorsqu&#8217;on l&#8217;utilise est déchargées dès que possible.</li>
</ul>
<p>Une session ne doit donc contenir qu&#8217;une chose : Des informations sur la session en cours, typiquement peut s&#8217;agir :</p>
<ul>
<li>D&#8217;un identifiant utilisateur</li>
<li>Un email</li>
<li>Une clef unique</li>
<li>La date de création de la session</li>
</ul>
<h2>Configuration et scaling</h2>
<p>Le fonctionnement des sessions vu ci-dessus n&#8217;est pas gravé dans le marbre. Et heureusement.Si il a le mérité d&#8217;être simple à utiliser, il est totalement inutilisable sur des sites à gros traffic.</p>
<h3>Configurer le cookie</h3>
<p>Le nom par défaut du cookie des sessions est <em>PHPSESSID</em>. Simple, clair, on sait de quoi il s&#8217;agit. Un peu trop même. Cela peut être changé en utilisant la fonction <a href="http://fr2.php.net/session-name"><em>session_name()</em></a> ou la variable de configuration <a href="http://fr2.php.net/manual/fr/session.configuration.php#ini.session.name"><em>session.name</em></a>.</p>
<p>Mais il y a plus grave, ce cookie est défini par défaut comme ceci :</p>
<ul>
<li>Il n&#8217;est valable que pour le domaine (VHOST) en cours (donc si vous changez de domaine =&gt; en.monsite.com vers fr.monsite.com, il n&#8217;est plus valable)</li>
<li>Il est valable des la racine &#8216;/&#8217; (Si votre site est www.site.com/monsite/, vous le partagez avec www.site.com/autresite/)</li>
<li>C&#8217;est un cookie de session (Des que le navigateur est fermé, il n&#8217;est plus valable)</li>
<li>Il est valable qu&#8217;on soit en HTTP ou HTTPS</li>
</ul>
<p>Pour configurer ça, nous avons la méthode</p>
<pre lang="PHP">session_set_cookie_params($lifetime, $path, $domain, $secure, $httponly);</pre>
<ul>
<li><strong>$lifetime</strong> : Si 0, cookie de session, sinon, le nombre de secondes pendant lequel il sera valable [Default: 0]</li>
<li><strong>$path</strong> : Définit la racine du chemin a partir duquel le cookie sera valide (Ex: &#8216;/monsite&#8217;) [Default: '/']</li>
<li><strong>$domain</strong> : Domaine pour lequel le cookie sera valable. Pour tous les domaines se terminant par &#8216;juliencrouzet.fr&#8217;, utilisez &#8216;<span style="text-decoration: underline;"><strong>.</strong></span>juliencrouzet.fr&#8217; [Default: Le VHOST en cours]</li>
<li><strong>$secure</strong> : Si true, le cookie ne sera envoyé que si l&#8217;on est en HTTPS [Default: false]</li>
<li><strong>$httponly</strong> : Si true, le cookie ne sera envoyé que si le protocole est HTTP (Pas dans le cas d&#8217;une demande de script ou de feuille CSS, comme c&#8217;est le cas sur les attaques <a href="http://fr.wikipedia.org/wiki/Cross_site_scripting">XSS</a>) [Default: false]</li>
</ul>
<h3>Modifier la gestion des cookie</h3>
<p>PHP est livré avec le système de session géré par fichier temporaire comme décrit plus haut.  Cependant, comme nous l&#8217;avons rappelé, ce système est couteux en ressources et inadapté à des sites professionnels à forts traffic.</p>
<p>Heureusement, tout à été prévu ! La fonction <a href="http://fr2.php.net/manual/fr/function.session-set-save-handler.php"><em>session_set_save_handler()</em></a> vous permet de gérer vous même la création, la destruction est la manipulation des sessions et ainsi les stocker dans :</p>
<ul>
<li>Une base de données MySQL, SQLite, etc.</li>
<li>Un système de cache (Attention cependant, un cache est volatile et peut disparaitre, vos sessions aussi !)</li>
<li>Ce que vous voulez !</li>
</ul>
<h3>Scaling de votre application</h3>
<p>Si modifier la gestion des sessions peut paraitre un best practice si l&#8217;on a qu&#8217;un serveur, elle devient indispensable si l&#8217;on a plusieurs serveurs !</p>
<p>Une session est propre à un site Internet, pas à une machine, et si la session est stockée sur le disque dur de la première machine ou l&#8217;a fait une requête, elle aura disparue des que l&#8217;on change de serveur !</p>
<h2>Sécuriser des sessions</h2>
<p>Les sessions servant essentiellement à authentifier un internaute, il est primordial de vérifier leur sécurité. Une des première faille du système repose sur le fait qu&#8217;il suffise de connaitre l&#8217;identifiant de la session d&#8217;un internaute pour usurper son identité. C&#8217;est moche.</p>
<p>Une des premières idées que l&#8217;on peut avoir est de couplé cet identifiant à une adresse I.P., mais quid des utilisateurs en entreprise qui sont souvent derrière un pool de proxy et donc qui changent régulierement d&#8217;I.P. ?</p>
<p>La plus importante règle de sécurité à appliquer est en fait de regénérer l&#8217;identifiant de session à chaque requête. Certes, le cookie change à chaque fois et cela peut être un peu gourmand en ressources, mais si quelqu&#8217;un arrive à récupérer votre identifiant, cela ne lui sert a rien, il aura déjà changé lors de la prochaine requête.</p>
<p>Il suffit pour cela d&#8217;utiliser <a href="http://fr2.php.net/session-regenerate-id"><em>session_regenerate_id()</em></a> &#8211; ou &#8211; utiliser Zend Framework ! (oui je sais c&#8217;est récurrent ça)</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.juliencrouzet.fr/263/php-les-sessions/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>10 outils qui séparent un développeur d’un webmaster</title>
		<link>http://blog.juliencrouzet.fr/252/10-outils-qui-separent-un-devloppeur-d-un-webmaster/</link>
		<comments>http://blog.juliencrouzet.fr/252/10-outils-qui-separent-un-devloppeur-d-un-webmaster/#comments</comments>
		<pubDate>Sun, 08 Mar 2009 14:57:14 +0000</pubDate>
		<dc:creator>c2c</dc:creator>
				<category><![CDATA[code]]></category>
		<category><![CDATA[geek]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[Tech]]></category>

		<guid isPermaLink="false">http://blog.juliencrouzet.fr/?p=252</guid>
		<description><![CDATA[
Warning: call_user_func_array() expects parameter 1 to be a valid callback, first array member is not a valid class name or object in /home/www/blog.juliencrouzet.fr/wp-includes/plugin.php on line 166

Call Stack:
    0.0001     623440   1. {main}() /home/www/blog.juliencrouzet.fr/index.php:0
    0.0002     628968   2. require('/home/www/blog.juliencrouzet.fr/wp-blog-header.php') /home/www/blog.juliencrouzet.fr/index.php:17
    0.2053   38133272   3. require_once('/home/www/blog.juliencrouzet.fr/wp-includes/template-loader.php') /home/www/blog.juliencrouzet.fr/wp-blog-header.php:16
    0.2062   38136192   4. do_feed() /home/www/blog.juliencrouzet.fr/wp-includes/template-loader.php:14
    0.2062   38136472   5. do_action() /home/www/blog.juliencrouzet.fr/wp-includes/functions.php:1721
    0.2063   38138496   6. call_user_func_array() /home/www/blog.juliencrouzet.fr/wp-includes/plugin.php:395
    0.2063   38138552   7. do_feed_rss2() /home/www/blog.juliencrouzet.fr/wp-includes/plugin.php:0
    0.2063   38138744   8. load_template() /home/www/blog.juliencrouzet.fr/wp-includes/functions.php:1753
    0.2064   38200936   9. require_once('/home/www/blog.juliencrouzet.fr/wp-includes/feed-rss2.php') /home/www/blog.juliencrouzet.fr/wp-includes/theme.php:1087
    0.3351   38250296  10. the_excerpt_rss() /home/www/blog.juliencrouzet.fr/wp-includes/feed-rss2.php:46
    0.3511   38252904  11. apply_filters() /home/www/blog.juliencrouzet.fr/wp-includes/feed.php:177
    0.3513   38255312  12. call_user_func_array() /home/www/blog.juliencrouzet.fr/wp-includes/plugin.php:166

]]></description>
			<content:encoded><![CDATA[<p><a href="http://blog.juliencrouzet.fr/wp-content/uploads/2009/02/codemonkeysketch.jpg" rel="lightbox[252]"><img class="aligncenter size-medium wp-image-206" title="codemonkeysketch" src="http://blog.juliencrouzet.fr/wp-content/uploads/2009/02/codemonkeysketch-296x300.jpg" alt="codemonkeysketch" width="144" height="146" /></a></p>
<p>Suite au <a href="http://blog.juliencrouzet.fr/2009/02/28/10-regles-qui-separent-un-developpeur-dun-webmaster/comment-page-1/#comment-49">commentaire de Fred</a>, je me lance dans une nouvelle liste, plus ou moins la même, mais concernant cette fois les outils utilisés dans le cadre d&#8217;un développement PHP. Pour d&#8217;autres langages, la plupart du temps, les mêmes outils existent, n&#8217;hésitez pas à commenter.</p>
<p><span id="more-252"></span></p>
<h2><a href="http://www.getfirefox.com">Firefox</a></h2>
<p>Je pense qu&#8217;il est pas nécessaire de s&#8217;étendre sur Firefox&#8230;</p>
<p><span style="text-decoration: underline;">Alternatives</span> : Vous savez &#8230;</p>
<h2><a href="http://www.getfirebug.com"> Firebug et ses modules</a></h2>
<p><a href="http://www.getfirebug.com">Firebug</a> est tellement incontournable qu&#8217;il devrait faire l&#8217;objet de cours dans les écoles d&#8217;informatique qui touchent au développement Web !Régulièrement, je me pose la question : Combien de temps aurais-je eu besoin pour débugguer ça sans Firebug ? Et en général c&#8217;est des jours &#8230;</p>
<p>Firebug, c&#8217;est une <a href="http://getfirebug.com/logging.html">console</a> de débug, un <a href="http://getfirebug.com/dom.html">explorateur DOM</a>, un <a href="http://getfirebug.com/js.html">profiler Javascript</a>, un <a href="http://getfirebug.com/html.html">inspecteur HTML</a>, un <a href="http://getfirebug.com/net.html">sniffer HTTP</a>, <a href="http://www.evotech.net/blog/2007/06/introduction-to-firebug/">etc</a>.</p>
<p>Mais pas seulement &#8230;</p>
<p>Petit à petit des extensions de Firebug (oui des extensions d&#8217;un extension &#8230; c&#8217;est magique Firefox) on poussé. En voila 3 qui me parraissent tout simplement indispensable à votre santé mentale :</p>
<h3><a href="http://addons.mozilla.org/en-US/firefox/addon/6683">Firecookie</a></h3>
<p>Permet d&#8217;avoir un log de toutes les créations, modifications et expirations des cookies, de les gérer (création, edition, supression, &#8230;) et de configurer les autorisations.</p>
<h3><a href="http://fireunit.org/">Fireunit</a></h3>
<p>Permet de créer et d&#8217;exécuter des tests unitaires en Javascript.</p>
<h3><a href="http://developer.yahoo.com/yslow/">YSlow</a></h3>
<p>Crée un rapport de performance sur votre site (connection, rapidité, etc.) en utilisant Firebug. Développé par Yahoo!.</p>
<p>Au passage, ça <a href="http://getfirebug.com/lite.html">marche sous les autres navigateurs</a> !</p>
<p><span style="text-decoration: underline;">Alternatives</span> : Aucune ! Des petits bouts dans <a href="http://addons.mozilla.org/fr/firefox/addon/60">Web Developper</a>, ou <a href="http://addons.mozilla.org/addon/216">Javascript Debugger</a> mais on en est loin.</p>
<h2><a href="http://fr.wikipedia.org/wiki/Git">GIT</a></h2>
<p>GIT (connard, en anglais) est outil de <a href="http://fr.wikipedia.org/wiki/Syst%C3%A8me_de_gestion_de_versions">versionning</a> développé par Linus Torvalds (le créateur de Linux).</p>
<p>Comme tout outil de versionning, il permet de gérer les évolutions de fichiers dans une architecture ; cependant; il a quelques avantages :</p>
<ul>
<li>Un système <a href="http://fr.wikipedia.org/wiki/Gestion_de_version_d%C3%A9centralis%C3%A9e">décentralisé</a></li>
<li>Une gestion des droits plus poussée</li>
<li>Une vraie gestion des branches</li>
<li>Un besoin d&#8217;espace disque réduit</li>
<li>Une performance (rapidité, fiabilité) à toute épreuve</li>
</ul>
<p><span style="text-decoration: underline;">Alternatives</span> : <a href="http://subversion.tigris.org/">SVN</a>, <a href="http://bazaar-vcs.org/">Bazaar</a>, <a href="http://www.bitkeeper.com/">BitKeeper </a>(propriétaire)</p>
<h2><a href="http://validator.w3.org/">W3C Validator</a></h2>
<p>Valider son code (X)HTML peut parfois paraitre un long et inutile processus. Surtout que le sus nommé validateur est très pointilleux ; mais croyez-moi ; vous gagnez en fait de loooongues heures de débuggage.</p>
<p>Une source XHTML valide à 100% a de très très fortes chances de s&#8217;afficher correctement sous tous les navigateurs et qui plus est, plus rapidement.</p>
<p><span style="text-decoration: underline;">Alternatives</span> : <a href="http://www.htmlhelp.com/tools/validator/">WDG Validator</a>, <a href="https://addons.mozilla.org/fr/firefox/addon/249">HTML Validator for Firefox</a></p>
<h2><a href="http://www.jslint.com/">JSLint</a> &amp; <a href="http://www.icosaedro.it/phplint/">PHPLint</a></h2>
<p>Ceux qui ont fait du <a href="http://fr.wikipedia.org/wiki/C_(langage)">C</a>, du vrai, du costaud, du barbu connaissent <a href="http://docs.sun.com/source/806-3567/lint.html">lint</a>. lint c&#8217;était un peu le vieux monsieur du batiment qui arrivent sur un chantier qui apparement est fini et vous dit &laquo;&nbsp;Votre mur là, c&#8217;est du béton pauvre en ciment, ca va tomber dans 2 ans !&nbsp;&raquo;.</p>
<p>Les fonctions de lint sont aujourd&#8217;hui intégrées aux compilateurs (gcc &amp; co), et lint est plutôt un terme génrérique (<a href="http://www.jslint.com/">JSLint,</a> <a href="http://www.icosaedro.it/phplint/">PHPLint</a>, <a href="http://www.sureshotsoftware.com/javalint/">JAVALint</a>, etc.) qui décrit un outil analysant votre code afin d&#8217;y trouver les incohérences ou bugs potentiels. Ils permettent, entre autres, de détécter :</p>
<ul>
<li>Les variables non utilisées, non instanciées ou mal typées</li>
<li>Les partie de code qui ne seront jamais utilisées</li>
<li>Les potentielles boucles infinies</li>
<li>Les confusions possibles dues à de mauvais noms de variables ou fonctions</li>
</ul>
<p><span style="text-decoration: underline;">Alternatives</span> : <a href="http://yasca.org/">YASCA</a>, <a href="http://seclab.tuwien.ac.at/projects/pixy/">Pixy</a>, <a href="http://www.fortify.com/">Fortify</a> (commercial)</p>
<h2><a href="http://www.zend.com/fr/products/studio/">Zend Studio</a></h2>
<p>Je suis d&#8217;habitude du genre à préférer les solutions open source, mais je n&#8217;ai pas trouvé d&#8217;équivalent pour l&#8217;intant. C&#8217;est en suite un question d&#8217;habitude&#8230;</p>
<p>Quoi qu&#8217;il en soit, il est inconcevable de coder de manière optimale sans un IDE ou au moins un éditeur spécialisé.</p>
<p>Ce que j&#8217;aime dans Zend Studio :</p>
<ul>
<li>La complétion de code intelligente (parsing de votre code, typage, etc)</li>
<li>Les gabarits (templates) facilement éditables avec support de variables</li>
<li>Intégration de Zend Framework native</li>
<li>Support de CVS, SVN, Git (pour la version Eclipse) et SFTP/FTP</li>
<li>L&#8217;interface de Zend Studio 5 (pas celle d&#8217;Eclipse)</li>
<li>Gestion du XHTML et de Javascript</li>
</ul>
<p><span style="text-decoration: underline;">Alternatives</span> : <a href="http://www.php-editors.com/">Tout est là</a></p>
<h2><a href="http://www.softpedia.com/get/Internet/Browsers/Internet-Explorer-Collection.shtml">Internet Explorer Collection</a></h2>
<p>Quiconque a déjà développé un site <a href="http://blogs.zdnet.com/Berlind/?p=565">le sait</a>. Le support de Internet Explorer (surtout 6) est une vraie plaie qui ralentit le développement de manière considérable.Plus on vérifie tôt, plus souvent on le fait, plus on gagnera de temps.</p>
<p>IE Collection installe sur votre machine (Windows) toute les versions de Internet Explorer de la 1 (ouch !) à la 8, de manière native.</p>
<p><span style="text-decoration: underline;">Alternatives</span> : <a href="http://tredosoft.com/Multiple_IE">MultipleIE</a>, <a href="http://www.my-debugbar.com/wiki/IETester/HomePage">IETester</a></p>
<h2><a href="http://framework.zend.com/">Zend Framework</a></h2>
<p>Pas de débat. La chose est tranchée <img src='http://blog.juliencrouzet.fr/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<p>Zend Framework EST le Framework le plus <a href="http://framework.zend.com/community/partners">soutenu</a>, le plus <a href="http://framework.zend.com/build">maintenu</a>, le plus <a href="http://framework.zend.com/about/components">complet</a>, le mieux <a href="http://framework.zend.com/docs/overview">documenté</a>, le plus <a href="http://framework.zend.com/about/casestudies">utilisé </a>et le <a href="http://ordinarywebguy.wordpress.com/2008/04/22/i-love-zend-framework-it-really-rocks/">plus mieux du monde</a>.</p>
<p><span style="text-decoration: underline;">Alternatives (si vous cherchez moin bien <img src='http://blog.juliencrouzet.fr/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> )</span> : <a href="http://www.symfony-project.org/">Symphony</a>, <a href="http://www.blueshoes.org/">Blue Shoes</a>,  <a href="http://cakephp.org/">CakePHP</a></p>
<h2><a href="http://trac.edgewall.org">Trac</a></h2>
<p>Trac est un outil de gestion de projet open source qui démoule son poney (Copyright <a href="http://www.korben.info/edito-du-dernier-vendredi-de-janvier.html">Korben</a>). Véritable couteau suisse, il gère pour vous de base :</p>
<ul>
<li>Le Wiki du projet</li>
<li>La roadmap (feuille de route)</li>
<li>La gestion des tickets (bugs, tâches, amélioration, points à trancher, etc.)</li>
<li>L&#8217;exploration de votre outils de versionning (SVN)</li>
</ul>
<p>Après un tour dans le <a href="http://trac-hacks.org/">répertoire de plugins</a>, il gérera pour vous des miliers d&#8217;autres choses, comme la gestion du temps, le support de Git ou autres, s&#8217;intégrera à Zend Studio ou ira vous chercher un Grande Late chez Starbucks (enfin je crois)</p>
<p><span style="text-decoration: underline;">Alternatives</span> : <a href="http://www.mantisbt.org/">Mantis</a>, <a href="http://www.bugzilla.org">Bugzilla</a>, <a href="http://www.phprojekt.com/features.php">PHProjekt</a></p>
<h2><a href="http://www.jquery.com">jQuery</a></h2>
<p>Last but not least &#8230; jQuery est LA bibliothèque Javascript qu&#8217;il vous faut. Décrire tout ce que jQuery peut vous apporter prendrait des heures et des heures &#8230; Alors certes, d&#8217;autres librairies existent, et presque aussi complètes, mais voilà  :</p>
<p><a href="http://blog.juliencrouzet.fr/wp-content/uploads/2009/03/jquery_mootools_prototype.jpg" rel="lightbox[252]"><img class="aligncenter size-medium wp-image-259" title="jquery_mootools_prototype" src="http://blog.juliencrouzet.fr/wp-content/uploads/2009/03/jquery_mootools_prototype-235x300.jpg" alt="jquery_mootools_prototype" width="235" height="300" /></a></p>
]]></content:encoded>
			<wfw:commentRss>http://blog.juliencrouzet.fr/252/10-outils-qui-separent-un-devloppeur-d-un-webmaster/feed/</wfw:commentRss>
		<slash:comments>9</slash:comments>
		</item>
		<item>
		<title>Segmenter les résultats de Google Analytics par réseau sociaux</title>
		<link>http://blog.juliencrouzet.fr/228/segmenter-les-resultats-de-google-analytics-par-reseau-sociaux/</link>
		<comments>http://blog.juliencrouzet.fr/228/segmenter-les-resultats-de-google-analytics-par-reseau-sociaux/#comments</comments>
		<pubDate>Sat, 28 Feb 2009 15:01:40 +0000</pubDate>
		<dc:creator>c2c</dc:creator>
				<category><![CDATA[code]]></category>
		<category><![CDATA[google analytics]]></category>
		<category><![CDATA[social]]></category>
		<category><![CDATA[Tech]]></category>
		<category><![CDATA[web2.0]]></category>

		<guid isPermaLink="false">http://blog.juliencrouzet.fr/?p=228</guid>
		<description><![CDATA[
Warning: call_user_func_array() expects parameter 1 to be a valid callback, first array member is not a valid class name or object in /home/www/blog.juliencrouzet.fr/wp-includes/plugin.php on line 166

Call Stack:
    0.0001     623440   1. {main}() /home/www/blog.juliencrouzet.fr/index.php:0
    0.0002     628968   2. require('/home/www/blog.juliencrouzet.fr/wp-blog-header.php') /home/www/blog.juliencrouzet.fr/index.php:17
    0.2053   38133272   3. require_once('/home/www/blog.juliencrouzet.fr/wp-includes/template-loader.php') /home/www/blog.juliencrouzet.fr/wp-blog-header.php:16
    0.2062   38136192   4. do_feed() /home/www/blog.juliencrouzet.fr/wp-includes/template-loader.php:14
    0.2062   38136472   5. do_action() /home/www/blog.juliencrouzet.fr/wp-includes/functions.php:1721
    0.2063   38138496   6. call_user_func_array() /home/www/blog.juliencrouzet.fr/wp-includes/plugin.php:395
    0.2063   38138552   7. do_feed_rss2() /home/www/blog.juliencrouzet.fr/wp-includes/plugin.php:0
    0.2063   38138744   8. load_template() /home/www/blog.juliencrouzet.fr/wp-includes/functions.php:1753
    0.2064   38200936   9. require_once('/home/www/blog.juliencrouzet.fr/wp-includes/feed-rss2.php') /home/www/blog.juliencrouzet.fr/wp-includes/theme.php:1087
    0.3689   38254200  10. the_excerpt_rss() /home/www/blog.juliencrouzet.fr/wp-includes/feed-rss2.php:46
    0.3705   38256784  11. apply_filters() /home/www/blog.juliencrouzet.fr/wp-includes/feed.php:177
    0.3707   38259168  12. call_user_func_array() /home/www/blog.juliencrouzet.fr/wp-includes/plugin.php:166

]]></description>
			<content:encoded><![CDATA[<div id="attachment_171" class="wp-caption aligncenter" style="width: 206px"><a href="http://blog.juliencrouzet.fr/wp-content/uploads/2009/02/seo-blocks.gif" rel="lightbox[228]"><img class="size-medium wp-image-171" title="seo-blocks" src="http://blog.juliencrouzet.fr/wp-content/uploads/2009/02/seo-blocks-300x231.gif" alt="Another project released !" width="196" height="151" /></a><p class="wp-caption-text">Another project released !</p></div>
<p>Il y a quelques temps, je vous parlais de <a href="http://blog.juliencrouzet.fr/2008/12/15/socialhistory-le-bigbrother-des-medias-sociaux/">SocialHistory </a>&#8230; et j&#8217;ai eu une idée (wahou) !</p>
<p>Grace à CSS et un iframe  il est possible de savoir quels sont les sites qu&#8217;une personne à déjà consulté, donc qu&#8217;il utilise probablement.</p>
<p>Google Analytics permet de segmenter ses utilisateurs selon une variable laissée libre à l&#8217;utilisateur, les &laquo;&nbsp;User Defined Value&nbsp;&raquo; :</p>
<p><a href="http://blog.juliencrouzet.fr/nas/user%20defined%20value.swf">User Defined Value dans Google Analytics en vidéo</a></p>
<p>En combinant les deux, on peut donc savoir quels sont les réseaux sociaux les plus utilisés par vos visiteurs !</p>
<p>Et voila le résultat : <a href="http://code.google.com/p/jsocialanalytics/">jSocialAnalytics</a></p>
<p>En live, ca donne <a href="http://blog.juliencrouzet.fr/jSocialAnalytics/">ça</a>.</p>
<p>Bien entendu c&#8217;est très beta pour le moment, mais je suis bien content de moi <img src='http://blog.juliencrouzet.fr/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
]]></content:encoded>
			<wfw:commentRss>http://blog.juliencrouzet.fr/228/segmenter-les-resultats-de-google-analytics-par-reseau-sociaux/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>10 règles qui séparent un développeur d&#039;un webmaster</title>
		<link>http://blog.juliencrouzet.fr/205/10-regles-qui-separent-un-developpeur-dun-webmaster/</link>
		<comments>http://blog.juliencrouzet.fr/205/10-regles-qui-separent-un-developpeur-dun-webmaster/#comments</comments>
		<pubDate>Sat, 28 Feb 2009 09:13:25 +0000</pubDate>
		<dc:creator>c2c</dc:creator>
				<category><![CDATA[code]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[social]]></category>
		<category><![CDATA[Tech]]></category>

		<guid isPermaLink="false">http://blog.juliencrouzet.fr/?p=205</guid>
		<description><![CDATA[
Warning: call_user_func_array() expects parameter 1 to be a valid callback, first array member is not a valid class name or object in /home/www/blog.juliencrouzet.fr/wp-includes/plugin.php on line 166

Call Stack:
    0.0001     623440   1. {main}() /home/www/blog.juliencrouzet.fr/index.php:0
    0.0002     628968   2. require('/home/www/blog.juliencrouzet.fr/wp-blog-header.php') /home/www/blog.juliencrouzet.fr/index.php:17
    0.2053   38133272   3. require_once('/home/www/blog.juliencrouzet.fr/wp-includes/template-loader.php') /home/www/blog.juliencrouzet.fr/wp-blog-header.php:16
    0.2062   38136192   4. do_feed() /home/www/blog.juliencrouzet.fr/wp-includes/template-loader.php:14
    0.2062   38136472   5. do_action() /home/www/blog.juliencrouzet.fr/wp-includes/functions.php:1721
    0.2063   38138496   6. call_user_func_array() /home/www/blog.juliencrouzet.fr/wp-includes/plugin.php:395
    0.2063   38138552   7. do_feed_rss2() /home/www/blog.juliencrouzet.fr/wp-includes/plugin.php:0
    0.2063   38138744   8. load_template() /home/www/blog.juliencrouzet.fr/wp-includes/functions.php:1753
    0.2064   38200936   9. require_once('/home/www/blog.juliencrouzet.fr/wp-includes/feed-rss2.php') /home/www/blog.juliencrouzet.fr/wp-includes/theme.php:1087
    0.3753   38258104  10. the_excerpt_rss() /home/www/blog.juliencrouzet.fr/wp-includes/feed-rss2.php:46
    0.3861   38260688  11. apply_filters() /home/www/blog.juliencrouzet.fr/wp-includes/feed.php:177
    0.3864   38263072  12. call_user_func_array() /home/www/blog.juliencrouzet.fr/wp-includes/plugin.php:166

]]></description>
			<content:encoded><![CDATA[<div id="attachment_206" class="wp-caption aligncenter" style="width: 241px"><a href="http://blog.juliencrouzet.fr/wp-content/uploads/2009/02/codemonkeysketch.jpg" rel="lightbox[205]"><img class="size-medium wp-image-206" title="codemonkeysketch" src="http://blog.juliencrouzet.fr/wp-content/uploads/2009/02/codemonkeysketch-296x300.jpg" alt="codemonkeysketch" width="231" height="166" /></a><p class="wp-caption-text">De PHP/FI à PHP6, les règles on changé</p></div>
<p>Après une dure semaine coté outils et méthodes de développement, je me lance dans une liste dont j&#8217;assume le coté très subjectif et qui n&#8217;engage que moi : les 10 choses qui permettent de séparer un développeur, un vrai qui sent la sueur, d&#8217;un webmaster.</p>
<p>Cette liste s&#8217;entend pour un développement Web et PHP &#8230;</p>
<p><span id="more-205"></span></p>
<h2><a href="http://fr.wikipedia.org/wiki/Programmation_orient%C3%A9e_objet">Programmation Orientée Objet</a></h2>
<p>Sujet sensible, si l&#8217;en est &#8230; J&#8217;ai encore du mal à comprendre qu&#8217;en 2009 on développe en <a href="http://fr.wikipedia.org/wiki/Programmation_proc%C3%A9durale">procédural </a>ma bonne dame !</p>
<h2><a href="http://fr.wikipedia.org/wiki/Framework">Utilisation d&#8217;un framework</a></h2>
<p>J&#8217;ai fait mes études à <a href="http://www.epitech.eu">{EPITECH}</a> (pas taper), ou l&#8217;on commence sa première année à réinventer la roue : se redévelopper sa propre libc, de <a href="http://www.linux-kheops.com/doc/man/manfr/man-html-0.9/man3/atoi.3.html">atoi()</a> à <a href="http://www.linux-kheops.com/doc/man/manfr/man-html-0.9/man3/malloc.3.html">malloc()</a>. Je comprenais et appréciais le principe de disséquer tout ça pour mieux le comprendre plutôt que d&#8217;en apprendre le manuel et s&#8217;en contenter.</p>
<p>Et puis est venu le stage, et la je ne comprenais plus ! Mon directeur technique s&#8217;était bricolé une librairie PHP3/PHP4 sortie d&#8217;un espace intersidéral qui était censée gérer tout, du traitement des chaînes au transferts FTP ; ce mauvais reflexe m&#8217;a poursuivi longtemps &#8230;</p>
<p>Développer un site ou une application Web, c&#8217;est utiliser une base saine, donc un Framework, pour se concentrer sur ce que l&#8217;on crée, à quoi bon <strong>mal </strong>recoder <a href="http://www.dreamincode.net/code/snippet1428.htm">une fonction</a> qui protège les champs d&#8217;une requête SQL ? Des centaines de développeurs l&#8217;ont déjà <strong>bien </strong>fait <a href="http://framework.zend.com/manual/fr/zend.db.html">pour vous</a> !</p>
<h2><a href="http://fr.wikipedia.org/wiki/Mod%C3%A8le-Vue-Contr%C3%B4leur">Utilisation d&#8217;une architecture MVC</a></h2>
<p>Un développeur qui ne respecte pas MVC :</p>
<blockquote><p>Si on veut enlever ces liens du footer, je vais devoir modifier la fonction generate_footer()</p></blockquote>
<p>L&#8217;équivalent chez son garagiste :</p>
<blockquote><p>Sur que je peux vous changer la plaque d&#8217;immatriculation, mais je vais devoir démonter la boite de vitesse</p></blockquote>
<p>L&#8217;avantage, c&#8217;est que ce point a de fortes chances d&#8217;être correlé avec le point précédent puis que la plupart des Framework PHP actuels se reposent sur une architecture MVC.</p>
<h2><a href="http://fr.wikipedia.org/wiki/Test_unitaire">Définir des tests unitaires</a></h2>
<p>Un développeur, un webmaster ou un boulanger ont une chose en commun : Ils ne sont pas infaillibles. Tout développement comporte forcément des bugs, c&#8217;est la <a href="http://fr.wikipedia.org/wiki/Loi_de_murphy">loi de murphy</a>.</p>
<p>Bien qu&#8217;aillant du mal à l&#8217;admettre, le développeur, le vrai, le poilu sait prévoir le fait qu&#8217;il oubliera ça et là de jolies erreur de conception, et il veut le savoir avant d&#8217;être montré du doigt ; il a donc inventé les <a href="http://fr.wikipedia.org/wiki/Test_unitaire">tests unitaires</a>.</p>
<p>PHP à donc aussi ses outils de tests unitaires, comme <a href="http://www.phpunit.de/">PHPUnit </a>ou <a href="http://www.simpletest.org/">SimpleTest</a>. A consommer sans modération !</p>
<h2><a href="http://fr.wikipedia.org/wiki/M%C3%A9moire_cache">Utiliser un cache</a></h2>
<p>Même si certains le pensent, les ressources sont chères et il ne faut pas les gaspiller. Le but ultime de toute application Web reste quand même, dans une grande majorité de cas, d&#8217;être utilisée par le plus de monde possible. C&#8217;est donc automatique, plus votre site est consulté, plus vous aurez besoin de processeur et de mémoire, plus cela vous coutera cher.La meilleure et la plus simple des méthodes d&#8217;économie de ressources est l&#8217;utilisation de mémoire cache.</p>
<p>Tout résultat d&#8217;une requête SQL, tout résultat d&#8217;une fonction complexe (calculs, recherches, etc.) doit ammener une question simple : Est-ce que je ne peux pas mettre ça en cache ? Si oui, action !</p>
<p>Le cache le plus simple est d&#8217;écrire ce résultat dans un fichier, mais il reste des solutions plus optimisées et simple à déployer comme <a href="http://www.danga.com/memcached">memcached</a>, <a href="http://sharedance.pureftpd.org/project/sharedance">sharedance </a>ou <a href="http://fr.php.net/apc">APC</a>. Là aussi, les Frameworks vous rendent cette tâche encore plus simple qu&#8217;elle ne l&#8217;est.</p>
<h2><a href="http://fr.wikipedia.org/wiki/Documentation_logicielle">Documenter son code</a></h2>
<p>Le meilleur conseil que l&#8217;on puisse donner à un développeur est:</p>
<blockquote><p><a class="title" href="http://www.myconfinedspace.com/watermark.php?src=wp-content/uploads/2007/06/001grg3w.jpg" rel="lightbox[205]"> Always code as if the person who will maintain your code is a maniac serial killer knows where you live</a></p></blockquote>
<p>Un des primodiaux pour ne pas vous faire éventrer par ce serial killer est de documenter ce code. Ce qui vous parait très clair aujourd&#8217;hui ne le sera plus du tout 3 jours ou 3 bières plus tard ; autant dire que cela ressemblera peut être à du bulgare pour un autre développeur 3 ans plus tard.</p>
<p>Et quitte à commenter votre code, autant bien le faire, en respectant une norme communément admise en PHP, j&#8217;ai nommé <a href="http://fr.wikipedia.org/wiki/Javadoc">JavaDoc</a>. Ce <a href="http://pear.php.net/manual/en/standards.php">document</a> est une bible, il est conseillé, sous peine de torture.</p>
<h2><a href="http://fr.wikipedia.org/wiki/Factorisation_(informatique)">Factoriser son code</a></h2>
<p>Ce point coule vraiment de source (mais rarement appliqué). Combien de fois suis-je tombé sur des projets ou la meme chose était codée dans 5 fonctions (et donc 5 fois avec des bugs, même souvent différents !) ?</p>
<p>Donc, vu qu&#8217;un développeur poilu code aussi en POO (oui, le premier point), factoriser son code c&#8217;est aussi utiliser de l&#8217;<a href="http://fr.wikipedia.org/wiki/H%C3%A9ritage_(informatique)">héritage de classe</a>.</p>
<h2><a href="http://fr.wikipedia.org/wiki/%C3%89vidence">Concentrer la configuration</a></h2>
<p>Toute configuration (j&#8217;entend par la des <a href="http://fr.php.net/define">define()</a>, des <a href="http://fr.php.net/manual/fr/language.variables.scope.php">variables globales</a>, meme si c&#8217;est très mal, ou toute variables que l&#8217;on peut modifier) doit être séparée du code et concentrer dans un fichier ou plusieurs fichiers dans un répertoire différent, la mettre en haut d&#8217;une classe est une absurdité !</p>
<p>De même, même si c&#8217;est aussi évident, ce fichier ou répertoire ne doit pas être consultable par les internautes (en dehors du htdocs).</p>
<h2><a href="http://fr.wikipedia.org/wiki/R%C3%A9gionalisation_de_logiciel">Localiser son code</a></h2>
<p>Personne ne sait de quoi demain sera fait, votre super site peut devenir demain un tel succès que des anglophones veuillent, eux aussi, profiter de cette merveille. Je pense qu&#8217;à ce jour, j&#8217;ai du assister à plus de 10 fois à un rush pour recoder tout un site en anglais.</p>
<p>Pour éviter ça, un reflexe simple, localiser son code, en utilisant des outils comme <a href="http://www.gnu.org/software/gettext/">Gettext</a>, <a href="http://developers.sun.com/dev/gadc/technicalpublications/articles/xliff.html">XLIFF</a> ou <a href="http://www.potu.com/man/doc.trolltech.com/4.0/linguist-manual.html">Qt Linguist</a>. &lt;radottage&gt;Les frameworks actuels gèrent tous ça&lt;/radottage&gt;</p>
<h2><a href="http://fr.wikipedia.org/wiki/Analyse_fonctionnelle_(conception)">Réfléchir avant de coder</a></h2>
<p>Ce point est très subjectif, je sais. Mais c&#8217;est un point essentiel du succès d&#8217;un développement. C&#8217;est très tentant de se jeter dans son éditeur, au début d&#8217;un projet, pour mettre les mains dans le camboui.</p>
<p>Résistez à la tentation et jetez sur papier ou sur <a href="http://fr.wikipedia.org/wiki/Unified_Modeling_Language">UML </a>votre réflexion &#8230; ca prend 10 minutes pour chaque classe et ca vous sauve souvent 2 heures de prise de tête !</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.juliencrouzet.fr/205/10-regles-qui-separent-un-developpeur-dun-webmaster/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
	</channel>
</rss>
