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

Like this? Share it with your network

Share

Coat::Persistent at FPW2009

on

  • 2,327 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,327
Views on SlideShare
2,229
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 Presentation Transcript

  • 1. Coat::Persistent Votre base de données à portées d'objets FPW 2009 – 13 Juin 2009 Alexis Sukrieh http://www.sukria.net
  • 2. Plan
    • Le concept ORM
    • 3. Origines de Coat::Persistent
    • 4. Mise en place de Coat::Persistent
    • 5. Accèder aux données (lecture/écriture)
    • 6. Relations entre tables / modèles
    • 7. Fonctionnement du cache
  • 8. Le concept ORM Une méthode moderne et efficace pour manipuler les données
  • 9. Le principe ORM
    • Un framework Objet
    • 10. Une table devient une classe
    • 11. Une ligne devient une instance
    • 12. Une colonne devient un attribut
    • 13. Le SQL est désormais une couche de bas niveau
  • 14. Avantages
    • Moins de code pour manipuler les données
    • 15. Plus de code pour écrire l'application
    • 16. Factorisation du problème d'accès aux données
    • 17. Facilités et puissance de l'approche Objet
    • 18. Simplicité d'utilisation
  • 19. Avantages
    • Moins de code pour manipuler les données
    • 20. Plus de code pour écrire l'application
    • 21. Factorisation du problème d'accès aux données
    • 22. Facilités et puissance de l'approche Objet
    • 23. Simplicité d'utilisation
    • 24. Moins de SQL
  • 25. Avantages
    • Moins de code pour manipuler les données
    • 26. Plus de code pour écrire l'application
    • 27. Factorisation du problème d'accès aux données
    • 28. Facilités et puissance de l'approche Objet
    • 29. Simplicité d'utilisation
    • 30. Moins de SQL
    • 31. Moins de SQL
  • 32. Avantages Moins de SQL ??!
  • 33. 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...
  • 34. CATS DON'T LIKE SQL
  • 35. Avec Coat::Persistent foreach my $obj (Table->find()) { # ici on joue avec $obj ... } Je crois que le chat s'est calmé...
  • 36. Pourquoi vouloir moins de SQL ?
    • Pour les tâches répétitives, SQL est lourd
    • 37. Chaque fois qu'une requête SQL apparaît dans du code, un risque d'injection est présent
    • 38. La validation des valeurs soumises en SQL est lourde
    • 39. La préparation des valeurs l'est aussi (escaping, conversion de format)
    • 40. Le temps passé à manipuler SQL n'est pas consacré au code métier
  • 41. Mais le SQL est possible
    • On ne ferme pas pour autant la porte au SQL
    • 42. Pour les requêtes complexes, SQL reste un bon choix
    • 43. Pour les requêtes simples et courantes, il faut l'éviter
  • 44. Les ORM en Perl
    • Class::DBI
  • 45. Les ORM en Perl
    • Class::DBI
    • 46. DBIx::Class
  • 47. Les ORM en Perl
    • Class::DBI
    • 48. DBIx::Class
    • 49. Rose::DB::Object
  • 50. Les ORM en Perl
    • Class::DBI
    • 51. DBIx::Class
    • 52. Rose::DB::Object
    • 53. ...
    • 54. Pourquoi un nouvel ORM ?
  • 55. Les origines de Coat::Persistent
    • ActiveRecord : l'ORM de Ruby on Rails
    • 56. Coat : le mini Moose sans dépendances
    • 57. Deux bonnes idées qui méritaient d'être réunies
  • 58. Objectifs pour Coat::Persistent
    • Simple d'utilisation
  • 59. Objectifs pour Coat::Persistent
    • Simple d'utilisation
    • 60. Léger
  • 61. Objectifs pour Coat::Persistent
    • Simple d'utilisation
    • 62. Léger
    • 63. Rapide
  • 64. Objectifs pour Coat::Persistent
    • Simple d'utilisation
    • 65. Léger
    • 66. Rapide
    • 67. Aussi près que possible de l'API ActiveRecord
  • 68. Objectifs pour Coat::Persistent
    • Simple d'utilisation
    • 69. Léger
    • 70. Rapide
    • 71. Aussi près que possible de l'API ActiveRecord
    • 72. Interopérable (MySQL, SQLite, CSV, ...)
  • 73. Mise en place Comment utiliser Coat::Persistent dans votre projet
  • 74. Installation
    • cpan install Coat
    • 75. cpan install Coat::Persistent
    • 76. Le driver DBI pour votre SGBD
  • 77. Une premier modèle C::P package Camel ; use Coat; use Coat::Persistent;
  • 78. Une premier modèle C::P avec MySQL package Camel ; use Coat; use Coat::Persistent; Coat::Persistent->map_to_dbi( mysql => ' dbname ',' dbuser ',' dbpass ');
  • 79. Une premier modèle C::P avec SQLite package Camel ; use Coat; use Coat::Persistent; Coat::Persistent->map_to_dbi( sqlite => ' dbname=dbfile ');
  • 80. Une premier modèle C::P avec CSV package Camel ; use Coat; use Coat::Persistent; Coat::Persistent->map_to_dbi( csv => ' f_dir=dbfile ');
  • 81. Conventions
    • La mapping est possible par défaut ou par classe
    • 82. Le nom de la classe implique un nom de table
    • 83. La clef primaire se nomme « id »
    • 84. Une clef étrangère se nomme table_id
    • 85. On peut surcharger chacune de ces conventions
  • 86. 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 ');
  • 87. 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);
  • 88. Maintenant il est possible :
    • Remonter des objets à partir de la base
    • 89. Créer de nouvelles entrées
    • 90. Modifier des entrées existantes
    • 91. Accèder au handle de la base de données
    • 92. Obtenir des objets à partir de requetes SQL complexes
  • 93. Coat::Persistent est en place !
  • 94. Un modèle Coat::Persistent
    • C'est une classe qui hérite de Coat::Object
    • 95. C'est une classe qui hérite de Coat::Persistent
    • 96. À ce titre, elle bénéficie de :
      • Méthodes statiques qui s'appliquent à une table
      • 97. 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 :
  • 98. Attribut et méthodes La déclaration de l'attribut « foo » implique :
      • $obj->foo()
      • 99. Class->find_by_foo()
      • 100. Class->find_or_create_by_foo()
      • 101. Class->find_or_initialize_by_foo()
  • 102. Création de données
    • Un nouvel objet Coat::Persistent n'est pas sauvé en base tant que save() n'est pas appelé
    • 103. La méthode create() permet de faire un new() et un save()
    • 104. Des méthodes permettent de faire des créations d'objet avec ou sans sauvegarde selon l'existence d'un enregistrement particulier
  • 105. Création de données
    • Class->new() : crée une instance en mémoire
    • 106. $obj->save() : sauve l'instance dans la base de donnée
    • 107. Class->create() : crée et sauve l'instance
    • 108. Class->find_or_create_by_ATTR(val) : find_by_ATTR(val) ou create(ATTR => val)
    • 109. Class->find_or_initialize_by_ATTR(val) : find_by_ATTR(val) ou new(ATTR => val)
  • 110. 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
  • 111. 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
  • 112. Lecture
    • Pour lire les données existantes, on utilise un finder
    • 113. Le contexte d'appel est important (on remonte N entrées avec un contexte de liste et uniquement la première en contexte scalaire)
    • 114. Les finders peuvent se décliner
    • 115. find, find_by_attribut, find(id), find('condition') ...
  • 116. find en contexte de liste Perl> my @camels = Camel->find(); $ARRAY1 = [ Camel=HASH(0x9cfc568), Camel=HASH(0x9cfc718), Camel=HASH(0x9cfc7c8) ];
  • 117. find avec un id Perl> my $camel = Camel->find(1); $Camel1 = Camel=HASH(0x9cfc568)
  • 118. find avec plusieurs id Perl> my @camels = Camel->find(1,2); $ARRAY1 = [ Camel=HASH(0x9ba0648), Camel=HASH(0x9cfc818) ];
  • 119. find avec un attribut Perl> my $joe = Camel->find_by_name('joe'); $Camel1 = Camel=HASH(0x9cfc568) Perl> $joe->name; 'joe'
  • 120. find avec une condition Perl> @camels = Camel->find('age > 10'); $Camel1 = Camel=HASH(0x9d0af78); Perl> $camels[0]->age 12
  • 121. find avec des options Perl> my @camels = Camel->find('age > 3', { order => 'name', limit => '5', });
  • 122. 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) ];
  • 123. Modifier Perl> $camel = Camel->find(1); $Camel1 = Camel=HASH(0x9cfc528) Perl> $camel->age(3); 3 Perl> $camel->save; 1
  • 124. Supprimer Perl> $camel = Camel->find(1); $Camel1 = Camel=HASH(0x9cfc528) Perl> $camel->delete; 1 Perl> $camel = Camel->find(1); undef
  • 125. N'oublions pas Coat
    • Le hooks de Coat (Moose) s'appliquent très bien ici
    • 126. Chaque méthode proposée par C::P est interceptable via les hooks Coat before, after et around
    • 127. Les méthodes BUILD et DEMOLISH sont implémentables par les objets C::P
    • 128. Types utilisateur et coercition
  • 129. Les hooks
    • before save => sub { ... }
    • 130. after save => sub { }
    • 131. sub BUILD { ... }
    • 132. sub DEMOLISH { ... }
    • 133. ...
  • 134. 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($_) };
  • 135. Types et Coercition has_p 'created_at' => ( is => 'rw', isa => 'DateTime', coerce => 1, ); before 'save' => sub { my ($self) = @_; $self->created_at(time()); };
  • 136. Les relations entre tables
  • 137. Relations côté SQL ... sqlite> create table master (id int, name varchar(25)); sqlite> alter table camel add column master_id int;
  • 138. … et côté Perl package Camel ; use Coat; use Coat::Persistent; has_p name => (isa => 'Str' ); has_p age => (isa => 'Int' ); has_one 'master'; ;
  • 139. … et côté Perl package Master ; use Coat; use Coat::Persistent; has_p name => (isa => 'Str' ); has_many 'camels', class_name => 'Camel'; ;
  • 140. 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;
  • 141. 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
  • 142. 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) ];
  • 143. Accéler les choses
    • Pour améliorer les performances, on peut cacher les résultats des requêtes SQL
    • 144. Le cache est activable à la demande, par Classe ou pour l'ensemble du processus
    • 145. 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
    • 146. Ce résultat en cache est retourné s'il existe
  • 147. Accéler les choses
    • L'expiration des données est gérée en interne par Cache::FastMmap
    • 148. On peut activer/désactiver le cache à la volée
  • 149. 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' , );
  • 150. Exemple de Cache Uniquement pour la classe utilisée Camel ->enable_cache( expire_time => '1h' , cache_size => '50m' , share_file => '/var/cache/myapp.cache' , );
  • 151. Pour la suite ...
    • Gestion de l'option join dans les finder
    • 152. Migrations (classe Coat::Persistent::Migration)
    • 153. Valider de nouveaux drivers DBI
    • 154. Méthodes manquantes de ActiveRecord
    • 155. Optimisations (occupation mémoire, requêtes générées)
  • 156. Pour Contribuer
    • Les patchs sont toujours bienvenus
    • 157. svn co svn://svn.sukria.net:2015/Coat-Persistent
    • 158. Bugs : http://rt.cpan.org
    • 159. Pour me contacter : sukria@sukria.net