Data driven programming

Data driven programming

Le but de cet UE est d'apprendre à maîtriser les concepts et les outils informatiques liés

  • à la conservation,
  • la mise à jour
  • et la mise en forme

de grandes quantités de données.

 

Vous apprendrez à organiser les étapes du développement autour

  • du modèle de données,
  • de leur présentation
  • et des actions de l'utilisateur.

Partie 1

Persistance des données

Partie 1

Persistance des données

Section 1

Généralités

Donnée informatique

Une donnée informatique est un élément d'information ayant subi un encodage numérique :

  • Consultable/manipulable/échangeable par des programmes informatiques
  • Possibilité de la conserver sur un support de stockage numérique (CD-ROM, disque dur, SSD, …)

Donnée persistante

Les données persistantes sont une des composantes essentielles des programmes informatiques.

  • Il s'agit par définition des informations qui doivent être conservées entre deux exécutions.

  • Un jeu de valeurs encodé et enregistré est appelé un enregistrement
  • Avec l’augmentation des capacités de stockage et leur mise en réseau, les quantités de données conservées ont considérablement augmenté au cours des dernières décennies.

Exemples de données persistantes

  • Les données liées à l'utilisateur (données personnelles, sauvegardes,…)

  • Les données de l'entreprise:

    • données comptables

    • ventes

    • achats

    • employés

    • stocks

    • production

    • etc..

  • Bases d'information:

    • Documents en ligne

    • Services (trajets SNCF, articles commerciaux à vendre, données météo, articles de presse…)

  • Échanges et communication

    • index web (moteurs de recherche)

    • graphes de liens et messages (réseaux sociaux)

Stockage des données

  • Les informations peuvent être stockées dans un fichier
    • exemple : fichier csv
  • La plupart du temps, on utilisera des bases de données :
    • plus robuste
    • plus rapide
    • plus sécurisé

Bases de données

Une base de données est une infrastructure matérielle et logicielle  permettant :

  • le stockage
  • la conservation
  • la mise à jour
  • et la restitution des données informatiques

 

Modèle de base de données

  • Un modèle de base de donnée est une description logique :
    • d'un ensemble de données
    • et d'un ensemble de relations entre ces données
  • qui vise à assurer :
    • l'intégrité/unicité
    • l'exhaustivité/la précision
    • l'associativité
    • la "navigabilité" des données manipulées.
  • Repose sur :
    • des méthodes de conception ensemblistes
    • fondées sur le modèle relationnel

Système de gestion de bases de données

  • Un SGBD (Système de Gestion de Bases de Données) est
    • un programme
    • qui gère une (ou des) base(s) de données.
    • optimisé afin :
      • d’accélérer l’accès
      • et rationaliser le traitement d’un grand ensemble d’enregistrements stockés sur un support informatique.
  • Le fonctionnement d'un tel programme repose sur :
    • un langage de requête permettant de consulter et mettre à jour les données stockées dans la base
    • des algorithmes de stockage et de classement efficace (afin d’accélérer les temps de recherche)

Requête

  • une requête (en anglais query)
    • est une demande de consultation,
    • effectuée par un programme client
    • à l’attention d’un programme serveur.

Exemples

  • requêtes http : demande de consultation d’une page web ( url = référence vers un fichier)

  • Moteur de recherche : recherche de pages contenant les mots-clés spécifiés

  • Bases de données : utilisation d’un langage de requête (SQL):

SELECT *
FROM  Eleves
WHERE NOM = 'Dugenou'

Serveur de bases de données

  • Les données sont centralisées au niveau du serveur, chargé :
    • de la gestion,
    • de la manipulation
    • et du stockage des données.
  • Le programme client représente l’utilisateur, il
    • enregistre la demande de l’utilisateur,
    • la transmet au serveur,
    • puis met en forme visuellement la réponse du serveur.

Partie 1

Persistance des données

Section 2

La mémoire cache

Rappel sur les fichiers

  • La mémoire secondaire est organisée sous forme
    • de pages
    • ou secteurs (blocs de 512 octets environ)
  • Les programmes ne peuvent pas directement écrire sur les secteurs.
    • Le système d'exploitation assure la gestion de l'accès au disque via les fichiers
  • Un fichier est une entité logique représentant un ensemble de pages de la mémoire secondaire
  • Il est désigné par son descripteur (nom, chemin d'accès, droits,…)

Ouverture

f = open("/chemin/vers/mon_fichier", "r")

Ouverture

  • Ouverture d'un fichier :

    • initialisation d'un descripteur de fichier f:

  • f est un objet qui implémente un flux de données.

  • Un flux de données est structure d'accès :
    • sans adressage
    • les données sont lues dans l'ordre dans lequel elles ont été écrites par le serveur

  • On parle d'accès séquentiel aux données

f = open("/chemin/vers/mon_fichier", "r")

Lecture

  • L'opération de lecture :

    • dépile l'élément situé en tête de flux (dans la mémoire cache)

    • et le retourne à l'utilisateur

  • Le système d'exploitation se charge de gérer la mémoire cache :
    • les donnée sont lues en fonction des demandes du programme

    • typiquement le système charge plusieurs pages en avance dans la mémoire cache

s = f.readline()

Ecriture

  • Le système d'exploitation modifie le cache sans modifier immédiatement le fichier

f.write(s)
f.close()
  • L'écriture dans la mémoire secondaire est garantie lors de la fermeture

f.flush()
  • Pour forcer l'écriture sans fermer le fichier, on on effectue un "vidage" du cache dans la mémoire secondaire

Accès aux bases de données

import sqlite3
db = sqlite3.connect("/chemin/vers/mabase.db"))

Accès aux bases de données

  • l'objet db ouvre une communication (un "socket") avec un programme de gestion de bases de données (ici l'application sqlite3).
    • Le programme n'est donc plus en communication directe avec le système d'exploitation mais avec une application tierce

    • C'est maintenant sqlite3 qui gère le flux de données.

import sqlite3
db = sqlite3.connect("/chemin/vers/mabase.db"))
  • Le curseur est l'objet qui gère l'accès séquentiel aux données

c = db.cursor()
c.execute("SELECT * FROM MaTable")
  • Le programme sqlite3 exécute la requête et génère un flux de données

t = c.fetchone()
  • Lecture de la première réponse (du premier tuple) du flux:

Lecture

  • Le curseur est l'objet qui gère l'accès séquentiel aux données

c.execute("INSERT INTO MaTable VALUES (v1, v2, v3)")
db.commit()
  • Les modifications sont conservées dans la mémoire cache de sqlite. Néanmoins, pour s'assurer d'un enregistrement effectif en mémoire secondaire, il faut effectuer un commit (pour forcer l'écriture)

Ecriture

Appariement (Mapping) Objet/Données

  • Un appariement (Mapping) est une couche d'abstraction logicielle qui permet :

    • de manipuler les données de la base données de manière plus conviviale et intuitive,

    • essentiellement en faisant correspondre les tuples (enregistrements) de la base de données avec des variables du programme

      • correspondance objets/données

      • On parle aussi d'interface objets/données

Appariement (Mapping) Objet/Données

Exemples

  • "Vues" d'une base de données :

    • tables virtuelles correspondant à des requêtes pré-définies

    • –> en RAM

Exemples

  • Mapping objet/Relationnel (ORM – Object-Relational Mapping) :

    • mise en correspondance table/classe

    • + ajout de getters/setters

    • patron de conception DAO (Data Access Object)

Exemples

  • Approche “CRUD”: les requêtes se réduisent à quatre grandes familles d'opérations:

    • Création (Create) : ajout de nouveaux objets

    • Lecture/recherche (Read) : consulation du contenu d'un objet

    • Mise à jour (Update) : changement du contenu existant

    • Suppression (Delete) : suppression des objets périmés

Exemples

  • Analyse de données :

    • Mise en forme hiérarchique des données :

      • Dimensions (indexation multiple hiérarchique)

      • Agrégation multi-critères (tableaux croisés dynamiques, cubes de données etc.)

    • Visualisation

  • Dans les deux premiers cas que nous avons vus, la gestion de la mémoire cache est déléguée à des programmes tiers:
    • Les système d'exploitation (pour la gestion des fichiers)

    • Le gestionnaire de BD (requêtes vers une BD)

  • Dans le cas du mapping Objet/Relationnel,
    • la couche de persistance gère le chargement en mémoire des données de la base.
    • Elle joue le même rôle que la mémoire cache:
      • en maintenant en mémoire l'état des objets modifiés par l'utilisateur

      • en chargeant de manière parcimonieuse le contenu de la base (seuls les données réellement utilisées doivent être chargées en mémoire)

Remarques

Partie 1

Persistance des données

Section 3

De la conception à la réalisation

Principe général:

  • Les variables et objets manipulé sont régulièrement sauvegardés

  • Pour plus d'efficacité, le fichier de sauvegarde est une base de données

  • Au niveau de la conception du programme, on doit distinguer les données persistances des données non-persistantes

  • Mise en correspondance et synchronisation entre les donnée du programme et la base de données

  • Maintien de la cohésion assuré par la mémoire cache (interface entre application et SGBD)

Retrouver le programme dans l'état dans lequel on l'a laissé lorsqu'on l'a précédemment quitté:

Méthode

  • Les données persistantes sont conservées dans une base de données relationnelle dont le schéma est établi au cours de l'étape de modélisation.

Modèle entité/association

Passage au modèle relationnel

  • Enseignant(e-mail-ens, nom, prénom, tel)

  • UE(code_UE, intitulé, semestre, nb_crédits, e-mail-ens)

  • Séance(id_séance, code_UE, e-mail-ens, type, salle, date, heure)

  • Présence(e-mail-eleve, id_seance)

  • Elève(e-mail-eleve, nom, prénom, tel)

  • Examen(code_UE, e-mail-eleve, date, heure, note)

Création de tables SQL

CREATE TABLE Enseignant (
    e_mail_ens VARCHAR(30) NOT NULL,
    nom VARCHAR(30) NOT NULL,
    prénom VARCHAR(30) NOT NULL,
    tel VARCHAR(12),
    PRIMARY KEY (e_mail_ens));

Enseignant(e-mail-ens, nom, prénom, tel)

UE(code_UE, intitulé, semestre, nb_crédits, e-mail-ens)

CREATE TABLE UE (
    code_UE VARCHAR(30) NOT NULL,
    intitulé VARCHAR(30) NOT NULL,
    semestre INTEGER NOT NULL,
    nb_crédits INTEGER NOT NULL,
    e_mail_ens VARCHAR(30) NOT NULL,
    PRIMARY KEY (code_UE),
    FOREIGN KEY (e_mail_ens) REFERENCES Enseignant);

Passage au modèle UML (I)

Passage au modèle UML (II)

Réalisation en Python

Pour chaque Entité une classe distincte.

class Enseignant:
    def __init__(self, e_mail_ens , nom, prénom, tel):
        self.e_mail_ens = e_mail_ens
        self.nom = nom
        self.prénom = prénom
        self.tel = tel
        self.responsabilités = set()
        self.séances = set()
 
    def ajoute_seance(self, séance):
        self.séances.add(séance)
 
    def ajoute_responsabilité(self, UE):
        self.responsabilités.add(UE)

Réalisation en Python

Pour chaque Entité une classe distincte.

class Séance:
    def __init__(self, id_séance , date, heure, salle, type, enseignant):
        self.id_séance = id_séance
        self.date = date
        self.heure = heure
        self.salle = salle
        self.type = type
        self.enseignant = enseignant
        self.présence = set()
 
    def ajoute_présence(self, élève):
        self.présence.add(élève)
 

Mise en oeuvre : le patron DAO

Un DAO (Data Access Object) est une classe qui réalise l'interface entre une classe d'objets persistants et la base de données.

  • Une classe DAO permet de mettre en œuvre les quatre opérations de base (CRUD) :

    • Create

    • Read

    • Update

    • Delete

  • Il existe autant de classes DAO que de classes persistantes

Mise en oeuvre : le patron DAO

Dans l'exemple considéré, on doit donc avoir les six classes suivantes:

  • Enseignant_DAO

  • UE_DAO

  • Séance_DAO

  • Elève_DAO

  • Examen_DAO

Mise en oeuvre : le patron DAO

En python :

class Enseignant_DAO:
    def __init__(self, db_name):
        self.db = sqlite3.connect(db_name)
    def create_enseignant(self, enseignant):
        ...
    def get_enseignant_by_id(self, id_enseignant): # Read
        ...
    def update_enseignant(self, enseignant):
        ...
    def delete_enseignant(self, enseignant):
        ...

get_enseignant_by_id

En python :

class Enseignant_DAO:
    def __init__(self, db_name):
        self.db = sqlite3.connect(db_name)
    def create_enseignant(self, enseignant):
        ...
    def get_enseignant_by_id(self, id_enseignant): # Read
        ...
    def update_enseignant(self, enseignant):
        ...
    def delete_enseignant(self, enseignant):
        ...
  1. recherche les données de l'enseignant dans la table Enseignant
  2. initialisation un objet enseignant de type Enseignant
  3. recherche les séances programmées dans la table Séances
  4. initialise et insère dans enseignant.séances autant d'objets de type Séance
  5. recherche des responsabilités d'UE dans la table UE
  6. initialise et insère dans enseignant.responsabilité autant d'objets de type UE

get_enseignant_by_id

En python :

from enseignant import Enseignant

class Enseignant_DAO:
    def __init__(self, db_name):
        self.db = sqlite3.connect(db_name)
    def create_enseignant(self, enseignant):
        ...
    def get_enseignant_by_id(self, id_enseignant, fill=True): # Read
        c = db.cursor()
        t_enseignant = c.execute("SELECT * FROM Enseignant WHERE e_mail_ens = ?", (id_enseignant,)).fetchone()
        enseignant = Enseignant(t_enseignant[0], t_enseignant[1], t_enseignant[2], t_enseignant[3])
        if fill:
            seance_DAO = Seance_DAO(self.db_name)
            liste_id_seances = c.execute("SELECT id_séance FROM Seance WHERE e_mail_ens = ?", (id_enseignant,)).fetchall()
            for t_id_seance in liste_id_seances:
            	enseignant.séances.add(seance_DAO.get_seance_by_id(t_id_seance), fill=False)
            ue_DAO = UE_DAO(self.db_name)
            liste_code_UE = c.execute("SELECT code_UE FROM UE WHERE e_mail_ens = ?")
            for t_code_UE in liste_code_UE:
                enseignant.responsabilité.add(ue_DAO.get_UE_by_id(t_code_UE), fill=False)
        return enseignant
        
    def update_enseignant(self, enseignant):
        ...
    def delete_enseignant(self, enseignant):
        ...

Raffinement : l'héritage

En python :

class DAO:
    def __init__(self, db_name):
            self.db = sqlite3.connect(db_name)

class Enseignant_DAO(DAO):
    def create_enseignant(self, enseignant):
        ...
    def get_enseignant_by_id(self, id_enseignant): # Read
        ...
    def update_enseignant(self, enseignant):
        ...
    def delete_enseignant(self, enseignant):
        ...
  • Problème : avec le patron DAO, l'existence de relations many-to-many a pour effet de charger l'intégralité des tables concernées en mémoire lors de la lecture d'un objet unique!!
  • Exemple : relation many-to-many entre Elève et Séance :

    • La méthode get_séance_by_id fait appel à get_eleve_by_id pour établir la liste de présence

    • La méthode get_eleve_by_id fait appel à get_séance_by_id pour établir la liste des séances auxquelles l'élève a assisté

    • etc….

  • Il faut donc prévoir de ne charger qu'une partie des informations, celle qui est réellement utile au programme (inutile de charger l'emploi du temps de chaque élève lorsqu'on s'intéresse à la liste de présence d'une séance particulière).

  • Avec le patron DAO, il faut gérer au cas par cas

  • Les Gestionnaires de persistance ORM (django, Pony ORM) permettent de gérer le chargement des données "à la demande", à la manière de la mémoire cache.

Partie 1

Persistance des données

Section 4

Un gestionnaire de persistance : la librairie Pony ORM

Un gestionnaire de persistance : la librairie Pony ORM

Partie 1

Persistance des données

Section 5

Le patron MVC

Présentation

  • Le sigle MVC signifie "Modèle - Vue - Contrôleur"
  • Il s'agit d'un patron de conception
  • Destiné à faciliter le développement d'interfaces graphiques.

Interface Graphique

Une Interface graphique (ou GUI -- Graphical User Interface) est constituée essentiellement de deux modules :

  • Le "front-end" (la "devanture"), qui est la partie du programme visible pour l'utilisateur et avec laquelle l'utilisateur peut interagir à l'aide de menus, de boutons et de formulaires…

  • Le "back-end" (l'"arrière-boutique"), qui correspond aux rouages invisible à l'utilisateur, permettant au programme de réaliser la tâche pour laquelle il a été conçu.

Modularité

Pour développer un tel programme, on le divise généralement en trois modules appelés respectivement:

  • le Modèle

  • la Vue

  • le Contrôleur

Le modèle

Le modèle est la partie du programme :

  • qui manipule et met à jour les informations qui doivent être conservées d'une session à l'autre.
  • Il s'agit de l'ensemble des variables et objets qui sont créés et mis à jour par l'utilisateur lorsqu'il interagit avec le programme.

Modèle

La vue

La Vue est la partie du programme qui gère la mise en page, la disposition des informations, des boutons et des formulaires, l'organisation et la visibilité des différentes fenêtres du programme s'il y en a.

  • La Vue fait appel au Contrôleur à chaque fois que l'utilisateur effectue une action (saisie d'information, pointage de souris, sélection de menu, activation d'un bouton etc…)

  • La Vue fait appel au Modèle pour afficher en permanence un contenu actualisé par les actions de l'utilisateur.

Modèle

Contrôleur

Vue

READ

ACT

Le contrôleur

Le contrôleur est la partie du programme qui gère les actions de l'utilisateur. Chacune des actions proposées dans la vue est implémentée dans le contrôleur sous la forme d'une fonction.

  • Le contrôleur fait appel au Modèle lorsque l'action modifie les variables et objets manipulés par le programme.

Modèle

Contrôleur

Vue

CREATE

UPDATE

DELETE

ACT

Programmation événementielle

L'écriture d'une interface graphique permet de mettre en œuvre les principes de la programmation événementielle:

  • Une interface est constituée de plusieurs éléments graphiques (appelés widgets) positionnés dans une fenêtre.

    • les widgets sont éditables/positionnables via les méthodes définies dans la librairie

    • il est possible de modifier leur contenu en cours d'exécution (via des événements)

Programmation événementielle

  • Les actions de l'utilisateur (mouvements et clics de souris, entrées clavier ,…) produisent des événements:

  • Les événements sont déclenchés par des widgets actifs (boutons, menus,…) capables de lancer l'exécution d'une ou plusieurs opérations:

    • mise à jour d'une variable ou d'un attribut

    • lancement d'un calcul

    • envoi d'un message

    • modification du rendu visuel

    • arrêt du programme

    • etc.

Programmation événementielle

Dans le cadre du patron MVC, les informations affichées dans l'interface (le contenu des widgets) sont paramétrées par les objets du modèle. On a typiquement le cycle suivant :

  • L'utilisateur déclenche une action via l'interface

  • Le contrôleur exécute l'action

  • Les changements produits par l'action sont répercutés dans le modèle

  • l'interface consulte le modèle pour mettre à jour son contenu.

Partie 2

Analyse des données

Partie 2

Analyse des données

Section 1

Données orientées document

Texte et Document

  • Textes,
  • comptes rendus,

  • série de notes, de valeurs sans format précis :

Le format txt désigne des données non structurées de type “texte” regroupant différents modes d’encodage :

  • ASCII (caractères sans accent),

  • utf8 (caractères accentués et spéciaux),

Texte et Document

  • Un document contient des chapitres, des sections, des sous-sections etc…
  • Organisation des données correspondant à une structure d’arbre.

  • Dans le cas d’un recueil de données, correspond à la définition de rubriques et sous-rubriques.

Texte et Document

Formats xml, xhtml, json, …

Pour les données organisées de manière hiérarchique. Des balises servent à séparer les différents attributs.

<nom> Dubois </nom>
<prénom> Martine </prénom>
<adresse>
  <num> 28 </num>
  <voie> rue des Lilas </voie>
  <code postal> 45000 </code postal>
  <ville> Orléans </ville>
</adresse>
<âge> 45 </âge>

XML

Texte et Document

Formats xml, xhtml, json, …

Pour les données organisées de manière hiérarchique. Des balises servent à séparer les différents attributs.

{
  "nom" : "Dubois",
  "prénom" : "Martine",
  "adresse" :
  {
    "numero" : 28,
    "voie" : "rue des Lilas",
    "code_postal" : 45000,
    "ville" : "Orléans"
  },
  "âge" : 45
}

json (JavaScript Object Notation)

Texte et Document

Formats xml, xhtml, json, …

Pour les données organisées de manière hiérarchique. Des balises servent à séparer les différents attributs.

data-driven-programming

By Emmanuel Dauce

data-driven-programming

  • 1,415