Bonjour. Dans cette séquence, je vais vous parler de
Voyage qui est un wrapper pour bases de données NoSQL.
On va voir un petit peu ce que c'est que Voyage.
Là, l'objectif c'est de vous permettre de créer une véritable application.
Tiny blog, vous allez pouvoir le stocker avec Voyage sur
des bases de données Mongo et le déployer sur un vrai service.
L'idée, c'était de vous montrer un petit peu aussi
comment on peut sauver facilement des objets, et on a
choisi cette solution parce qu'elle est vraiment super simple pour le cours.
MongoDB, qu'est-ce que c'est en fait?
MongoDB, c'est les nouvelles bases de données NoSQL qui
sont orientées documents. Vous avez un langage de
requêtes dessous et c'est une des plus populaires.
Après, vous avez Couch DB et Riak.
Là pour le moment, on utilise MongoDB et Voyage.
Qu'est-ce que Voyage ?
En fait Voyage finalement, c'est un mappeur qui va
prendre des objets et les mapper sur MongoDB et le faire
quasiment automatiquement pour vous.
Pour ceux qui ont fait du Java en hibernate, Voyage, c'est
l'équivalent de hibernate pour MongoDB et bien sûr, c'est fait pour Pharo.
Quelles sont les fonctionnalités de Voyage?
En fait, Voyage est très simple, il va vous garantir l'identité
de vos objets quand vous les sauvez en base et que vous les rechargez.
Il offre des capacités de gérer des erreurs.
Il y a aussi une pool de connexion pour que ça aille plus
vite en fait.
Juste pour démarrer et pour vous montrer, la première
chose qu'on va faire, c'est créer un repository Mongo
avec ce genre d'expression.
Là, c'est si vous voulez accéder à votre base de données
Mongo qui est gérée de manière extérieure à Pharo.
Maintenant ce qu'on fait souvent quand on est en mode
prototype, on va utiliser une base de données Mongo en mémoire.
Vous avez vu la différence, là il y a Mongo memory repository.
L'idée, c'est que vous n'avez pas besoin d'une base de
données Mongo, vous allez prototyper votre application.
Et quand finalement ça fonctionne, vous allez pouvoir
changer le memory repository en un vrai repository et
attaquer votre base extérieure, donc c'est la bonne pratique à avoir.
Pour illustrer Mongo, on va faire un petit modèle
objet qui est des super-héros qui ont des super pouvoirs, avec des armures.
Vous aurez un exercice, vous pourrez le faire de toute
façon, tout ce que je vous montre pendant ce cours, vous
aurez le support pour pouvoir le faire.
Et je vous suggère de le faire parce que c'est marrant de scrypter Superman.
On va regarder juste comment fonctionne Héros et les supers pouvoirs.
En gros, on a une classe Héros.
Il a un nom, un niveau et puis il a des pouvoirs.
Le nom, j'ai un accesseur avec le nom.
J'ai un setter pour mettre son nom.
J'ai un niveau pareil ici.
Et les pouvoirs, je les gère sous forme d'un ensemble.
Donc là, je dis les pouvoirs, au début si c'est vide je
mets un ensemble, et quand je peux ajouter un pouvoir, ça
rajoute un pouvoir à l'ensemble.
Donc, vraiment complètement basique.
Et les pouvoirs, qu'est-ce que c'est?
Pour le moment, notre pouvoir a juste un nom et on peut
mettre ce nom ou pas.
Maintenant, le point c'est comment est-ce que je déclare
que les classes de mon domaine sont stockées en base?
Là c'est l'idée de root class, quels sont les points d'entrée
qu'on va avoir dans notre base de données?
Ça peut être n'importe quelle classe du système.
Comment on va déclarer ça ?
On doit déclarer ça avec une méthode de classe, j'insiste
sur le classe, une méthode de classe qui s'appelle isVoyageRoot.
Comment on fait pour les héros ?
C'est super débile, on va faire héros classe isVoyage rend vrai.
À partir de ce moment-là, Voyage sait que je vais pouvoir
stocker mes héros dans la base Mongo.
Si on fait Spiderman, Spiderman il s'appelle Spiderman,
il est de niveau épique, il a comme super pouvoir une
super force, il peut monter aux murs lui aussi et il a
apparemment un instinct d'araignée.
Et puis on en a un autre.
Là vous voyez, je sauve, save, ça indique à Voyage "OK,
tu prends ce super héros et tu le stockes dans ta base".
Et de la même manière avec Wolverine, vous avez compris
qu'il a d'autres propriétés et pareil, je peux sauver.
Maintenant si je regarde ma base Mongo, si je fais DB
Hero find 0, qu'est-ce que je vois ?
Je vois mon héros Spiderman et qu'est-ce qu'il a?
Alors là justement il faut faire attention, on voit bien
qu'il a son super pouvoir qui est complètement décrit
ici. Vous auriez pareil avec Wolverine, et caetera.
D'accord ?
Une fois qu'on a fait ça au niveau de Pharo, on peut
faire des tas d'expressions. Je ne vais pas aller dans
les détails mais je peux sélectionner tous les super-héros.
Là, je vais avoir Spiderman et Wolverine.
Je peux dire que je veux trouver le héros qui s'appelle Spiderman.
Là, je peux dire moi je veux trouver tous les super-héros
qui ont comme level épique.
Là, je vais retrouver mes 2 super-héros.
Maintenant, je vais l'exprimer différemment parce qu'en
fait, la base de données Mongo comprend du json, donc je
peux créer du json au vol et l'injecter et faire une query à base de json.
Là, j'aimerais connaître le super-héros dont le
nom est Spiderman mais vous voyez que je l'ai exprimé
sous-forme de Json, et en faisant as directory ça me rend un dictionnaire.
Je peux faire la même chose pour select as many.
Ça dépendra des query, il y a des query qui sont plus
faciles à exprimer sous cette forme-là ou sous une autre,
mais pour vous pour le moment c'est du détail.
On peut faire des query qui sont bien plus avancées.
Je peux dire "Je veux sélectionner la plupart des
super-héros qui ont un niveau épique, dont le nom est
trié dans un ordre ascendant et je veux une limite de 10,
et je veux commencer à la page 0" pour pouvoir chercher
des tranches dans ma base de données.
Ça, quand vous en aurez besoin vous regarderez la doc.
On peut faire d'autres opérations dessus.
Je peux compter le nombre de héros, déjà ça c'est super.
Et puis, je peux compter ceux qui satisfont une certaine propriété.
Bien sûr, je peux enlever, alors là si vous faites remove
all, vous n'aurez plus d'objets en base, il faut savoir assumer.
Là, je peux dire "Je vais en sélectionner un et puis je vais l'enlever.
" Et j'aurai pu enlever mon héros de ma base de données.
Ce n'est que les opérations qui font du sens, on va dire.
Maintenant la question qui se pose finalement quand vous
allez utiliser MongoDB, c'est "Qu'est-ce qu'on appelle
une racine de base, et quand est-ce qu'on définit une
classe comme une racine de base ?"
On définit une classe comme une racine de base quand on a
besoin de faire des query.
Ça, c'est la première règle: je fais une query parce que
je définis ma classe comme une racine parce que je veux
pouvoir accéder à tous les objets de cette classe.
L'autre point, c'est "Je veux partager des objets entre
mes objets. " Donc là par exemple je veux partager des
pouvoirs, parce que la phrase n'est pas très claire, je
veux partager des pouvoirs entre mes héros.
Dans ces cas-là, je vais devoir définir "pouvoirs" comme
une racine, donc on va voir ça.
Si on regarde héros, c'est bien une racine dans notre
exemple, mais en fait les pouvoirs ça pourrait être aussi
des racines, il n'y a pas de problème.
Dans Voyage, on peut déclarer n'importe quelle classe comme racine.
Comment on fait ça ?
Pareil que tout à l'heure, je vais dire que ma classe
power, c'est une racine. Ça veut dire que
si je crée le pouvoir fly qui veut dire voler et que je
le sauve, il sera mis en base; la force surhumaine, c'est pareil.
Et maintenant ce que je vais faire, je vais pouvoir faire
une query qui me dit "Je veux récupérer le pouvoir
de voler. Je veux aussi récupérer le pouvoir d'avoir une force surhumaine.
" Et là maintenant, je recrée Superman en disant "J'
ai récupéré ces 2 pouvoirs", donc ça veut dire qu'il n'y
en a qu'un dans le système à chaque fois et je le sauve.
Qu'est-ce qui se passe au niveau de ma base?
C'est important, il faut faire un reset pour que ça
fonctionne bien. En général, à chaque fois que vous
changez le schéma de base, il faut faire cette expression.
Mais ce qui m'intéresse là, c'est de vous montrer que
maintenant dans les pouvoirs de Superman, je n'ai plus le
pouvoir qui est décrit de manière composée à l'intérieur,
mais j'ai une référence vers un pouvoir.
Et là, je vais avoir une autre référence.
Donc qu'est-ce que ça veut dire ?
Ça veut dire que si j'ai un autre super-héros qui sait
voler, je vais pouvoir partager ce super pouvoir au lieu
d'en avoir 2. Et ça, ça dépend de votre domaine donc
suivant le domaine et suivant comment vous voulez
modéliser votre domaine, vous allez devoir définir des racines différentes.
Là, c'est sur un exemple idiot mais c'était pour vous donner l'intuition.
Si je répète, vous allez définir une racine du domaine si
vous avez besoin de faire des query, ou si vous voulez
partager des objets de cette racine.
Comment on exprime les relations dans Voyage?
En fait, c'est l'équivalent des foreign keys dans les
bases de données relationnelles. Voyage va gérer
automatiquement les références cycliques entre vos racines.
Vous n'avez rien à faire.
Par contre, il faut faire attention, Voyage ne gère pas
les références cycliques entre des objets qui seraient
composés à l'intérieur. Vous vous expérimenterez et puis
vous verrez que la plupart du temps quand vous avez des
racines, vous n'avez aucun problème.
Ce que je voulais vous montrer dans ce cours, c'est qu'on
peut très facilement sauver des objets dans une base de données Mongo.
Si vous voulez en savoir plus, il y a aussi un chapitre
dans Enterprise Pharo, ou Web perspectives qui est dans
les ressources du MOOC. Et de toute façon, vous aurez un
petit tutoriel qui vous prendra par la main en vous
faisant refaire les super-héros, donc vous pourrez tout apprendre.