Publication de Coat::Persistent 0.200

Je viens d’uploader Coat::Persistent sur CPAN.

Voila une bonne chose de faîte, c’est en quelque sorte une manière de boucler la présentation des Journées Perl 2009 et le problème technique qui s’était posé.

Cette version propose les changements suivants :

  • Mention de la licence “perl” dans Makefile.PL (bug #46912)
  • Ajout d’un fichier CHANGES (bug #46913)
  • Support de l’option store_as pour les attributs persistants
  • Module Coat::Persistent::Types::MySQL qui fournit les types et les coercitions correspondantes pour les types de données MySQL Date et DateTime

Voici un petit exemple de code qui montre les possibilités de cette nouvelle version :

Reprenons notre chameau utilisé pour illustrer la présentation, nous allons lui ajouter une date de création, que l’on souhaitera manipuler sous forme de timestamp dans le code de l’application, et stocker sous forme de MySQL DateTime dans la base.

package Camel;
use Coat;
use Coat::Persistent;
use Coat::Persistent::Types::MySQL;

has_p name => (isa => 'Str');
has_p age => (age => 'Int');

has_p created_at => (
  is => 'rw',
  isa => 'Int',
  store_as => 'MySQL:DateTime',
);

Jouons maintenant avec cette classe et observons le comportement de l’accesseur created_at :

Perl> use Camel
Perl> my $c = Camel->find(3)
$Camel1 = Camel=HASH(0x9967028);

Perl> $c->created_at(time)
1245413521

Perl> $c->save
3

Maintenant regardons le contenu de la base de données pour le camel d’id 3

sqlite> select created_at from camel where id = 3;
2009-06-19 14:12:01

Au passage, on notera un effet de bord assez apréciable de cette double coercition entre type réel et type de stockage : on peut très bien assigner une valeur formattée à created_at au lieu d’un timestamp. La coercition interviendra dans l’autre sens, et notre objet aura toujours un timestamp :

Perl> $c->created_at('1979-11-20 20:20:00')
311973600

Mission complete j’ai envie de dire ;)

Update: Suite à la remarque de oz dans les commentaires, j’ai publié la version 0.210 qui propose un module Coat::Persistent::Types afin de définir tout plein de types de Date et les coercitions qui vont bien

De la bonne façon de manipuler le temps avec Coat::Persistent

Soit la situation suivante : vous avez une classe qui modélise une table de votre base de données. Cette classe possède un champ de type date.

Comment faire pour pouvoir utiliser côté Perl, un timestamp et stocker en base une date formatée pour la base de données ?

C’est le problème que je me suis posé récemment avec Coat::Persistent. Plus exactement, ce problème s’est posé presque de lui-même pendant ma présentation aux Journées Perl 2009, suite à une question du public.

En fait, je n’avais que la moitié de la solution, et depuis, je me suis pris d’un défi pour résoudre correctement ce problème avec Coat::Persistent.

Je vous propose de voir ensemble comment faire.

Objectifs

  • Utiliser le champ date comme un entier dans le code Perl
  • Ne pas avoir a se soucier de son format de stockage

Dans sa version actuelle, Coat::Persistent ne fait pas de différence entre la valeur assignée a un attribut d’un objet et celle stockée en base. Il nous est donc impossible de réaliser notre objectif de manière élégante sans modifier Coat::Persistent.

La bonne façon de permettre cette fonctionnalité serait donc de dire qu’un attribut peut avoir un type propre (isa) et un type de stockage. On aurait donc quelquechose comme ça :

has_p created_at => (
    is => 'rw',
    isa => 'Int',
    store_as => 'DateTime',
);

Un attribut ainsi déclaré serait donc conscient que sa valeur mémoire (celle de l’objet instancié) est différente de celle stockée en base. Toute la logique de conversion qu’elle soit dans un sens ou dans l’autre serait donc gérée par Coat::Persistent, et non pas par l’utilisateur.

Tout cela est réalisable en utilisant une coercition bi-directionnelle. Derrière ce mot barbare se cache un principe finalement assez simple : une valeur x doit être convertible d’un type A vers un type B, et reciproquement.

Coat permet de définir des coeriction via le mécanisme de types utilisateurs. La subtilité est donc de :

  • Avoir une coercition de définie pour pouvoir convertir une valeur du type de l’attribut vers une valeur du type de stockage (qui interviendra avant un save)
  • Avoir une coercition de définie pour pouvoir convertir une valeur du type de stockage vers une valeur du type de l’attribut (qui interviendra après un find)

Voyons maintenant comment écrire ces types et leur règle de coercition respectives pour le coupe Int,DateTime

Nous allons commencer par définir le type DateTime que nous voulons utiliser pour représenter le format de stockage des date dans une table MySQL (YYYY-MM-DD HH:MM:SS).

subtype 'DateTime'
    => as 'Str'
    => where { /^\d\d\d\d-\d\d-\d\d \d\d:\d\d:\d\d$/ };

Un attribut de type DateTime est donc un attribut de type Str et dont la valeur respecte la regexp fournie.
Maintenant il nous faut écire la règle de conversion d’une valeur Int vers une valeur DateTime :

coerce 'DateTime'
    => from 'Int'
    => via {
        my ($sec, $min, $hour, $day, $mon, $year) =
            localtime($_);
        $year += 1900;
        $mon++;
        $day = sprintf('%02d', $day);
        $mon = sprintf('%02d', $mon);
        $hour = sprintf('%02d', $hour);
        $min = sprintf('%02d', $min);
        $sec = sprintf('%02d', $sec);
        return "$year-$mon-$day $hour:$min:$sec";
    };

Le type Int est un type standard, nous n’avons donc pas besoin de le définir. Nous avons seulement besoin de mettre en place une coercition depuis le type DateTime vers le type Int :

coerce 'Int'
    => from 'DateTime'
    => via {
        my ($year, $mon, $day, $hour, $min, $sec) =
             /^(\d{4})-(\d\d)-(\d\d) (\d\d):(\d\d):(\d\d)$/;
        $year -= 1900;
        $mon--;
        return mktime(
            int($sec), int($min), int($hour),
            $day, $mon, $year);
    };

Bien, tout ce code est intéressant, mais est-ce réellement à l’utilisateur de l’ORM de le définir ? Je ne crois pas, sa place serait idéale dans un jeu de types prédéfinis.

Pourquoi pas proposer une module Coat::Persistent::Types avec tous les types nécessaires ? Cela me semble bien plus élégant.

Imaginons donc que les types et coercitions définis ci-dessus seraient présents dans, Coat::Persistent::Types::MySQL. Le type pourrait même se nommer 'MySQL:DateTime' au lieu de 'DateTime'.

L’utilisateur pourrait donc faire tout simplement :

package Stuff;
use Coat;
use Coat::Persistent;
use Coat::Persistent::Types::MySQL;

has_p created_at => (
    isa => 'Int',
    store_as => 'MySQL:DateTime',
);

Et le tour serait joué !

Il ne resterait alors qu’une seule chose à faire : patcher la mécanique de sauvegarde de Coat::Persistent pour que les valeurs utilisées dans le SQL puissent être converties si nécessaire.

Cela peut se faire très simplement en introduisant la notion de valeur de stockage. Cette valeur serait égale à celle de l’attribut si aucun store_as n’est défini, elle serait égale à la coercition adéquate sinon.

Bien, maintenant que ce problème est résolu, il ne me reste plus qu’à patcher Coat::Persistent et à publier une nouvelle version avec toutes ces bonnes calories intellectuelles…

Et de 500

Un petit billet d’auto-mégalomanie-qui-n’intéresse-personne, parfois, c’est rigolo.

500

Et c’est Nicolas qui gagne, saluons la réactivité ;)

Coat::Persistent aux Journées Perl 2009

Je reviens à l’instant des Journées Perl 2009. La conférence se tenait au Carrefour Numérique de la Cité des Sciences et de l’Industrie, nous y avions deux salles très confortables. Je vous livre à chaud quelques impressions (ce billet n’est pas une couverture de l’ensemble de la conférence).

A noter au passage que d’après ce que m’a dit Sébastien Déseille – vice-président des Mongueurs et organisateur de l’événement – ces salles sont grâcieusement prétées à l’association, ce qui a permi de rendre cette conférence entièrement gratuite. Une belle initiative qui méritait d’être salluée.

J’ai d’abord assisté à la présentation de Philippe « BooK » Bruhat sur les opérateurs secrets de Perl : il s’agit d’un cocktail explosif de Perl, d’ASCII Art, de Star Wars et d’humour – avec un zeste de Goatse.

Finalement, BooK nous a montré comment on peut combiner différents opérateurs entre eux et avec les jeux de précédence, obtenir de nouveaux opérateurs, ou même des constantes.

L’immagination semble être la seule limite à cette véritable chasse au trésor. Quelques exemples pris sur le vif :

  • Bang Bang : !! $anyvalue : retourne l’expression booléenne de $anyvalue
  • Inch Worm : ~~ @anylist : retourne l’expression scalaire de @anylist
  • Goatse : $count =()= $regexp : Retounre le nombre de match dans la $regexp sur $_

Je vous renvoie aux slides de BooK Pour plus de détails (et surtout pour les illustrations croustillantes).

Après la pause déjeuner, c’était au tour de Coat d’être présenté par SébastienDéseille.

Pour sa présentation, Sébastien s’est donné comme défi de reprendre la série d’articles publiée sur ce blog et dédiée à l’apprentissage de Moose afin de l’adapter avec Coat. On a ainsi pu découvrir comment faire de l’objet avec Coat et avoir les bases nécessaires à l’apprentissage de Coat::Persistent.

J’ai donc ensuite présenté le petit frère Coat::Persistent dont voici les slides :

La vidéo de la présentation sera probablement en ligne prochainement, certainement par ici.

Sebastien Déseille Présente Coat

Dans l’ensemble la présentation s’est bien déroulée (du moins je l’espère :-).

J’aurais juste dû choisir un autre exemple pour la coercition car le mien ne correspondait pas à quelquechose de convenable en pratique. Lorsqu’on s’en rend compte en pleine présentation suite à une question du public ce n’est pas très agréable.

Du côté des bonnes surprises, Philippe Bruhat m’a parlé de son module Test::Database qui m’à tout l’air d’être le module manquant du jeu de test de Coat::Persistent : il permet de d’obtenir un pool de $dbh disponibles sur la machine courante, pour une série de drivers. C’est tout simplement l’outil révé pour écrire le jeu de tests unitaires de Coat::Persistent (pour l’instant je suis contraint à faire tourner les tests uniquement avec le driver CSV). A suivre donc.

Twitter devient une source d’information selon Le Monde.fr

Un article sur le site du Monde souligne que Twitter tend à devenir une source d’information à part entière. On est dans l’idée de ce que j’évoquais récemment en réfléchissant sur le phénomène Twitter.

Cela étant dit, on voit bien sur Twitterholic.com qu’avant les sources d’information sérieuses, la masse se dirige avant tout vers le futile : Ashton Kutcher et Britney Spears étant largement devant CNN Breaking News ou Barack Obama par exemple.

Nouvelle version de Coat::Persistent : 0.104

En travaillant sur mes slides pour FPW 2009, je me suis penché un peu sur le code de Coat::Persistent histoire que tout soit bien propre.

Du coup, j’en ai profité pour modifier subtilement la gestion des drivers DBI. En effet, comme me l’avait fait remarquer Sébastien Déseille dans un échange de mails (Sébastien présentera le module Coat), uniquement les drivers MySQL et CSV étaient supportés alors qu’un simple patch d’une ligne permettait de faire fonctionner C::P avec SQLite.

Il est vrai qu’intrinsèquement, rien n’interdit d’autres drivers : le SQL généré est standard puisque produit par SQL::Abstract, et les séquences sont gérées par DBIx::Sequence et ne reposent donc pas sur le SGBD.

La seule difficulté était donc de maintenir une liste de drivers de la bonne façon. J’ai opté pour un compromis :

  • D’une part, plutôt que de lister en dur dans le code de C::P la liste de tous les drivers DBI potentiellement compatibles, j’ai préféré ne lister par défaut que ceux pour lesquels je sais que tout fonctionne bien
  • D’autre part, le module propose une interface pour laisser le programme appelant modifier ce registre de drivers, il peut ainsi – sans patcher C::P – modifier ou ajouter les drivers connus

La documentation a été mise à jour et montre l’usage des nouvelles méthodes drivers(), get_driver() et add_driver().

Vers une étude du phénomène Twitter

Si Twitter est en pleine croissance en France, il n’a pas encore le succès qu’il a obtenu outre-atlantique chez nos amis américains. Je vois deux raisons qui expliquent cela :

  • Le succès exponentiel de Facebook dans notre pays, qui a su très vite séduire la masse des internautes français
  • La mauvaise connaissance de Twitter chez les internautes français, qui n’en perçoivent pas l’intérêt

Discutter du premier point n’aurait pas vraiment de sens, par contre, le second point m’intéresse :

  • pourquoi Twitter est-il un service novateur ?
  • en quoi Twitter a-t-il marqué un virage dans la consommation d’Internet ?
  • qu’est-ce que Twitter apporte à l’utilisateur ?

Je pense qu’en tentant de répondre à ces questions, on peut mieux expliquer le phénomène Twitter.

Twitter n’est pas ce qu’il croyait être

twitter bird

Je me souviens de ce qu’on disait lorsque Twitter a commencé à faire du bruit en France, on doutait par ci et par là de l’intérêt même d’un service de micro-blogging. En gros, l’idée qui revenait parmi les réfractaires était du genre « raconter sa vie sur Internet ne m’intéresse pas, alors la raconter en 140 caractères, encore moins ! »

Si c’était effectivement le but premier du service, ce n’est plus du tout son intérêt aujourd’hui. Twitter a dépassé Twitter, si on peut dire, un peu comme une partition de musique ou un tableau prend une vie propre, indépendante de son auteur.

Aujourd’hui, Twitter, c’est le réseau social du temps réel. Sorte de voie rapide de l’information dédiée à la propagation intra-réseaux.

De plus en plus Twitter sert à relayer des informations qui intéressent l’ensemble, et non plus des détails sur la vie privée de l’individu. Twitter n’est plus le « 36 15 ma-vie » en petit, c’est votre journal de 20h personnalisé en temps réel (avec les dérives que ça implique).

En cela, je trouve pour ma part que Facebook s’inscrit plus dans cette démarche exhibitioniste qui consiste à raconter sa vie via des status, alors que Twitter tend à s’en écarter au profit du partage de contenu et d’information.

Des limitations qui créent de la richesse

Le succès de Twitter réside dans les limitations qui ont été imposées : peu de caractères, donc des messages courts, donc une information réduite à son essentiel, pas de superflu, une propagation facile.

On lit vite, on comprend vite, on fait suivre vite. C’est du bon sens finalement.

Avec le recul, on a l’impression que la recette est simple : faire le service minimum (publication de messages), avec le maximum de contraintes (140 caractères et rien d’autre) et l’ouvrir entièrement (une API complète en lecture/écriture et gratuite).

Il en résulte deux choses : beaucoup d’utilisateurs et beaucoup d’applications, ce qui crée un cercle vertueux.

Une redécouverte du réseau

Ce socle qu’a proposé Twitter, combiné à l’ouverture du réseau aux applications tierces, a permis de nombreuses utilisations novatrices.

La simplicité du service s’adapte particulièrement bien à l’Internet mobile tel que celui que l’on utilise avec l’iPhone. Utiliser une application Twitter sur son iPhone revient presque à rendre la création de contenu Internet aussi simple que l’envoi d’un SMS. L’information ne se contente pas de se propager rapidement, elle se crée tout aussi simplement.

Certes on ne parle pas ici de création de contenu évolué, mais plutôt d’un type de contenu pop-corn : une photo volée dans une rue, une citation amusante entendue dans le métro ou encore une critique de cinéma écrite sur le vif, dès la sortie de la salle.

On redécouvre donc Internet grâce aux plaisirs cumulés du temps réel, du réseau social et du less is more, en voici quelques exemples parlants (n’hésitez pas à poster vos applications Twitter préférées en commentaires)

  • Twitturly : les URL les plus présentes sur le service, le successeur de Digg ?
  • TweetScan : le moteur de recherche temps réel des discussions Twitter
  • TwitPic : le partage de photo automatisé sur Twitter, avec un iPhone, c’est la combo magique.
  • Twist : les tendances Twitter, comparer ce qui se dit, les sujets populaires du moment
  • Yoolink : la plateforme de partage de liens, qui notamment permet d’automatiser la publication de lien sur Twitter
  • Topsy : Le moteur de recherche basé sur les URL twittées, assez bon

Twitter semble s’imposer progressivement comme le canal d’information temps réel que chaque institution se doit de posséder (ex: Obama, La Marine Nationale, le Figaro, CNN, etc).

A mon sens, sans s’en rendre compte, Twitter a apporté une véritable révolution aux usages d’Internet. Cela ne semble pas encore évident dans le paysage du numérique français mais pourrait bien le devenir.

Ouverture de l’intranet Chinois

En fait, c’est une façon de voir que de dire que le gourverment Chinois a coupé l’accès Internet aux sites Twitter, Flickr, Bing, Live.com, YouTube et Hotmail.

On peut aussi voir la chose en se disant que le Vénérable Intranet Nationnal du Parti a changé ses sources de contenu, non ? J’ai pas bon ?

Get Adobe Flash playerPlugin by wpburn.com wordpress themes