Coat::Persistent at FPW2009
Upcoming SlideShare
Loading in...5
×
 

Coat::Persistent at FPW2009

on

  • 2,292 views

Coat::Persistent est un ORM écrit pour Perl en s'inspirant de l'API d'ActiveRecord de Rails. Cette présentation a été tenue aux journées Perl 2009

Coat::Persistent est un ORM écrit pour Perl en s'inspirant de l'API d'ActiveRecord de Rails. Cette présentation a été tenue aux journées Perl 2009

Statistics

Views

Total Views
2,292
Views on SlideShare
2,194
Embed Views
98

Actions

Likes
0
Downloads
5
Comments
0

3 Embeds 98

http://www.sukria.net 96
http://www.slideshare.net 1
http://www.slideee.com 1

Accessibility

Categories

Upload Details

Uploaded via as OpenOffice

Usage Rights

© All Rights Reserved

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Processing…
Post Comment
Edit your comment

Coat::Persistent at FPW2009 Coat::Persistent at FPW2009 Presentation Transcript

  • Coat::Persistent Votre base de données à portées d'objets FPW 2009 – 13 Juin 2009 Alexis Sukrieh http://www.sukria.net
  • Plan
    • Le concept ORM
    • Origines de Coat::Persistent
    • Mise en place de Coat::Persistent
    • Accèder aux données (lecture/écriture)
    • Relations entre tables / modèles
    • Fonctionnement du cache
  • Le concept ORM Une méthode moderne et efficace pour manipuler les données
  • Le principe ORM
    • Un framework Objet
    • Une table devient une classe
    • Une ligne devient une instance
    • Une colonne devient un attribut
    • Le SQL est désormais une couche de bas niveau
  • Avantages
    • Moins de code pour manipuler les données
    • Plus de code pour écrire l'application
    • Factorisation du problème d'accès aux données
    • Facilités et puissance de l'approche Objet
    • Simplicité d'utilisation
  • Avantages
    • Moins de code pour manipuler les données
    • Plus de code pour écrire l'application
    • Factorisation du problème d'accès aux données
    • Facilités et puissance de l'approche Objet
    • Simplicité d'utilisation
    • Moins de SQL
  • Avantages
    • Moins de code pour manipuler les données
    • Plus de code pour écrire l'application
    • Factorisation du problème d'accès aux données
    • Facilités et puissance de l'approche Objet
    • Simplicité d'utilisation
    • Moins de SQL
    • Moins de SQL
  • Avantages Moins de SQL ??!
  • Avec du SQL ... my $sql = 'select * from table' ; my $sth = $dbh ->prepare( $sql ); $sth ->execute or die $! ; while ( my $row = $sth ->fetchrow_hashref()) { # ici on joue avec $row ... } On a donc 4 lignes pour pouvoir itérer sur des enregistrements...
  • CATS DON'T LIKE SQL
  • Avec Coat::Persistent foreach my $obj (Table->find()) { # ici on joue avec $obj ... } Je crois que le chat s'est calmé...
  • Pourquoi vouloir moins de SQL ?
    • Pour les tâches répétitives, SQL est lourd
    • Chaque fois qu'une requête SQL apparaît dans du code, un risque d'injection est présent
    • La validation des valeurs soumises en SQL est lourde
    • La préparation des valeurs l'est aussi (escaping, conversion de format)
    • Le temps passé à manipuler SQL n'est pas consacré au code métier
  • Mais le SQL est possible
    • On ne ferme pas pour autant la porte au SQL
    • Pour les requêtes complexes, SQL reste un bon choix
    • Pour les requêtes simples et courantes, il faut l'éviter
  • Les ORM en Perl
    • Class::DBI
  • Les ORM en Perl
    • Class::DBI
    • DBIx::Class
  • Les ORM en Perl
    • Class::DBI
    • DBIx::Class
    • Rose::DB::Object
  • Les ORM en Perl
    • Class::DBI
    • DBIx::Class
    • Rose::DB::Object
    • ...
    • Pourquoi un nouvel ORM ?
  • Les origines de Coat::Persistent
    • ActiveRecord : l'ORM de Ruby on Rails
    • Coat : le mini Moose sans dépendances
    • Deux bonnes idées qui méritaient d'être réunies
  • Objectifs pour Coat::Persistent
    • Simple d'utilisation
  • Objectifs pour Coat::Persistent
    • Simple d'utilisation
    • Léger
  • Objectifs pour Coat::Persistent
    • Simple d'utilisation
    • Léger
    • Rapide
  • Objectifs pour Coat::Persistent
    • Simple d'utilisation
    • Léger
    • Rapide
    • Aussi près que possible de l'API ActiveRecord
  • Objectifs pour Coat::Persistent
    • Simple d'utilisation
    • Léger
    • Rapide
    • Aussi près que possible de l'API ActiveRecord
    • Interopérable (MySQL, SQLite, CSV, ...)
  • Mise en place Comment utiliser Coat::Persistent dans votre projet
  • Installation
    • cpan install Coat
    • cpan install Coat::Persistent
    • Le driver DBI pour votre SGBD
  • Une premier modèle C::P package Camel ; use Coat; use Coat::Persistent;
  • Une premier modèle C::P avec MySQL package Camel ; use Coat; use Coat::Persistent; Coat::Persistent->map_to_dbi( mysql => ' dbname ',' dbuser ',' dbpass ');
  • Une premier modèle C::P avec SQLite package Camel ; use Coat; use Coat::Persistent; Coat::Persistent->map_to_dbi( sqlite => ' dbname=dbfile ');
  • Une premier modèle C::P avec CSV package Camel ; use Coat; use Coat::Persistent; Coat::Persistent->map_to_dbi( csv => ' f_dir=dbfile ');
  • Conventions
    • La mapping est possible par défaut ou par classe
    • Le nom de la classe implique un nom de table
    • La clef primaire se nomme « id »
    • Une clef étrangère se nomme table_id
    • On peut surcharger chacune de ces conventions
  • Surcharger les conventions package Camel ; use Coat; use Coat::Persistent table_name => ' camels ', primary_key => ' cid '; Coat::Persistent->map_to_dbi( csv => ' f_dir=dbfile ');
  • Terminer le mapping package Camel ; use Coat; use Coat::Persistent; has_p name => (isa => 'Str'); has_p age => (isa => 'Int'); sqlite> create table camel (id int, name varchar(25), age int);
  • Maintenant il est possible :
    • Remonter des objets à partir de la base
    • Créer de nouvelles entrées
    • Modifier des entrées existantes
    • Accèder au handle de la base de données
    • Obtenir des objets à partir de requetes SQL complexes
  • Coat::Persistent est en place !
  • Un modèle Coat::Persistent
    • C'est une classe qui hérite de Coat::Object
    • C'est une classe qui hérite de Coat::Persistent
    • À ce titre, elle bénéficie de :
      • Méthodes statiques qui s'appliquent à une table
      • Méthodes d'instances qui s'appliquent à une ligne
    • Pour chaque attribut déclaré, des accesseurs et une série de méthodes sont automatiquement définies :
  • Attribut et méthodes La déclaration de l'attribut « foo » implique :
      • $obj->foo()
      • Class->find_by_foo()
      • Class->find_or_create_by_foo()
      • Class->find_or_initialize_by_foo()
  • Création de données
    • Un nouvel objet Coat::Persistent n'est pas sauvé en base tant que save() n'est pas appelé
    • La méthode create() permet de faire un new() et un save()
    • Des méthodes permettent de faire des créations d'objet avec ou sans sauvegarde selon l'existence d'un enregistrement particulier
  • Création de données
    • Class->new() : crée une instance en mémoire
    • $obj->save() : sauve l'instance dans la base de donnée
    • Class->create() : crée et sauve l'instance
    • Class->find_or_create_by_ATTR(val) : find_by_ATTR(val) ou create(ATTR => val)
    • Class->find_or_initialize_by_ATTR(val) : find_by_ATTR(val) ou new(ATTR => val)
  • Exemple de création Perl> my $joe = Camel->new(name =>'joe',age => 7); $Camel1 = Camel=HASH(0x8dcf7a0); Perl> $joe->save 1 sqlite> select * from camel where id = 1; 1|joe|7
  • Exemple de création (plus court) Perl> my $joe = Camel->create(name =>'night',age => 4); $Camel1 = Camel=HASH(0x8dcf7a0); sqlite> select * from camel where id = 1; 1|joe|7 2|night|4
  • Lecture
    • Pour lire les données existantes, on utilise un finder
    • Le contexte d'appel est important (on remonte N entrées avec un contexte de liste et uniquement la première en contexte scalaire)
    • Les finders peuvent se décliner
    • find, find_by_attribut, find(id), find('condition') ...
  • find en contexte de liste Perl> my @camels = Camel->find(); $ARRAY1 = [ Camel=HASH(0x9cfc568), Camel=HASH(0x9cfc718), Camel=HASH(0x9cfc7c8) ];
  • find avec un id Perl> my $camel = Camel->find(1); $Camel1 = Camel=HASH(0x9cfc568)
  • find avec plusieurs id Perl> my @camels = Camel->find(1,2); $ARRAY1 = [ Camel=HASH(0x9ba0648), Camel=HASH(0x9cfc818) ];
  • find avec un attribut Perl> my $joe = Camel->find_by_name('joe'); $Camel1 = Camel=HASH(0x9cfc568) Perl> $joe->name; 'joe'
  • find avec une condition Perl> @camels = Camel->find('age > 10'); $Camel1 = Camel=HASH(0x9d0af78); Perl> $camels[0]->age 12
  • find avec des options Perl> my @camels = Camel->find('age > 3', { order => 'name', limit => '5', });
  • find avec … du SQL Perl> @camels = Camel->find_by_sql('select * from camel where age is not null'); $ARRAY1 = [ Camel=HASH(0x9cfc528), Camel=HASH(0x9cfca78), Camel=HASH(0x94c3380) ];
  • Modifier Perl> $camel = Camel->find(1); $Camel1 = Camel=HASH(0x9cfc528) Perl> $camel->age(3); 3 Perl> $camel->save; 1
  • Supprimer Perl> $camel = Camel->find(1); $Camel1 = Camel=HASH(0x9cfc528) Perl> $camel->delete; 1 Perl> $camel = Camel->find(1); undef
  • N'oublions pas Coat
    • Le hooks de Coat (Moose) s'appliquent très bien ici
    • Chaque méthode proposée par C::P est interceptable via les hooks Coat before, after et around
    • Les méthodes BUILD et DEMOLISH sont implémentables par les objets C::P
    • Types utilisateur et coercition
  • Les hooks
    • before save => sub { ... }
    • after save => sub { }
    • sub BUILD { ... }
    • sub DEMOLISH { ... }
    • ...
  • Types et Coercition subtype 'DateTime' => as 'Str' => where { /d{4}-dd-dd dd:dd:dd/ }; coerce 'DateTime' => from 'Int' => via { convert_time_to_datetime_str($_) };
  • Types et Coercition has_p 'created_at' => ( is => 'rw', isa => 'DateTime', coerce => 1, ); before 'save' => sub { my ($self) = @_; $self->created_at(time()); };
  • Les relations entre tables
  • Relations côté SQL ... sqlite> create table master (id int, name varchar(25)); sqlite> alter table camel add column master_id int;
  • … et côté Perl package Camel ; use Coat; use Coat::Persistent; has_p name => (isa => 'Str' ); has_p age => (isa => 'Int' ); has_one 'master'; ;
  • … et côté Perl package Master ; use Coat; use Coat::Persistent; has_p name => (isa => 'Str' ); has_many 'camels', class_name => 'Camel'; ;
  • Le maître des chameaux Perl> my $m = Master->create(name => 'Al Kabir') $Master1 = Master=HASH(0x913c168); Perl> my @camels => Camel->find(); $ARRAY1 = [ Camel=HASH(0x913c5e8), Camel=HASH(0x913c588) ]; Perl> map { $_->master($m); $_->save; } @camels;
  • Trouver le maître Perl> my $camel = Camel->find(1); $Camel1 = Camel=HASH(0xa07cd60); Perl> $camel->master $Master1 = Master=HASH(0xa07d050); Perl> $camel->master->name Al Kabir
  • Trouver les chameaux Perl> my $master = Master->find(1); $Master1 = Master=HASH(0xa07d050); Perl> my @camels = $master->camels; $ARRAY1 = [ Camel=HASH(0xa07ce00), Camel=HASH(0xa07d080) ];
  • Accéler les choses
    • Pour améliorer les performances, on peut cacher les résultats des requêtes SQL
    • Le cache est activable à la demande, par Classe ou pour l'ensemble du processus
    • Pour chaque requête SQL générée (pour un set de valeurs données) C::P maintient une entrée en cache avec le résultat
    • Ce résultat en cache est retourné s'il existe
  • Accéler les choses
    • L'expiration des données est gérée en interne par Cache::FastMmap
    • On peut activer/désactiver le cache à la volée
  • Exemple de Cache Pour l'ensemble du processus (toutes les classes C::P sont affectées) Coat::Persistent ->enable_cache( expire_time => '1h' , cache_size => '50m' , share_file => '/var/cache/myapp.cache' , );
  • Exemple de Cache Uniquement pour la classe utilisée Camel ->enable_cache( expire_time => '1h' , cache_size => '50m' , share_file => '/var/cache/myapp.cache' , );
  • Pour la suite ...
    • Gestion de l'option join dans les finder
    • Migrations (classe Coat::Persistent::Migration)
    • Valider de nouveaux drivers DBI
    • Méthodes manquantes de ActiveRecord
    • Optimisations (occupation mémoire, requêtes générées)
  • Pour Contribuer
    • Les patchs sont toujours bienvenus
    • svn co svn://svn.sukria.net:2015/Coat-Persistent
    • Bugs : http://rt.cpan.org
    • Pour me contacter : sukria@sukria.net