Feeds:
Articles
Commentaires

Je viens de lire la série de twitts de morgan_it, qui commence ici sur le repli communautaire de la génération Y (soit les gens qui sont nés entre 1977 et 1995). Et j’y ai un peu réfléchi.

Chaque génération crée ses communautés

Premièrement, pour qu’il y ai un repli communautaire, il faut déjà qu’il y ait eu une phase d’ouverture vers l’extérieur. Cette phase, si elle existe, aurait eu lieu durant les deux générations précédentes (génération X, 1959-1977, et génération baby-boom, 1943-1959). Or pour moi, cette phase, plus qu’une phase d’ouverture, est plutôt une phase de destruction des anciennes communautés. Durant cette période, le village est détruit pour laisser place à la ville : par l’exode rural, des gens qui ont vécu dans de petits villages se retrouvent dans des grandes villes. Cela entraîne la disparition de certains rituels communautaires, par exemple la messe le dimanche (ce qui provoque le recul de l’église, qui perds l’une de ses raisons premières : rassembler une communauté).

Mais l’homme est un animal de meute (oui, je pousse un peu plus loin l’expression d’Aristote « l’homme est un animal social »). La perte de la communauté villageoise détruit la meute. La génération du baby-boom se doit de retrouver, sinon une meute, au moins un groupe. Et c’est dans l’engagement politique que cette génération va reconstruire des communautés. On aura les libertaires, les féministes, les gauchistes (de toutes les mouvances possibles et inimaginables…), les hippies… Néanmoins, ces engagements politiques vont se heurter à la réalité (et oui, tout n’est ni tout blanc, ni tout noir) : mouvements violents d’extrême gauche, crimes des régimes soi-disant communistes, SIDA, plafond de verre…

La génération suivante (la génération X) rejette alors l’action politique strictement politique, et va tenter de se fédérer par des grandes actions associatives : marche des beurs, concert Band Aid, resto du coeur… Là encore, de nouvelles communautés se forment. On peut noter que cette génération est également la génération de la « crise », ce qui peut également la pousser non pas à réclamer (ce que faisait la génération précédente) mais à sauvegarder (d’où un élan vers des actions solidaires). Mais au final, l’effet est le même, des communautés se forment.

Enfin on arrive à la génération Y (la mienne ^_^). Là encore, cette génération va voir l’échec (relatif) de la génération précédente : émeutes en banlieue (1991), associations débordées par la demande (les restos du coeur), dirigeants de ces mêmes associations qui ne sont pas des saints (Bernard Kouchner, Julien Dray…). Et cette génération forme alors de nouvelles communautés.

Ce qui est intéressant avec ces nouvelles communautés, c’est que d’une part, et contrairement aux communautés des deux générations précédentes, ces communautés ne se fondent plus sur une vision de la société ou sur un rêve commun mais sur des passions communes. Et que d’autre part, et en continuité avec les grands mouvements des année 1970 et 1980, ces communautés sont mondiales.

En fait ces nouvelles communautés sont très étranges à décrire car elles sont à la fois locales (le groupe d’amis/de passionnés proche) et mondiales (grâce à internet). Par exemple je suis un passionné de skateboard. D’une part j’ai mon petit groupe d’amis avec qui je fais du skate. Et d’autre part je regarde des vidéos de skate tournées aux États-Unis, je discute sur des réseaux sociaux avec des gens qui aiment le skate…

Au final, en trois générations, on est passé de communautés qui se définissaient par le territoire (le village, et on n’aime pas le village d’à coté) à des communautés qui se définissent par leur passion (par exemple les skateurs, et on n’aime pas les rappeurs –> oui, c’est un peu caricatural).

Les conséquence des communautés de la génération Y

D’une part, mais c’est dans la nature des relations entre générations, ces communautés sont méprisés par la génération précédentes « ces jeunes sont renfermés sur eux même et ne s’intéressent pas aux problèmes du monde ». On a eu la même chose sur la génération X « ces jeunes ne s’intéressent pas à la politique » et sur la génération du baby-boom « ces jeunes ne connaissent pas la dureté de la vie, et ils font les malins en faisant de grands discours politiques ». Et inversement. La nouvelle génération Y dit à l’ancienne « tes associations c’est bien joli mais ça n’a pas été très efficace ». Comme la génération X a dit aux baby-boomers « le rêve politique c’est bien joli mais cela a provoqué beaucoup de massacres et d’attentats ». Et comme les baby-boomers ont dit à la génération d’avant « pouvoir consommer c’est bien joli mais c’est un peu vide non ? »

À noter, on peut voir cette lutte entre générations dans le domaine des logiciels libres et de l’open source dans l’opposition entre la vision de Richard Stallman (génération baby-boom), plus politique, et la vision de Linus Torvalds (génération X), que nous dirons plus pragmatique.

D’autre part, les communautés de la génération Y vont bientôt atteindre leurs limites. C’est à dire que c’est bien joli d’avoir son petit groupe de passionnés de musique électronique des années 1978-1981, de faire des festivals, de participer à des conférences, mais pendant ce temps, on a un gouvernement qui vote des choses en notre nom. Cette conscience a commencé à se réveiller chez la jeune génération notamment avec le débat sur Hadopi. Mais ce n’est pas gagné : la catégorie de population qui s’est le plus abstenue aux élections européennes de 2009, ce sont les 18-35 ans, soit… La génération Y.

Conclusion

L’homme est un animal qui se sent bien dans une communauté relativement restreinte (« meute ») et tout homme finit par se retrouver dans une communauté restreinte. C’est pourquoi il n’y a pas de repli communautaire d’une génération par rapport à une autre, juste la création de nouvelles communautés, différentes de celles de la génération précédente. Chaque génération crée ses propres communautés, avec leurs avancées et avantages, et leurs limites. Limites que la génération suivante tente de dépasser en créant de nouvelles communautés.

Publicités

Aujourd’hui j’ai du générer un package PEAR pour un plugin Symfony de ma composition. Ce plugin est en fait un admin-generator amélioré. Pour créer un package PEAR, il faut d’abord créer un fichier package.xml à la racine du plugin. Cela est bien expliqué dans le chapitre 17 du Definitive Guide To Symfony (désolé, c’est en anglais).

Le problème, c’est que dans ce fichier package.xml il faut taper toute l’architecture du plugin. Et pour un admin generator modifié, cela commence à faire beaucoup (une vingtaine de fichiers). C’est pourquoi, au lieu de tout taper bêtement à la main, nous allons utiliser un logiciel pour générer le fichier package.xml

On va donc :

  • récupérer le générateur automatique du fichier package.xml
  • générer le fichier package.xml et le rendre conforme à Symfony
  • générer le package

Récupération du générateur automatique du fichier package.xml

Je suppose que vous avez déjà installé PEAR (# apt-get install php-pear). Comme la version de PEAR fournie par Squeeze (ah oui, je suis passé à Squeeze récemment) et donc à fortiori celle fournie par Lenny n’est pas suffisante, il nous faut d’abord mettre à jour PEAR par la commande suivante :

# pear upgrade pear

Et après on installe le générateur automatique du fichier package.xml :

# pear install PEAR_PackageFileManager
# pear install PEAR_PackageFileManager_cli

Ensuite, vous taper pfm dans une ligne de commande. S’il vous renvoie bash: pfm: command not found, il va falloir encore souffrir un peu pour installer le générateur…

Note : Les instructions en italique sont à suivre seulement si la commande pfm ne marche pas.

On récupère d’abord le générateur pfm et on le met dans le dossier d’installation de PHP, ce qui donne les commandes suivantes. On se place d’abord dans le répertoire d’installation de PHP :

# cd /usr/share/php

On récupère la dernière version du fichier pfm (à vérifier dans les sources de PEAR, au moment où j’écris, c’est la version 1.21) :

# wget http://cvs.php.net/viewvc.cgi/pear/PEAR_PackageFileManager_Cli/scripts/pfm?revision=1.21&view=co

Et on change le nom du fichier en pfm :

# mv pfm\?revision\=1.21 pfm

Note : le fichier pfm doit obligatoirement se placer dans le dossier PHP dans lequel est installé PEAR.

Après on rend le fichier pfm exécutable en ligne de commande. Pour cela on modifie d’abord la première ligne du fichier pfm pour que script s’execute avec l’executable PHP. Ainsi chez moi :

#!@php_bin@

devient :

#!/usr/bin/php

Ensuite on crée un lien dans le dossier /usr/bin pour rendre le fichier pfm exécutable en ligne de commande :

# ln -s /usr/share/php/pfm /usr/bin/pfm

Voilà, vous pouvez désormais utiliser le logiciel pfm

génération du package.xml

Nous allons maintenant générer le fichier package.xml. Pour cela, on se place d'abord dans le dossier du plugin puis on lance pfm :

$ cd repertoire_racine_du_futur_package
$ pfm

Après il suffit de répondre aux questions que pose le programme (on sens la flemme du mec qui n'a pas envie de détailler toutes les questions... Bon, comme je suis gentil, et pour vous préparer psychologiquement, voici un lien vers le détail des questions posées). Vous terminez le questionnaire en répondant 14 (save & quit) à la dernière question et c'est bon, votre fichier package.xml est généré.

Néanmoins, il nous reste encore un petit détail à régler pour que le fichier package.xml devienne le fichier package.xml d'un plugin Symfony. Pour cela, il suffit de changer, pour toutes les balises <file>, l'attribut role="php" en role="data" (un recherche et remplacer devrait faire l'affaire :))

Votre fichier package.xml est prêt !!!

génération du package

Une simple commande, à effectuer dans le dossier racine de votre plugin (là où est votre fichier package.xml) et votre package est généré :

$ pear package

Conclusion

Ouf, on y est arrivé. Peut-être qu'en tapant tout à la main cela aurait été plus rapide 😉 ?

Dans une ancienne publication, je vous expliquais comment écrire Chinois (et/ou Japonais) sous Debian. Et bien aujourd’hui allons plus loin et donnons-nous la possibilité d’écrire Chinois dans des documents Latex.

Note : cet article a pour pré-requis l’installation d’une méthode d’écriture du Chinois (voir ecrire Chinois et/ou Japonais sous Debian)

Installation de CJK

Tout d’abord, il nous faut installer quelques packages pour que Latex puisse comprendre les caractères Chinois :

# apt-get install latex-cjk latex-cjk-chinese

Note : CJK est un acronyme signifiant Chinese, Japanese, Korean. Ainsi, semblable à latex-cjk-chinese, il existe des packages latex-cjk-japanese et latex-cjk-korean.

Charger les packages dans votre document Latex

Note : partie inspirée par le site des tuteurs de l’ENS, qui est une mine d’or en ce qui concerne Latex.

Ensuite, pour pouvoir écrire chinois, il suffit de rajouter les lignes suivantes en tête de votre document Latex :

\usepackage[cjkgb]{ucs}
\usepackage[utf8x]{inputenc}
\usepackage[C10,T1]{fontenc}
\DeclareFontSubstitution{C10}{gbsn}{m}{n}

Vous pouvez désormais taper vos textes en Chinois avec SCIM et les compiler avec Latex.

EDIT Note : Faite attention, vous ne pouvez taper que des caractères simplifiés. Taper un caractère non simplifié provoquera une erreur à la compilation.

Astuce et Bonus Style

Voir les cours de Kidtonik pour comprendre le titre de cette partie

Pour écrire en pinyin en latex, il faut charger le package pinyin en ajoutant la ligne suivante en tête de votre document .tex :

\usepackage{pinyin}

Après, il suffit de taper, par exemple pour wàn, \wan4. Ainsi pour taper la phrase 我很高兴 (je suis content) en pinyin dans un document latex, il faut taper :

\wo3 \hen3 \gao1\xing4

Conclusion

Voilà, vous pouvez désormais utiliser Latex pour écrire vos documents en Chinois, avec le pinyin.

Toujours Symfony, toujours… Comme dit dans la précédente publication, je travaille en ce moment sur plusieurs applications web. Chacun de ces applications me (nous) ont fait faire du symfony propel:init-admin de manière industrielle.

Pour tous ces init-admin, un fichier de configuration global unique de type generator.yml pour l’application que l’on puisse surcharger avec les fichiers generator.yml des modules est un plus. Cela permet par exemple de faire en sorte que la forme de tous les champs « created_at » de nos tables soit stockée à un unique endroit.

Nous allons donc intégrer un fichier globalgenerator.yml dans les fichiers de configuration de symfony, qui sera chargé avant le generator.yml.

Cela se fera en deux étapes :

  • 1° étape, surcharger la classe sfGeneratorConfigHandler par une classe monGeneratorConfigHandler
  • 2° étape, modifier la classe monGeneratorConfigHandler pour prendre en compte un nouveau fichier de configuration

1° étape, surcharger la classe sfGeneratorConfigHandler par une classe monGeneratorConfigHandler

Tout d’abord, il faut savoir que les fichiers de configuration sont lus par des Handlers, qui sont des classes PHP situées dans vendor/symfony/lib/config en partant du vendor. Chaque fichier de configuration a son propre Handlers, les liens entre les fichiers de configuration et leurs Handlers étant fait dans le fichier config_handlers.yml situé dans vendor/symfony/lib/config/config.

L’idée va être dans un premier temps de surcharger, et le Handler du fichier generator.yml, le bien nommé sfGeneratorConfigHandler, et le config_handlers.yml.

On commence par copier le fichier sfGeneratorConfigHandler.class.php (situé dans vendor/symfony/lib/config) dans le répertoire lib de votre projet (ou à toute autre endroit où vous êtes sur qu’il sera chargé par Symfony).

Renommez ensuite ce fichier en, par exemple monGeneratorConfigHandler.class.php et éditez le pour que l’entête du fichier ressemble à cela :

<?php

class monGeneratorConfigHandler extends sfYamlConfigHandler
{

Note : pour les puristes on pourrait faire en sorte que la classe monGeneratorConfigHandler étende la classe sfGeneratorConfigHandler.

Bon, après, on va faire en sorte que ce soit ce Handler qui soit appelé pour traiter les fichiers generator.yml. Pour cela, on crée un fichier config_handlers.yml dans le dossier config de l’application concernée (soit apps/monApplication/config) et on le remplit avec les lignes suivantes :

modules/*/config/generator.yml:
  class:    monGeneratorConfigHandler

Voilà, désormais, lorsque vous chargez un module avec un generator, c’est notre Handler qui est appelé. Nous allons maintenant éditer ce Handler pour qu’il puisse prendre en compte un fichier de configuration supplémentaire.

2° étape, modifier la classe monGeneratorConfigHandler pour prendre en compte un nouveau fichier de configuration

On va faire en sorte que le Handler prenne en compte le fichier globalgenerator.yml situé dans le dossier config de notre application (si ce fichier existe).

EDIT Note : n’appelez pas le fichier global generator.yml. En effet, placer un fichier generator.yml dans le dossier config de l’application fait crasher la dite application.

Pour cela, on rajoute quelques lignes à la méthode execute de notre classe monGeneratorConfigHandler, ainsi cela :

  ...
  public function execute($configFiles)
  {
    // parse the yaml
    $config = self::getConfiguration($configFiles);
    if (!$config)
    ...

devient cela :

  ...
  public function execute($configFiles)
  {
    
    $advancedConfigFiles = $configFiles;
    if (file_exists(sfConfig::get('sf_app_config_dir').'/globalgenerator.yml')) {
      $advancedConfigFiles = array_merge(
             array(sfConfig::get('sf_app_config_dir').'/globalgenerator.yml'), 
             $configFiles);
    }
    // parse the yaml
    $config = self::getConfiguration($advancedConfigFiles);
    if (!$config)
    ...

Note : la méthode sfConfig::get(‘sf_app_config_dir’) nous permet de récupérer le chemin du dossier config de l’application. D’autres variables peuvent être récupérées par cette manière. On peut notamment les voir dans le menu config/settings de la barre symfony apparaissant dans le navigateur web lorsque l’on charge une page de l’application.

Voilà, désormais, si le fichier globalgenerator.yml existe dans le dossier config de l’application, le Handler ira d’abord le rechercher puis le surchargera avec le generator.yml du module.

Conclusion

Nous avons donc vu comment créer un fichier de configuration global pour tous les generators de notre application. On peut bien entendu penser à surcharger de cette manière d’autres fichiers de configuration (par exemple view.yml)

Un mois sans publications, que le temps passe vite !!! En effet, ces dernières semaines ont été assez… Chargées. J’ai notamment trois développements d’application web en cours, ce qui ne laisse pas beaucoup de temps pour écrire.

D’ailleurs, cette publication leur est consacrée (oui, le boulot, toujours le boulot…). Pour ces projets, je, enfin nous (je ne suis pas tout seul à développer) utilisons le cadriciel Symfony.

Et récemment, j’ai dû rajouter des méthodes aux classes du model (alias Machin et MachinPeer). C’est ce que je vais vous expliquer maintenant.

Nous allons voir trois méthodes (trois « voies ») pour ajouter des méthodes aux classes du model (classes situées dans lib/model).

  • la voie facile : ajout de méthodes à l’aide des Behaviors
  • la voie des damnés : ajout de méthodes en modifiant le model-generator
  • EDIT la voie du sage : contournement de l’ajout de méthodes par création d’une nouvelle classe

Note : Les deuxième et troisième voies permettent notamment de rajouter des méthodes statiques. La deuxième méthode est fortement déconseillée car elle modifie le coeur même de symfony.

la voie facile : ajouter des methodes à une classe du model à l’aide de Behaviors


Cette possibilité d’ajouter des méthodes à une classe machin du model a en effet déjà été prise en compte dans Symfony, cela s’appelle les Behaviors. Un behavior permet d’ajouter des méthodes d’une classe à une autre classe. Nous allons donc coder un Behavior pour notre classe machin

Il nous faut d’abord créer un plugin ce qui se traduit dans les faits par créer le dossier plugins/monPlugin à la racine de votre projet Symfony

Ensuite, on crée dans ce plugin les dossiers config et lib. Et dans ces dossiers on crée respectivement les fichiers config.php et monBehavior.class.php. On a donc l’architecture suivante :

racine du projet
    ...
    plugins
        monPlugin
            config
                config.php
            lib
                monBehavior.class.php

Bon, ensuite, dans le fichier monBehavior.class.php, on crée une classe monBehavior et dans cette classe on y met les méthodes que l’on souhaite appeler dans la classe Machin, par exemple une méthode getIdAndString() :

<?php

class monBehavior {

  public function getIdAndString($object, $con = null) {
    $id = 'get'.get_class($object).'Id';
    return $object->$id()." -  oh yeah";
  }
}

Après, on va dans le fichier config.php et on ajoute le code suivant afin de charger les méthodes de la classe monBehavior pour qu’elles soient accessibles à d’autres classes :

<?php

sfPropelBehavior::registerMethods('monBehavior', array(
  ':getIdAndString'            => array('monBehavior', 'getIdAndString'),
));

note On constate que la méthode sfPropelBehavior::registerMethods prend deux arguments, le premier le nom sous lequel le behavior sera appelé (voir ci-dessous), le deuxième est un tableau avec comme index le nom des méthodes dans la classe qui appelle le behavior, et en valeur un tableau à deux éléments contenant la classe appelée et la méthode de la classe appelée.

Bon, une fois ceci effectué, il nous faut encore charger le behavior dans la classe Machin. Cela se fait en ajoutant la ligne suivante en dessous de la classe comme ceci :

<?php

class Machin extends BaseMachin
{
}

sfPropelBehavior::add('Machin', array('monBehavior'));

Voilà, il ne reste plus qu’à activer les behaviors en remplaçant false par true à la fin de la ligne suivante du fichier config/propel.ini :

propel.builder.addBehaviors = true

Et à régénerer le model (symfony propel:build-model pour les ignares…). Vous pouvez désormais appeler la methode getIdAndString() à partir d’un objet de classe Machin.

Avantages et limites des behaviors

Le gros avantage, c’est que l’on peut ainsi faire un pseudo multi-héritage (qui n’existe pas en PHP). Une classe peut utiliser à la fois les méthodes de la classe dont elle hérite et d’une autre classe myBehavior.

La grosse limite, c’est que cela ne marche pas pour les méthodes statiques, à cause d’une limitation du language PHP.

En effet, et sans rentrer dans les détails, lors de la sortie de PHP 5, les codeurs avait pensé à une fonction __call() qui permettait de récupérer les appels à des méthodes non définies mais malheureusement cette fonction ne marche pas avec les méthodes statiques. Cela sera possible dans PHP 5.3 avec la méthode __callStatic(). Cette fonction __call() permettant aux behaviors d’être appelés, on ne peut donc pas utiliser les behaviors pour des méthodes statiques.

C’est ce qui va nous pousser, pour pouvoir ajouter facilement des méthodes à toutes les classes Peer, à plonger dans les tréfonds du model-generator…

la voie des damnés : ajouter des méthodes statiques à la classe MachinPeer du model en modifiant le model-generator


ATTENTION : cette méthode est totalement déconseillée. Elle risque notamment de vous empêcher de mettre à jour Symfony. En effet, cette méthode implique de modifier des fichiers au coeur même de Symfony. Donc si vous pouvez vous en passer…

EDIT : Préférez largement la troisième voie (voir fin de la publication) à cette méthode

En gros, cette méthode consiste à rajouter directement les méthodes dans les fichiers de chargement des méthodes prédéfinies des classes peers afin qu’elles soient générées en même temps que le model. Pour cela, deux fichiers nous intéressent, et ce sont en partant du vendor de Symfony, les fichiers (respirez un bon coup) :

symfony/lib/plugins/sfPropelPlugin/lib/vendor/propel-generator/classes/propel
/engine/builder/om/php5/PHP5PeerBuilder.php

et

symfony/lib/plugins/sfPropelPlugin/lib/vendor/propel-generator/classes/propel/
engine/builder/om/PeerBuilder.php

Ce qu’on va faire, c’est mettre les méthodes que l’on veut ajouter dans PHP5PeerBuilder.php et les insérer dans la classe générée dans PeerBuilder.php.

Pour cela, il faut comprendre un peu comment fonctionne la génération des classes du model. Le générateur crée d’abord une chaine de caractères vide qu’il va remplir au fur et à mesure des headers puis des methodes de la classes. Le remplissage s’effectue donc par étapes et sous-étapes, chaque étape étant représentée par une méthode add du générateur.

Nous allons donc coder nos propres méthodes add puis nous allons les ajouter dans la méthode de création du corps de la classe générée afin de générer nos méthodes automatiquement.

Tout d’abord, on ajoute une méthode add à la classe PHP5PeerBuilder du fichier… PHP5PeerBuilder.php !!! Cela ressemble à cela :

	protected function addRetrieveByString(&$script)
	{
		$script .= "
	public static function retrieveByString(\$string = null, PropelPDO \$con = null)
	{
            return null;
	}
";
	}

Vous pouvez constater que cette methode addRetrieveByString prend en argument une chaine de caractères et lui rajoute une autre chaine de caractères contenant la méthode que nous aimerions voir généré automatiquement dans les classes peers.

Après, il nous faut faire en sorte que cette méthode add soit appelé lorsque le générateur contruit la classe peer. Il faut donc ajouter la ligne suivante à la fin de la méthode addClassBody de la classe PeerBuilder dans le fichier PeerBuilder.php :

$this->addRetrieveByString(&$script);

Et voilà, on régénère le model et la fonction « retrieveByString » est ajoutée à toutes les classes Peers… Elle n’est pas belle la vie ?

Conclusion


On a donc vu deux méthodes pour ajouter des méthodes à une classe du modèle, une facile pour les méthodes non statiques, l’autre plus expérimentale et à utiliser en ultime recourt pour les méthodes statiques des classes peers.

Un dernier conseil, si vous utilisez la deuxième méthode : copier les fichiers originaux quelque part, modifier vos fichiers, générez le model puis remettez les fichiers originaux (quitte à copier vos fichiers modifiés autrepart). Cela vous permettra de garder votre Symfony « propre ».

EDIT : la troisième voie : la voie du sage, contourner l’ajout de méthodes


En fait, il existe une troisième voie (merci Jon). La solution pour rajouter des méthodes dans une classe peer sans modifier symfony (avec toutes les conséquences que cela implique), c’est de ne pas essayer de rajouter des méthodes dans la classe peer.

Bon, normalement, là, vous vous dites : il est bien gentil mais moi je veux ma méthode MachinPeer::retrieveByString() qui retourne null et que l’on puisse surcharger. Patience, cela arrive.

L’idée c’est de créer une classe à un endroit qui sera lu par symfony, par exemple dans le dossier lib à la racine de symfony. Créons donc la classe MorePeerMethods dans le fichier MorePeerMethods.class.php dans le dossier lib de symfony.

Et après, pour chaque méthode créée dans cette classe, on fait en sorte que la dite méthode vérifie d’abord qu’une méthode du même nom n’existe pas dans, par exemple, MachinPeer (ceci pour permettre la surcharge). Pour cela, on introduit un choix « if ». Ainsi en reprenant l’exemple de la méthode retrieveByString décrite au dessus, cette méthode devient dans la classe MorePeerMethods :

<?php

class MorePeerMethods {

  public static function retrieveByString($object, $string = null, $con = null) {
    if(method_exists($object.'Peer', 'retrieveByString')) {
      return call_user_func_array($object.'Peer::retrieveByString', array($string, $con));
    } else {
      return null;
    }
}

Ensuite, pour appeler cette méthode dans un action.class.php quelconque, il suffit de taper :

 MorePeerMethods::retrieveByString('Machin', $monArgument1,$monArgument2);

Au lieu de :

 MachinPeer::retrieveByString($monArgument1, $monArgument2);

Le tour est joué, tout le monde est content, et personne n’a eu à tuer Symfony

Conclusion n°2


Jon a toujours raison.

Un tout petit mémoire (14 pages) sur la machine Enigma que j’ai eu à faire pour un cours de cryptanalyse.

Vous y trouverez un bref historique de la machine Enigma, une présentation de la technique de cryptographie d’une machine Enigma simplifiée et enfin un listing de code en Python permettant de modéliser cette machine Enigma simplifiée.

Lien ver le mémoire :

Mémoire sur Enigma

Sommaire du mémoire :

  • 1. Introduction
  • 2. Historique
  • 3. Fonctionnement
    3.1 Théorie
    3.2 Mécanisme

  • 4. Modélisation d’une machine Enigma en Python
    4.1 Modélisation
    4.2 Tests

  • 5. Conclusion
  • A. Bibliographie
  • B. Diagramme de classe
    B.1 Rotor
    B.2 Reflecteur
    B.3 Enigma

  • C. Codes
    C.1 rotor.py
    C.2 reflecteur.py
    C.3 enigma.py
    C.4 test.py

EDIT : Suite au commentaire de desfrenes, j’ai corrigé la boulette qui faisait dire que le Python ne supportait pas la surchage des opérateurs dans la conclusion de l’article.

Pour un devoir à la maison que je dois rendre, j’ai programmé une machine Enigma. J’ai décidé de faire ce travail en Python, d’une part parce que c’est un langage assez simple à écrire (pas de « #include stdio », pas de « private int monEntier »…) et d’autre part parce que cela faisait un an que je n’avais pas programmé dans ce langage et qu’il fallait que je me dérouille un peu.

Préliminaires

Avant de parler plus en détail de mon expérience, je vais commencer par relater une discussion que j’ai eu récemment avec un professeur de mon école. Ce professeur avait dû apprendre le Python dans le cadre de son travail, et n’avait pas du tout apprécié ce langage. Il était en effet choqué par plusieurs choses, par exemple l’absence de typage, ou par l’impossibilité de surcharger les méthodes.

Toutes ces choses le confortaient dans l’idée de ne jamais enseigner le Python dans le cadre de ses cours. Sur le coup je n’ai pas très bien compris, parce que pour moi le Python est vraiment le language idéal pour les débutants. Cela les force à indenter, le code est clair, il n’y a rien de superflu… Surtout que dans un hors-série récent de GNU Linux Magazine j’avais lu un plaidoyer pour l’enseignement du Python à la place du C ou du Java comme premier langage.

La (dure) reprise

Et j’ai commencé à programmer. Et j’ai compris mon professeur. Première réaction : « eeuuh, ils sont où les types ??? ». Ah ben oui, en Python, tout peut être tout et n’importe quoi. Après 6 mois de Java ça fait tout drôle. Et rien ne vous dira que vous vous plantez, en tout cas pas Pydev, le greffon Python d’Eclipse.

Bon, je programme pépère… Arrive le moment de tester mon programme. Et là l’interpréteur me signale une erreur de manque d’arguments. Après recherche sur internet, je constate qu’en effet, le Python et la surcharge, cela fait deux. Là je me dis « Mais c’est quoi cette blague !!! »

Bref, j’ai eu un peu du mal à m’y remettre, et quand je pense à mon professeur, je le comprends. Cela fait plus de 10 ans qu’il programme en C, en Java. Qu’il a l’habitude de surcharger ses fonctions. Qu’il a l’habitude de déclarer ses types. Moi, après 6 mois de Java, j’ai déjà du mal alors lui…

La dernière fois que j’ai fait du Python, je venais de faire du C++ non objet (hérésie quand tu nous tiens…), le Python m’était alors apparu comme une révélation. Mais là, après 6 mois sur Java avec Eclipse (IDE grâce auquel, il faut le dire, programmer en Java se fait les yeux fermés), ce fut un tout autre son de cloche.

Ce bon vieux Python

Néanmoins, après ces désagréables surprises et un petit temps d’adaptation, quel plaisir. Parce que taper trois lignes de code pour une fonction, regarder le code, se poser la question : elle est finie là ma fonction ?, reregarder le code, et voir qu’en effet la fonction est bien terminée, c’est une sensation agréable que je ne connais qu’en Python.

Et que dire de la gestion des listes… On passe d’une chaine de caractères à une liste, on supprime, on ajoute, on permute avec bonheur. Ce qui, pour programmer une machine Enigma, est assez utile. Quand je me rappelle l’année dernière comment j’avais galéré pour écrire une sorte de parseur en C++…

Conclusion

Deux conclusions s’imposent. D’une part, en informatique, il faut toujours essayer de coder dans tous les languages que l’on a appris, et ne pas se limiter à un seul language ou deux. En effet, on prend vite des habitudes qui peuvent nous jouer des tours. Et l’on finit par rejeter des languages forts intéressants, comme mon professeur avec le Python. Et en plus on perd son sens critique vis à vis de certains langages. D’où l’apparition des débats du genre Emacs/Vi…

D’autre part, le Python, malgré ce qu’il prétend, n’est pas un language objet. Il lui manque trop de choses qui font un language objet (surcharges de toutes les méthodes et non simplement surcharge des opérateurs…). Par contre, ce language est parfait pour apprendre l’algorithmique voir la programmation objet basique. Sa simplicité permet aux débutants de se concentrer sur le code et non pas sur « est ce que je dois mettre un point-virgule ou pas ».

Mais il n’est pas suffisant en programmation objet. Je pense qu’un enseignement Python + Java serait parfait pour une école généraliste. Le seul point génant est que l’on laisse le C/C++ de coté. Mais cela permettrait d’avoir un enseignement progressif incluant toutes les notions de la programmation impérative et objet.