Technologies Web avancées. Technologies Web avancées



Documents pareils
NFA 008. Introduction à NoSQL et MongoDB 25/05/2013

Cours 8 Not Only SQL

Master1 ère année. Réseaux avancés I. TP nº5 filière ISICG

OpenPaaS Le réseau social d'entreprise

Projet de programmation (IK3) : TP n 1 Correction

Alfstore workflow framework Spécification technique

Quelques patterns pour la persistance des objets avec DAO DAO. Principe de base. Utilité des DTOs. Le modèle de conception DTO (Data Transfer Object)

Modélisation PHP Orientée Objet pour les Projets Modèle MVC (Modèle Vue Contrôleur) Mini Framework

ISC Système d Information Architecture et Administration d un SGBD Compléments SQL

PHP et mysql. Code: php_mysql. Olivier Clavel - Daniel K. Schneider - Patrick Jermann - Vivian Synteta Version: 0.9 (modifié le 13/3/01 par VS)

Les bases de données

Bases de Données NoSQL

Pour signifier qu'une classe fille hérite d'une classe mère, on utilise le mot clé extends class fille extends mère

Plan Général Prévisionnel (1/2) (non contractuel) Internet et Outils L1/IO S2-IO2 Bases de données: Jointures, Transactions

Bases de données documentaires et distribuées Cours NFE04

Introduction à JDBC. Accès aux bases de données en Java

Cette application développée en C# va récupérer un certain nombre d informations en ligne fournies par la ville de Paris :

Paginer les données côté serveur, mettre en cache côté client

Compte-rendu de projet de Système de gestion de base de données

Modélisation et Gestion des bases de données avec mysql workbench

Java Licence Professionnelle Cours 7 : Classes et méthodes abstraites

La programmation orientée objet Gestion de Connexions HTTP Manipulation de fichiers Transmission des données PHP/MySQL. Le langage PHP (2)

PHP 4 PARTIE : BASE DE DONNEES

Serveur d'application Client HTML/JS. Apache Thrift Bootcamp

NoSQL : hype ou innovation? Grégory Ogonowski / Recherches Octobre 2011

TP2_1 DE BUSINESS INTELLIGENCE ISIMA ZZ3 F3

Devenez un véritable développeur web en 3 mois!

Cours Base de données relationnelles. M. Boughanem, IUP STRI

Construire une application marketing Facebook sur la plateforme Windows Azure

Le stockage local de données en HTML5

Développement d'applications Web HTML5 L'art et la manière avec Visual Studio 2015 et TFS

Tutoriel: Création d'un Web service en C++ avec WebContentC++Framework

Rafraichissement conditionné d'une page en.net

NoSQL. Introduction 1/23. I NoSQL : Not Only SQL, ce n est pas du relationnel, et le contexte. I table d associations - Map - de couples (clef,valeur)

SYNC FRAMEWORK AVEC SQLITE POUR APPLICATIONS WINDOWS STORE (WINRT) ET WINDOWS PHONE 8

Technologies Web. Ludovic Denoyer Sylvain Lamprier Mohamed Amine Baazizi Gabriella Contardo Narcisse Nya. Université Pierre et Marie Curie

DOM - Document Object Model

1. Installation du Module

Les Triggers SQL. Didier DONSEZ. Université de Valenciennes Institut des Sciences et Techniques de Valenciennes

PHP 5. La base de données MySql. A. Belaïd 1

Java DataBaseConnectivity

Langage et Concepts de ProgrammationOrientée-Objet 1 / 40

Programmation en Java IUT GEII (MC-II1) 1

Les Utilisateurs dans SharePoint

Corrigé de l'atelier pratique du module 5 : Analyse de SQL Server

Licence de MIDO - 3ème année Spécialités Informatique et Mathématiques Appliquées

Rapport de Mini-Projet en ArcGIS Engine

Plan du cours. Historique du langage Nouveautés de Java 7

BIRT (Business Intelligence and Reporting Tools)

1. Qu'est-ce que SQL? La maintenance des bases de données Les manipulations des bases de données... 5

Gestion des utilisateurs et de leurs droits

Programmation par les Objets en Java

Création d objet imbriqué sous PowerShell.

Principales failles de sécurité des applications Web Principes, parades et bonnes pratiques de développement

Procédures Stockées WAVESOFT ws_sp_getidtable Exemple : ws_sp_getnextsouche Exemple :... 12

Bases de données élémentaires Maude Manouvrier

Logiciel : GLPI Version : SYNCRHONISATION DE GLPI AVEC ACTIVE DIRECTORY. Auteur : Claude SANTERO Config. : Windows 2003.

Soon_AdvancedCache. Module Magento SOON. Rédacteur. Relecture & validation technique. Historique des révisions

Service WEB, BDD MySQL, PHP et réplication Heartbeat. Conditions requises : Dans ce TP, il est nécessaire d'avoir une machine Debian sous ProxMox

Séance 1 Introduction aux bases de données

HTML5. Développement d applications Web. Visual Studio 2015 et TFS. L art et la manière. avec. Philippe DIDIERGEORGES

Mise en route et support Envision 10 SQL server (Avril 2015) A l'intention de l'administrateur SQL Server et de l administrateur Envision

Django et PostgreSQL sous la charge

NoSQL. Introduction 1/30. I NoSQL : Not Only SQL, ce n est pas du relationnel, et le contexte. I table d associations - Map - de couples (clef,valeur)

ORACLE 10G DISTRIBUTION ET REPLICATION. Distribution de données avec Oracle. G. Mopolo-Moké prof. Associé UNSA 2009/ 2010

SQL MAP. Etude d un logiciel SQL Injection

Android et le Cloud Computing

Hibernate vs. le Cloud Computing

Application web de gestion de comptes en banques

Application de lecture de carte SESAM-Vitale Jeebop

Projet 2. Gestion des services enseignants CENTRE D ENSEIGNEMENT ET DE RECHERCHE EN INFORMATIQUE. G r o u p e :

Drupal Développeur. Theming et développement pour Drupal. Une formation Formateur : Fabien Crépin. Drupal Développeur.

Direction des Systèmes d'information

Module Administration BD Chapitre 1 : Surcouche procédurale dans les SGBDS

Programme Compte bancaire (code)

Composants Logiciels. Le modèle de composant de CORBA. Plan

Dossier Technique. Détail des modifications apportées à GRR. Détail des modifications apportées à GRR Le 17/07/2008. Page 1/10

Programmer en JAVA. par Tama

INTRODUCTION A JAVA. Fichier en langage machine Exécutable

Licence Bio Informatique Année Premiers pas. Exercice 1 Hello World parce qu il faut bien commencer par quelque chose...

Configurer la supervision pour une base MS SQL Server Viadéis Services

PHP 5.4 Développez un site web dynamique et interactif

Compte Rendu d intégration d application

JADE : Java Agent DEvelopment framework. Laboratoire IBISC & Départ. GEII Université & IUT d Evry nadia.abchiche@ibisc.univ-evry.

Architecture Orientée Service, JSON et API REST

Création d'un site dynamique en PHP avec Dreamweaver et MySQL

Reporting Services - Administration

BTS S.I.O PHP OBJET. Module SLAM4. Nom du fichier : PHPRévisionObjetV2.odt Auteur : Pierre Barais

Service d'authentification LDAP et SSO avec CAS

TP2 DE BUSINESS INTELLIGENCE ISIMA ZZ3 F3

Corrigé de l'atelier pratique du module 8 : Implémentation de la réplication

Phone Manager Soutien de l'application OCTOBER 2014 DOCUMENT RELEASE 4.1 SOUTIEN DE L'APPLICATION

Corrigé de l'atelier pratique du module 3 : Récupération d'urgence

Héritage presque multiple en Java (1/2)

.NET - Classe de Log

Transcription:

Technologies Web avancées

Objectif Appréhender trois outils complexes 1. Rappel MVC 2. ExtJS 3. NodeJS 4. NoSQL Sommaire 5. ExtJS + NodeJS + MongoDB

1 MVC a Théorie MVC Model View Controller Modèle vue contrôleur Les grands principes 3 / 65

1 MVC a Théorie Modèle Vue Contrôleur Modèle de données Présentation, interface utilisateur Logique de contrôle Gestion des événements Synchronisation 4 / 65

1 MVC a Théorie 5 / 65

1 MVC a Théorie http://baptiste-wicht.developpez.com/tutoriels/conception/mvc/ 6 / 65

1 MVC a Théorie http://perso.telecom-paristech.fr/~hudry/coursjava/interswing/boutons5.html 7 / 65

1 MVC b Exemples Framework CakePHP 8 / 65

1 MVC b Exemples Framework YII 9 / 65

1 MVC b Exemples Modèle class Partenaire { private $_nom; constructor () { $this->_nom = ''; } public int getnom() { return $this->_nom; } } public void setnom(int $nom) { $this->_nom = $nom; } 10 / 65

Technologies Web avancées 1 MVC b Exemples Symfony 2 Routing hqf_pizzas_towns_detail: pattern: /ville/{url}/{cp} defaults: { _controller: HQFPizzasBundle:Default:townsDetail } requirements: url: "[a-z0-9-]+" cp: "^([0-9]{5} 2[a b]){1,2}$" hqf_pizzas_partenaire_inscription: pattern: /partenaire/inscription defaults: { _controller: HQFPizzasBundle:Default:partenaireInscription } hqf_pizzas_partenaire_inscription_ok: pattern: /partenaire/inscription/ok defaults: { _controller: HQFPizzasBundle:Default:partenaireInscriptionOk } 11 / 65

Technologies Web avancées 1 MVC b Exemples Symfony 2 Routing _controller: HQFPizzasBundle:Default:XxxYyy Décomposition du chemin : HQFPizzasBundle => HQF PizzasBundle => src/hqf/bundle/pizzasbundle _controller + Default => /Controller/DefaultController.php Les deux mis ensemble : _controller: HQFPizzasBundle:Default:XxxYyy src/hqf/bundle/pizzasbundle/controller/defaultcontroller.php 12 / 65

1 MVC b Exemples Symfony 2 Contrôleur public function partenairesansidaction($url) { $em = $this->get('doctrine')->getmanager('ma_bd'); $repo_partenaire = $em->getrepository('hqfpizzasbundle:partenaire'); $partenaires = $repo_partenaire ->findallactivebyurl($url) ->getquery() ->getresult(); } return $this->render( 'HQFPizzasBundle::partenaire.html.twig', array('partenaires' => $partenaires) ); 13 / 65

Technologies Web avancées 1 MVC b Exemples Symfony 2 Vue <!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>{% block title %}Titre par défaut</title> </head> <body> {% for partenaire in partenaires %} <h2>{{ partenaire.nom }}</h2> {% endfor %} </body> </html> 14 / 65

2 ExtJS a Sencha 2007 V2 RIA / JavaScript Documentation++ APIs + exemples 2009 V3 REST Diagrammes ListView 2011 V4 Class MVC Animation 2014 V5 MVVM Responsive Routing 15 / 65

2 ExtJS a Sencha Clients 16 / 65

2 ExtJS a Sencha Distribution GPL v3 = Public releases: - Sencha Touch - Sencha Touch Charts - Sencha Ext JS - Sencha GXT Sencha commercial licence: - Sencha Touch Grid - Sencha Architect - Sencha Cmd 17 / 65

2 ExtJS a Sencha GPL v3 Personne ne doit être limité par les logiciels qu'il utilise. Il y a quatre libertés que tout utilisateur doit posséder. La liberté : - d'utiliser le logiciel à n'importe quelle fin, - de modifier le programme pour répondre à ses besoins, - de redistribuer des copies à ses amis et voisins, - de partager avec d'autres les modifications qu'il a faites. http://www.gnu.org/licenses/quick-guide-gplv3.html 18 / 65

2 ExtJS b ExtJS MVC Vue Modèle Contrôleur 19 / 65

2 ExtJS b ExtJS MVVM Vue Modèle Vue Modèle 20 / 65

2 ExtJS b ExtJS MVVM Vue Modèle Vue Modèle Vue Contrôleur 21 / 65

2 ExtJS b ExtJS Pratique https://fiddle.sencha.com/#home 22 / 65

2 ExtJS b ExtJS Pratique 23 / 65

2 ExtJS b Classes Chargement dynamique des classes Ext.require(['monenv.A'], function() { }); /* fonction à executer une fois chargé */ 24 / 65

2 ExtJS b Classes Ext.define('Gestion.Categorie', { extend: 'Ext.data.Model', fields: [{ name: 'id', type: 'int', usenull: true }, 'id_partenaire', 'importance', 'titre', 'description' ], hasmany: { model: 'Gestion.Produit', name: 'produits' } }); Ext.define('Gestion.Produit', { extend: 'Ext.data.Model', fields: [{ name: 'id', type: 'int', usenull: true }, 'id_partenaire', 'importance', 'titre', 'description', 'prix' ], hasmany: { model: 'Gestion.Attribut', name: 'attributs' }, belongsto: 'Gestion.Categories' }); 25 / 65

2 ExtJS b Classes Ext.define('Gestion.Produit', { extend: 'Ext.data.Model', fields: [{ name: 'id', type: 'int', usenull: true }, 'id_partenaire', 'importance', 'titre', 'description', 'prix' ], hasmany: { model: 'Gestion.Attribut', name: 'attributs' }, belongsto: 'Gestion.Categories' }); Ext.define('Gestion.Attribut', { extend: 'Ext.data.Model', fields: [{ name: 'id', type: 'int', usenull: true }, 'id_partenaire', 'importance', 'description', 'valeur', 'abbreviation' ], belongsto: 'Gestion.Produit' }); 26 / 65

2 ExtJS b Classes Attention Ext.define('verroumortel.A', { extend: 'verroumortel.b', }); Ext.define('verroumortel.B', { extend: 'verroumortel.c', }); Ext.define('verroumortel.C', { extend: 'verroumortel.a', }); 27 / 65

2 ExtJS c ExtJS TP MVVM Relation maître détail : - grille qui liste des champs qui sont recherchés en AJAX - quand on clique sur un champ - détail affiché dans un tableau 28 / 65

3 NodeJS a Rappel JavaScript Bases JavaScript Portée des variables Closures Fonctions anonymes Faits en cours 29 / 65

3 NodeJS a Principes synchrone / asynchrone Avantages et inconvénients Faits en cours 30 / 65

3 NodeJS a Principes synchrone / asynchrone http://msdn.microsoft.com/fr-fr/magazine/dn754378.aspx 31 / 65

3 NodeJS b Standardisation SQL / Nouveaux besoins Faits en cours 32 / 65

3 NodeJS b TP Microsoft Visual Studio Client + serveur synchrone Client + serveur asynchrone 33 / 65

3 NodeJS b TP Tests MVC sailsjs.org www.totaljs.com www.partialjs.com koajs.com locomotivejs.org expressjs.com flatironjs.org express-io.org geddyjs.org backbone.js 34 / 65

4 NoSQL a Principe En informatique, NoSQL (Not only SQL en anglais) désigne une catégorie de systèmes de gestion de base de données (SGBD) qui n'est plus fondée sur l'architecture classique des bases relationnelles. L'unité logique n'y est plus la table, et les données ne sont en général pas manipulées avec SQL. NoSQL = pas de SQL http://fr.wikipedia.org/wiki/nosql 35 / 65

4 NoSQL b Pourquoi Supporter des montées en charge (scalabilité) Pouvoir gérer une énorme quantité de données Les données peuvent être structurées ou pas Supporte les ajouts fréquents Asynchrone : envoi des informations réponse client immédiate 36 / 65

4 NoSQL c Types NoSQL document : une clé liée à un document = structure de données. Les document peuvent eux-même contenir d'autres paires clé-valeur (ou clé-document). NoSQL graph stocke des informations sur les réseaux. Cf Neo4J et HyperGraphDB. Cassandra et HBase sont optimisés pour des requêtes sur de gros volumes de données, et stockent les données par colonnes, au lieu de les stocker par lignes. 37 / 65

4 NoSQL d MongoDB Introduction MongoDB autorise la lecture d'enregistrements qui ne sont pas commités. Un client peut lire des informations qui ne seront jamais écrites en base (ex : on redémarre le serveur mongodb avant qu'il n'ait écrit le ou les enregistrements). Ce n'est que sur retour callback d'une écriture réussie, qu'on est sûr que les données sont bien écrites, et que même sur redémarrage elles seront présentes. 38 / 65

4 NoSQL d MongoDB Installation http://docs.mongodb.org/manual/tutorial/install-mongodb-on-debian sudo apt-key adv --keyserver keyserver.ubuntu.com --recv 7F0CEB10 echo 'deb http://downloads-distro.mongodb.org/repo/debian-sysvinit dist 10gen' sudo tee /etc/apt/sources.list.d/mongodb.list sudo apt-get update sudo apt-get install -y mongodb-org 39 / 65

4 NoSQL d MongoDB Introduction Création de la base de données : rien à faire! Si la base n'existe pas : créée automatiquement. Pas d'erreur. 40 / 65

4 NoSQL d MongoDB Introduction http://docs.mongodb.org/manual/core/crud-introduction/ http://docs.mongodb.org/manual/reference/write-concern/ http://docs.mongodb.org/manual/tutorial/project-fields-from-query-results/ 41 / 65

4 NoSQL d MongoDB Test installation http://docs.mongodb.org/manual/tutorial/getting-started/ mongo db show dbs use mydb db help j = { name : "mongo" } k = { x : 3 } db.testdata.insert( j ) db.testdata.insert( k ) show collections db.testdata.find() db.testdata.remove({}) 42 / 65

4 NoSQL d MongoDB Introduction Collection = tableau de documents qui ont un ou plusieurs indexes en commun. db.collection.find(); Par défaut : 20 éléments maximum => Spécifier le nombre d'éléments par défaut : DBQuery.shellBatchSize = 10; 43 / 65

4 NoSQL d MongoDB Introduction Tout charger en mémoire - mais ce n'est pas fait pour ça : var mycursor = db.inventory.find( { type: 'food' } ); var documentarray = mycursor.toarray(); var mydocument = documentarray[3]; Itération nécessaire : var mycursor = db.inventory.find( { type: 'food' } ); while (mycursor.hasnext()) { print(tojson(mycursor.next())); } 44 / 65

4 NoSQL d MongoDB Relationnel Recherche = "WHERE" en SQL. Ce ne sont que des filtres simples : clé / valeur. mongodbobj.livres.find().toarray( function(err, data){ if(err){ // gestion de l'erreur console.log(err); } else { // gérer les données } }); 45 / 65

4 NoSQL d MongoDB Exemples Filtres Livres dont l'id=2 mongodbobj.livres.find({ id: 2 }) Livres dont l'id <= 21 mongodbobj.livres.find({ id: {$gte:21} }) Livres qui, parmi leurs "emprunteurs", ont une valeur id=10 mongodbobj.livres.find({ "emprunteurs.id": 10 }) Livres qui ont un moins un de leurs emprunteurs avec un id<=5 mongodbobj.livres.find({ "emprunteurs.id": {$lte: 5} }) 46 / 65

Technologies Web avancées 4 NoSQL d MongoDB Exemples Projections Projection = filtrer sur les champs pour éviter que le document en entier soit renvoyé. Exemple - documentation officielle db.inventaire.find( { type: 'food' }, { item: 1, qty: 1, _id:0 } ) Qu'une partie d'un sous élément dans le document db.inventaire.find( { _id: 5 }, { ratings: { $slice: 2 } } ) Récupérer juste une partie d'un sous ensemble Seulement 2 méthodes disponibles : $elemmatch et $slice 47 / 65

4 NoSQL d MongoDB Exemples Insertion Insertion mongodbobj.livres.insert( NouveauLivre, {w:1}, function(err, result){ if (err) { // échec console.log(err); } else { // réussite } } }); 48 / 65

Technologies Web avancées 4 NoSQL d MongoDB Exemples Mise à jour mongodbobj.livres.update( { id:8 }, {titre:"le monde du fleuve"}, {w:1}, function(err, result) { /* réussite/erreur */ } ); (!!) Ici TOUT l'enregistrement va être écrasé => perte de tous les emprunts, et de l'auteur Solution : correctement préciser le champ : mongodbobj.livres.update( {id:8}, {$set: {titre: Le monde du fleuve }}, {w:1}, function(err, result) { /* réussite/erreur */ } ); 49 / 65

4 NoSQL d MongoDB Exemples Suppression Tous les enregistrements : mongodbobj.livres.remove(function(err, result) { /* réussite/erreur */ }); Avec une condition : mongodbobj.livres.remove( {id: 9}, {w:1}, function(err, result) { /* réussite/erreur */ } ); 50 / 65

4 NoSQL d MongoDB Exemples Jointures http://mongoosejs.com/docs/populate.html : Livre.findOne({ title: 'Guide du routard' }).populate('_creator').exec(function (err, story) { if (err) return handleerror(err); console.log('the creator is %s', story._creator.name); // prints "The creator is Aaron" }) 51 / 65

4 NoSQL d MongoDB Modélisation http://docs.mongodb.org/manual/tutorial/model-embedded-one-to-onerelationships-between-documents/ Modélisation dite flexible car que des documents dont le contenu peut totalement changer. Un document contient un/des autres documents 52 / 65

4 NoSQL d MongoDB Modélisation Personne => _id, nom, prenom Adresse => _id, ligne1, résidents collection personne { _id: objid, name: "theo", adresses: [objid, objid, objid] } collection adresse { _id: objid, ligne1 residents: [objid, objid] } 53 / 65

4 NoSQL d MongoDB Modélisation var personneadresses = db.users.findone(_id: objid).adresses; var adresses = db.adresses.find({ involved : {$in : personneadresses} }); 54 / 65

4 NoSQL d MongoDB Modélisation var date_debut = new Date(2012, 1, 14); var date_fin = new Date(2012, 1, 15); var adresses = db.adresses.find({ date: {$gte : date_debut}, date: {$lt : date_fin} }); 55 / 65

4 NoSQL d MongoDB Mongoose Lancer le serveur sinon cela ne fonctionnera jamais! sudo mongod noprealloc --dbpath /pathcomplet/nomfichier 56 / 65

4 NoSQL e MongoDB + NodeJS Connexion // Récupérer var MongoClient = require('mongodb').mongoclient; // Connect to the db MongoClient.connect( "mongodb://localhost:27017/exampledb", function(err, db) {} ); http://mongodb.github.io/node-mongodb-native/api-articles/nodekoarticle1.html 57 / 65

Technologies Web avancées 4 NoSQL d MongoDB + NodeJS Insertion de tuples MongoClient.connect("mongodb://localhost:27017/exampleDb", function(err, db) { if (err) { return console.dir(err); } var collection = db.collection('test'); var doc1 = {'hello':'doc1'}; var doc2 = {'hello':'doc2'}; var lotsofdocs = [{'hello':'doc3'}, {'hello':'doc4'}]; collection.insert(doc1); collection.insert(doc2, {w:1}, function(err, result) {}); collection.insert( lotsofdocs, {w:1}, function(err, result) {} ); }); 58 / 65

4 NoSQL d MongoDB + NodeJS Mongoose http://mongoosejs.com/ var mongoose = require('mongoose'); mongoose.connect('mongodb://localhost/test'); var Chien = mongoose.model('chien', { name: String }); var toutou = new Chien({ name: 'Arthur' }); toutou.save(function (err) { if (err) //... console.log('sauvegarde ok'); }); 59 / 65

4 NoSQL d MongoDB + NodeJS Mongoose http://mongoosejs.com/docs/guide.html 1 Faire un schéma 2 Préparer le schéma = mongoose.model() 3 On peut instancier le résultat 60 / 65

Technologies Web avancées 4 NoSQL d MongoDB + NodeJS Mongoose http://mongoosejs.com/docs/guide.html var personneschema = new Schema({ nom_complet: { prenom: String, nom: String } }); var Personne = mongoose.model( 'Personne', personneschema ); var moi = new Personne({ nom_complet: { nom: 'Pons', prenom: 'Olivier' } }); 61 / 65

4 NoSQL d MongoDB + NodeJS Mongoose http://mongoosejs.com/docs/guide.html Dans tous les schémas : - champ _id caché par défaut - getter id qui renvoie _id par défaut Pour ne pas le préciser : var schema = new Schema( { name: String }, { _id: false, id: false } ); 62 / 65

4 NoSQL d MongoDB + NodeJS Mongoose (!) Spécificité des dates de Mongoose : les changements des dates ne sont pas prises en compte dans la logique de prise en compte de modification d'un document. => Si on ne fait que changer les dates, mongoose ne voit aucun changement et l'appel à mondocument.save() ne fera rien. => Préciser "manuellement" le champ date qu'on a changé markmodified : mondocument.markmodified("monchampdate") Là - et seulement là, mondocument.save() fonctionnera comme on s'y attend. 63 / 65

4 NoSQL d MongoDB + NodeJS Mongoose TP : implémentation d'un diagramme de classe 64 / 65

4 NoSQL d MongoDB + NodeJS Mongoose Votre TP : implémentation du même diagramme de classe, mais de trois façons différentes, en expliquant dans quel but chaque implémentation peut être utilisée 65 / 65