Your SlideShare is downloading. ×
0
Coat::Persistent at FPW2009
Coat::Persistent at FPW2009
Coat::Persistent at FPW2009
Coat::Persistent at FPW2009
Coat::Persistent at FPW2009
Coat::Persistent at FPW2009
Coat::Persistent at FPW2009
Coat::Persistent at FPW2009
Coat::Persistent at FPW2009
Coat::Persistent at FPW2009
Coat::Persistent at FPW2009
Coat::Persistent at FPW2009
Coat::Persistent at FPW2009
Coat::Persistent at FPW2009
Coat::Persistent at FPW2009
Coat::Persistent at FPW2009
Coat::Persistent at FPW2009
Coat::Persistent at FPW2009
Coat::Persistent at FPW2009
Coat::Persistent at FPW2009
Coat::Persistent at FPW2009
Coat::Persistent at FPW2009
Coat::Persistent at FPW2009
Coat::Persistent at FPW2009
Coat::Persistent at FPW2009
Coat::Persistent at FPW2009
Coat::Persistent at FPW2009
Coat::Persistent at FPW2009
Coat::Persistent at FPW2009
Coat::Persistent at FPW2009
Coat::Persistent at FPW2009
Coat::Persistent at FPW2009
Coat::Persistent at FPW2009
Coat::Persistent at FPW2009
Coat::Persistent at FPW2009
Coat::Persistent at FPW2009
Coat::Persistent at FPW2009
Coat::Persistent at FPW2009
Coat::Persistent at FPW2009
Coat::Persistent at FPW2009
Coat::Persistent at FPW2009
Coat::Persistent at FPW2009
Coat::Persistent at FPW2009
Coat::Persistent at FPW2009
Coat::Persistent at FPW2009
Coat::Persistent at FPW2009
Coat::Persistent at FPW2009
Coat::Persistent at FPW2009
Coat::Persistent at FPW2009
Coat::Persistent at FPW2009
Coat::Persistent at FPW2009
Coat::Persistent at FPW2009
Coat::Persistent at FPW2009
Coat::Persistent at FPW2009
Coat::Persistent at FPW2009
Coat::Persistent at FPW2009
Coat::Persistent at FPW2009
Coat::Persistent at FPW2009
Coat::Persistent at FPW2009
Coat::Persistent at FPW2009
Coat::Persistent at FPW2009
Coat::Persistent at FPW2009
Coat::Persistent at FPW2009
Coat::Persistent at FPW2009
Coat::Persistent at FPW2009
Coat::Persistent at FPW2009
Coat::Persistent at FPW2009
Upcoming SlideShare
Loading in...5
×

Thanks for flagging this SlideShare!

Oops! An error has occurred.

×
Saving this for later? Get the SlideShare app to save on your phone or tablet. Read anywhere, anytime – even offline.
Text the download link to your phone
Standard text messaging rates apply

Coat::Persistent at FPW2009

1,478

Published on

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

Published in: Technology
0 Comments
0 Likes
Statistics
Notes
  • Be the first to comment

  • Be the first to like this

No Downloads
Views
Total Views
1,478
On Slideshare
0
From Embeds
0
Number of Embeds
1
Actions
Shares
0
Downloads
6
Comments
0
Likes
0
Embeds 0
No embeds

Report content
Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
No notes for slide

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 <ul><li>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 </li></ul>
  • 8. Le concept ORM Une méthode moderne et efficace pour manipuler les données
  • 9. Le principe ORM <ul><li>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 </li></ul>
  • 14. Avantages <ul><li>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 </li></ul>
  • 19. Avantages <ul><li>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 </li></ul>
  • 25. Avantages <ul><li>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 </li></ul>
  • 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 ? <ul><li>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 </li></ul>
  • 41. Mais le SQL est possible <ul><li>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 </li></ul>
  • 44. Les ORM en Perl <ul><li>Class::DBI </li></ul>
  • 45. Les ORM en Perl <ul><li>Class::DBI
  • 46. DBIx::Class </li></ul>
  • 47. Les ORM en Perl <ul><li>Class::DBI
  • 48. DBIx::Class
  • 49. Rose::DB::Object </li></ul>
  • 50. Les ORM en Perl <ul><li>Class::DBI
  • 51. DBIx::Class
  • 52. Rose::DB::Object
  • 53. ...
  • 54. Pourquoi un nouvel ORM ? </li></ul>
  • 55. Les origines de Coat::Persistent <ul><li>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 </li></ul>
  • 58. Objectifs pour Coat::Persistent <ul><li>Simple d'utilisation </li></ul>
  • 59. Objectifs pour Coat::Persistent <ul><li>Simple d'utilisation
  • 60. Léger </li></ul>
  • 61. Objectifs pour Coat::Persistent <ul><li>Simple d'utilisation
  • 62. Léger
  • 63. Rapide </li></ul>
  • 64. Objectifs pour Coat::Persistent <ul><li>Simple d'utilisation
  • 65. Léger
  • 66. Rapide
  • 67. Aussi près que possible de l'API ActiveRecord </li></ul>
  • 68. Objectifs pour Coat::Persistent <ul><li>Simple d'utilisation
  • 69. Léger
  • 70. Rapide
  • 71. Aussi près que possible de l'API ActiveRecord
  • 72. Interopérable (MySQL, SQLite, CSV, ...) </li></ul>
  • 73. Mise en place Comment utiliser Coat::Persistent dans votre projet
  • 74. Installation <ul><li>cpan install Coat
  • 75. cpan install Coat::Persistent
  • 76. Le driver DBI pour votre SGBD </li></ul>
  • 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 <ul><li>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 </li></ul>
  • 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 : <ul><li>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 </li></ul>
  • 93. Coat::Persistent est en place !
  • 94. Un modèle Coat::Persistent <ul><li>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 : </li><ul><li>Méthodes statiques qui s'appliquent à une table
  • 97. Méthodes d'instances qui s'appliquent à une ligne </li></ul><li>Pour chaque attribut déclaré, des accesseurs et une série de méthodes sont automatiquement définies : </li></ul>
  • 98. Attribut et méthodes La déclaration de l'attribut « foo » implique : <ul><ul><li>$obj->foo()
  • 99. Class->find_by_foo()
  • 100. Class->find_or_create_by_foo()
  • 101. Class->find_or_initialize_by_foo() </li></ul></ul>
  • 102. Création de données <ul><li>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 </li></ul>
  • 105. Création de données <ul><li>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) </li></ul>
  • 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 <ul><li>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') ... </li></ul>
  • 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 <ul><li>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 </li></ul>
  • 129. Les hooks <ul><li>before save => sub { ... }
  • 130. after save => sub { }
  • 131. sub BUILD { ... }
  • 132. sub DEMOLISH { ... }
  • 133. ... </li></ul>
  • 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 <ul><li>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 </li></ul>
  • 147. Accéler les choses <ul><li>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 </li></ul>
  • 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 ... <ul><li>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) </li></ul>
  • 156. Pour Contribuer <ul><li>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 </li></ul>

×