• Share
  • Email
  • Embed
  • Like
  • Save
  • Private Content
Coat::Persistent at FPW2009
 

Coat::Persistent at FPW2009

on

  • 2,200 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,200
Views on SlideShare
2,102
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