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,327