Projet Informatique
2A 2018 - 2019
Mickael Lecoq
Rappel du cours / TP précédent
DATA ACCESS LAYER
BUSINESS LAYER
PRESENTATION LAYER
Separation of Concerns
DATA ACCESS LAYER
BUSINESS LAYER
PRESENTATION LAYER
Separation of Concerns
- Isoler les parties du code, afin de pouvoir
- Réutiliser des parties du code
- Faire des optimisations
- Débugguer
DAO (Data Access Object)
DAO
DAO
DAO
Mises à jour
(insert, update, delete)
Lecture
(select)
Remontent des objets
Prennent en paramètre des objets
Business Layer
CRUD (Create, Read, Update, Delete)
def create(self, pokemon):
with connection.cursor() as cur:
try:
cur.execute(
"INSERT INTO pokedex (name, element) VALUES (%s, %s) RETURNING id;",
(pokemon.name, pokemon.element))
pokemon.id = cur.fetchone()[0]
# la transaction est enregistrée en base
connection.commit()
except psycopg2.Error as error:
# la transaction est annulée
connection.rollback()
raise error
return pokemon
CRUD (Create, Read, Update, Delete)
def read(self, id):
with connection.cursor() as cur:
row = cur.execute(
"select name, element from pokedex where id=%s;", (id,))
row = cur.fetchone()
if row:
return Pokemon(name=row[0], element=row[1], id=id)
else:
return None
def update(self, pokemon):
with connection.cursor() as cur:
try:
cur.execute(
"update pokedex set name=%s, element=%s where id=%s",
(pokemon.name, pokemon.element, pokemon.id))
connection.commit()
except psycopg2.Error as error:
connection.rollback()
raise error
CRUD (Create, Read, Update, Delete)
def delete(self, pokemon):
with connection.cursor() as cur:
try:
cur.execute("delete from pokedex where id=%s", (pokemon.id,))
connection.commit()
except psycopg2.Error as error:
connection.rollback()
raise error
CRUD (Create, Read, Update, Delete)
def delete(self, pokemon):
with connection.cursor() as cur:
try:
cur.execute("delete from pokedex where id=%s", (pokemon.id,))
connection.commit()
except psycopg2.Error as error:
connection.rollback()
raise error
Business Layer
- Logique de l'application
- Création, mise à jour et suppression des objets métiers
- Interactions entre les objets métiers
Presentation Layer
- Affichage des informations (couleurs, formats ...)
- Récupération des événements / saisies utilisateurs
Exemple création de compte
Affiche le formulaire, vérifie le format de l'email et la taille du mot de passe
Appelle une méthode creerCompte(email, motDePasse)
Vérifie que le compte n'existe pas déjà (l’email n'est pas en base). Si c'est ok crée le compte en base
Appelle une méthode pour récupérer les comptes existants avec l'email
Si Ok, appelle une méthode pour créer le compte
Communication avec la base de données
DATA ACCESS LAYER
BUSINESS LAYER
PRESENTATION LAYER
Separation of Concerns
Business
Objects
Diagramme de classes du rapport
Pattern MVC (Modèle Vue Controller)
Vue
Contrôleur
Modèle
Met à jour de la vue
Action Utilisateur
Met à jour du modèle
Lit
Parsing et Serialization de données
Problématique
- Comment exporter mes données
- Comment importer des données de tiers
Avoir un format d'échange
Vocabulaire
- Export : Sérialisation
- Import : Parsing
Hétérogénéité des formats
- CSV
- JSON
- XML
- ...
CSV (Comma-Separated Values)
- Représentation tabulaire
- Caractère de séparation (virgule, point-virgule, tabulation)
NOM;PRENOM;MAIL;ID;ID_APPARTENANCE
CROCQ;Andre;a.crocq@rennesmetropole.fr;795;920
ROBERT;Sylvie;s.robert@ville-rennes.fr;656;920
NADESAN;Yannick;y.nadesan@ville-rennes.fr;7285;3728
DEBROISE;Catherine;c.debroise@ville-rennes.fr;7293;3728
ROUAULT;Jean-Claude;;1363;920
PRIGENT;Alain;;4344;920
HOUSSEL;Pierric;;3340;920
BERROCHE;Eric;e.berroche@ville-rennes.fr;4666;4161
CSV (Comma-Separated Values)
- Avantages :
- Simple
- Tabulaire
- Léger / Compact
- Export/Lecture avec excel / google sheet ...
- Facile à parser / sérialiser
CSV (Comma-Separated Values)
- Inconvénients :
- Difficultés sur les structures complexes
- Tout est chaîne de caractère (nécessite de convertir les valeurs numériques)
CSV (Comma-Separated Values)
- Exemple :
- Gérer une liste de personnes qui ont chacune une liste de hobby
CSV (Comma-Separated Values)
- Déterminer une taille de liste ?
NOM;PRENOM;MAIL;ID;ID_APPARTENANCE;hobby1;hobby2;hobby3
CROCQ;Andre;a.crocq@rennesmetropole.fr;795;920;Jeux Vidéos;Ciné;;
ROBERT;Sylvie;s.robert@ville-rennes.fr;656;920;Musique;Sorties;Litterature
NADESAN;Yannick;y.nadesan@ville-rennes.fr;7285;3728;;;
Trop contraignant
CSV (Comma-Separated Values)
- Avoir un séparateur dédié
NOM;PRENOM;MAIL;ID;ID_APPARTENANCE;hobbys
CROCQ;Andre;a.crocq@rennesmetropole.fr;795;920;Jeux Vidéos|Ciné
ROBERT;Sylvie;s.robert@ville-rennes.fr;656;920;Musique|Sorties|Litterature
NADESAN;Yannick;y.nadesan@ville-rennes.fr;7285;3728;
Fonctionne mais non standard, nécessite un traitement particulier
CSV (Comma-Separated Values)
- Exemple :
- Gérer une liste de personnes qui ont chacune un animal de compagnie
CSV (Comma-Separated Values)
- Pas d'imbrication des données
NOM;PRENOM;MAIL;ID;ID_APPARTENANCE;NOM_ANIMAL;TYPE;Age
CROCQ;Andre;a.crocq@rennesmetropole.fr;795;920;Jacky;Chat;15
ROBERT;Sylvie;s.robert@ville-rennes.fr;656;920;Franky;Chien;8
NADESAN;Yannick;y.nadesan@ville-rennes.fr;7285;3728;Freddy;Poisson;2
- A quoi se rapporte la colonne Age ?
CSV (Comma-Separated Values)
Utilisation avec PYTHON - LECTURE
import csv
with open('./test.csv', 'r') as csvfile:
csvreader = csv.reader(csvfile, delimiter=';')
for row in csvreader:
for column in row:
print(column)
CSV (Comma-Separated Values)
Utilisation avec PYTHON - ECRITURE
import csv
with open('./test2.csv', 'w') as csvfile:
csvwriter = csv.writer(csvfile, delimiter=',',)
csvwriter.writerow(['nom', 'prénom', 'age'])
XML (eXtensible Markup Language)
- Format hiérarchisé
- Syntaxe stricte (standard) - validation
XML (eXtensible Markup Language)
Balise de début et de fin
<nom>
Lecoq
</nom>
XML (eXtensible Markup Language)
Hiérarchisation des informations
<personne>
<nom>
Lecoq
</nom>
<prenom>
Mickael
</prenom>
<profession>
Hacker
</profession>
<connu>
false
</connu>
<annee_xp>
10
</annees_xp>
</personne>
XML (eXtensible Markup Language)
Gestion des listes
<personnes>
<personne>
<nom>
Lecoq
</nom>
<prenom>
Mickael
</prenom>
<profession>
Hacker
</profession>
</personne>
<personne>
<nom>
Di Caprio
</nom>
<prenom>
Leonardo
</prenom>
<profession>
Acteur
</profession>
</personne>
</personnes>
XML (eXtensible Markup Language)
Attributs
<personnes>
<personne id="1">
<nom>
Lecoq
</nom>
<prenom>
Mickael
</prenom>
<profession>
Hacker
</profession>
</personne>
<personne id="2">
<nom>
Di Caprio
</nom>
<prenom>
Leonardo
</prenom>
<profession>
Acteur
</profession>
</personne>
</personnes>
XML (eXtensible Markup Language)
Entête
<?xml version='1.0' encoding='utf-8' ?>
<personnes>
<!-- C'est moi -->
<personne id="1">
<nom>
Lecoq
</nom>
<prenom>
Mickael
</prenom>
<profession>
Hacker
</profession>
</personne>
</personnes>
XML (eXtensible Markup Language)
Schéma - DTD
<?xml encoding="UTF-8"?>
<!ELEMENT personnes (personne)+>
<!ATTLIST personnes
xmlns CDATA #FIXED ''>
<!ELEMENT personne (nom,prenom,profession)>
<!ATTLIST personne
xmlns CDATA #FIXED ''
id CDATA #REQUIRED>
<!ELEMENT nom (#PCDATA)>
<!ATTLIST nom
xmlns CDATA #FIXED ''>
<!ELEMENT prenom (#PCDATA)>
<!ATTLIST prenom
xmlns CDATA #FIXED ''>
<!ELEMENT profession (#PCDATA)>
<!ATTLIST profession
xmlns CDATA #FIXED ''>
XML (eXtensible Markup Language)
Schéma - XSD
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified">
<xs:element name="personnes">
<xs:complexType>
<xs:sequence>
<xs:element maxOccurs="unbounded" ref="personne"/>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="personne">
<xs:complexType>
<xs:sequence>
<xs:element ref="nom"/>
<xs:element ref="prenom"/>
<xs:element ref="profession"/>
</xs:sequence>
<xs:attribute name="id" use="required" type="xs:integer"/>
</xs:complexType>
</xs:element>
<xs:element name="nom" type="xs:string"/>
<xs:element name="prenom" type="xs:string"/>
<xs:element name="profession" type="xs:string"/>
</xs:schema>
XML (eXtensible Markup Language)
Schéma - XSD
Type des données :
- xs:string
- xs:boolean
- xs:integer
- ....
XML (eXtensible Markup Language)
Python - LECTURE
from lxml import etree
tree = etree.parse("test.xml")
for personne in tree.xpath("/personnes/personne"):
print(personne.find('nom').text)
Il faut installer une librairie (ci-dessous lxml)
XML (eXtensible Markup Language)
Python - ECRITURE
from lxml import etree
personnes = etree.Element("personnes")
personne = etree.SubElement(personnes, "personne")
personne.set("id", "3")
nom = etree.SubElement(personne, "nom")
nom.text = "Stone"
prenom = etree.SubElement(personne, "prenom")
prenom.text = "Emma"
profession = etree.SubElement(personne, "profession")
profession.text = "Actrice"
print(etree.tostring(personnes, pretty_print=True).decode('utf8'))
Il faut installer une librairie (ci-dessous lxml)
XML (eXtensible Markup Language)
<inconvenient>Verbeux</inconvenient>
JSON (JavaScript Object Notation)
Moins verbeux que le XML
JSON (JavaScript Object Notation)
{
"nom": "Lecoq",
"prenom": "Mickael",
"profession": "Hacker",
"connu": false,
"annees_xp": 10
}
Système clé / valeur
Délimitation avec des accolades
JSON (JavaScript Object Notation)
{
"nom": "Lecoq",
"prenom": "Mickael",
"profession": "Hacker",
"connu": false,
"annees_xp": 10,
"coordonnees" : {
"adresse" : {
"ville" : "Rennes",
"cp": "35700"
}
"telephone" : {
"portable" : "06....."
}
}
}
Imbrication
JSON (JavaScript Object Notation)
{
"nom": "Lecoq",
"prenom": "Mickael",
"profession": "Hacker",
"connu": false,
"annees_xp": 10,
"coordonnees" : {
"adresse" : {
"ville" : "Rennes",
"cp": "35700"
}
"telephone" : {
"portable" : "06....."
}
},
"consoles" : ["Switch", "PS4"],
"groupes" : [
{"numero": 2, membres : ["AHEDDA Sami", "ATLAN Yoav" ...]},
{"numero": 3, ...}
...
]
}
Tableaux
JSON (JavaScript Object Notation)
{
"definitions": {},
"$schema": "http://json-schema.org/draft-07/schema#",
"$id": "http://example.com/root.json",
"type": "object",
"title": "The Root Schema",
"required": [
"nom",
"prenom",
"profession",
"connu",
"annees_xp"
],
"properties": {
"nom": {
"$id": "#/properties/nom",
"type": "string",
"title": "The Nom Schema",
"default": "",
"examples": [
"Lecoq"
],
"pattern": "^(.*)$"
},
"prenom": {
"$id": "#/properties/prenom",
"type": "string",
"title": "The Prenom Schema",
"default": "",
"examples": [
"Mickael"
],
"pattern": "^(.*)$"
},
"profession": {
"$id": "#/properties/profession",
"type": "string",
"title": "The Profession Schema",
"default": "",
"examples": [
"Hacker"
],
"pattern": "^(.*)$"
},
"connu": {
"$id": "#/properties/connu",
"type": "boolean",
"title": "The Connu Schema",
"default": false,
"examples": [
false
]
},
"annees_xp": {
"$id": "#/properties/annees_xp",
"type": "integer",
"title": "The Annees_xp Schema",
"default": 0,
"examples": [
10
]
}
}
}
JSON Schema
JSON (JavaScript Object Notation)
PYTHON - LECTURE
import json
example = '{"nom": "lecoq", "prenom": "mickael"}'
personne = json.loads(example)
print(personne['nom'])
JSON (JavaScript Object Notation)
PYTHON - ECRITURE
import json
personne = {"nom": "Lecoq", "prenom": "Mickael", "annees_xp": 10}
print(json.dumps(personne))
Pour les objects, utilisation d'un encoder
from json import JSONEncoder
class MyEncoder(JSONEncoder):
def default(self, o):
return o.__dict__
En TP
CSV
XML
JSON
Conversion d'un format à l'autre
Big Data
Fichiers données structurées
Data Lake
Données Brut
Machine Learning
Analytics
Base de données, ...
Lecture / Transformation
Librairie Panda
- Lecture de documents CSV et JSON
- Calcul / Agrégation
- Sélection des données
- Génération de graphiques (matplotlib)
Questions
ENSAI - Projet Info - Cours 2
By Mickael Lecoq
ENSAI - Projet Info - Cours 2
- 1,323