Analyse → Conception → Développement → Tests → Déploiement → Maintenance
Interface de gestion : Système permettant à l'utilisateur d'entrer, modifier, supprimer et afficher des données de manière organisée.
- Analyser les besoins de l'utilisateur
- Concevoir l'interface utilisateur
- Implémenter la logique de gestion
- Valider les données entrantes
- Tester l'interface
- Champs de saisie
- Boutons d'action
- Zone d'affichage
- Système de validation
- Messages d'erreur
import tkinter as tk
from tkinter import messagebox
class GestionContacts:
def __init__(self):
self.fenetre = tk.Tk()
self.fenetre.title("Gestion des contacts")
self.contacts = []
# Création des widgets
self.creer_widgets()
def creer_widgets(self):
# Cadre principal
cadre_principal = tk.Frame(self.fenetre, padx=20, pady=20)
cadre_principal.pack(fill=tk.BOTH, expand=True)
# Champs pour nom
tk.Label(cadre_principal, text="Nom :").grid(row=0, column=0, sticky=tk.W)
self.champ_nom = tk.Entry(cadre_principal, width=30)
self.champ_nom.grid(row=0, column=1, padx=10, pady=5)
# Champs pour email
tk.Label(cadre_principal, text="Email :").grid(row=1, column=0, sticky=tk.W)
self.champ_email = tk.Entry(cadre_principal, width=30)
self.champ_email.grid(row=1, column=1, padx=10, pady=5)
# Boutons
cadre_boutons = tk.Frame(cadre_principal)
cadre_boutons.grid(row=2, column=0, columnspan=2, pady=10)
tk.Button(cadre_boutons, text="Ajouter", command=self.ajouter_contact).pack(side=tk.LEFT, padx=5)
tk.Button(cadre_boutons, text="Afficher", command=self.afficher_contacts).pack(side=tk.LEFT, padx=5)
tk.Button(cadre_boutons, text="Effacer", command=self.effacer_champs).pack(side=tk.LEFT, padx=5)
import tkinter as tk
from tkinter import messagebox
import re
class GestionContacts:
def __init__(self):
self.fenetre = tk.Tk()
self.fenetre.title("Gestion des contacts")
self.fenetre.geometry("500x400")
self.contacts = []
self.creer_widgets()
def creer_widgets(self):
cadre_principal = tk.Frame(self.fenetre, padx=20, pady=20)
cadre_principal.pack(fill=tk.BOTH, expand=True)
# Titre
titre = tk.Label(cadre_principal, text="Gestion des contacts", font=("Arial", 16, "bold"))
titre.grid(row=0, column=0, columnspan=2, pady=10)
# Champs
tk.Label(cadre_principal, text="Nom :").grid(row=1, column=0, sticky=tk.W)
self.champ_nom = tk.Entry(cadre_principal, width=30)
self.champ_nom.grid(row=1, column=1, padx=10, pady=5)
tk.Label(cadre_principal, text="Email :").grid(row=2, column=0, sticky=tk.W)
self.champ_email = tk.Entry(cadre_principal, width=30)
self.champ_email.grid(row=2, column=1, padx=10, pady=5)
# Boutons
cadre_boutons = tk.Frame(cadre_principal)
cadre_boutons.grid(row=3, column=0, columnspan=2, pady=10)
tk.Button(cadre_boutons, text="Ajouter", command=self.ajouter_contact).pack(side=tk.LEFT, padx=5)
tk.Button(cadre_boutons, text="Afficher", command=self.afficher_contacts).pack(side=tk.LEFT, padx=5)
tk.Button(cadre_boutons, text="Effacer", command=self.effacer_champs).pack(side=tk.LEFT, padx=5)
# Zone d'affichage
tk.Label(cadre_principal, text="Contacts :").grid(row=4, column=0, sticky=tk.W, pady=(10,0))
self.zone_affichage = tk.Text(cadre_principal, height=10, width=50)
self.zone_affichage.grid(row=5, column=0, columnspan=2, pady=5)
def valider_email(self, email):
pattern = r'^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$'
return re.match(pattern, email) is not None
def ajouter_contact(self):
nom = self.champ_nom.get().strip()
email = self.champ_email.get().strip()
if not nom:
messagebox.showerror("Erreur", "Le nom est obligatoire")
return
if not email:
messagebox.showerror("Erreur", "L'email est obligatoire")
return
if not self.valider_email(email):
messagebox.showerror("Erreur", "Email invalide")
return
self.contacts.append({"nom": nom, "email": email})
messagebox.showinfo("Succès", f"Contact {nom} ajouté")
self.effacer_champs()
def afficher_contacts(self):
self.zone_affichage.delete(1.0, tk.END)
for i, contact in enumerate(self.contacts):
self.zone_affichage.insert(tk.END, f"{i+1}. {contact['nom']} - {contact['email']}\n")
def effacer_champs(self):
self.champ_nom.delete(0, tk.END)
self.champ_email.delete(0, tk.END)
def run(self):
self.fenetre.mainloop()
# Exécution de l'application
app = GestionContacts()
app.run()
• Validation préalable : Vérifier les données avant traitement
• Interface intuitive : Organiser les éléments de manière logique
• Messages clairs : Informer l'utilisateur des actions effectuées
Fichiers CSV : Fichiers texte contenant des données tabulaires séparées par des virgules.
- Ouverture du fichier
- Lecture des lignes
- Validation des données
- Transformation des types
- Stockage dans une structure
import csv
import os
def lire_csv_valide(nom_fichier):
if not os.path.exists(nom_fichier):
print(f"Erreur : Fichier {nom_fichier} non trouvé")
return None
with open(nom_fichier, 'r', encoding='utf-8') as f:
lecteur = csv.DictReader(f)
donnees = []
for ligne in lecteur:
# Validation des champs
if valider_ligne(ligne):
donnees.append(ligne)
else:
print(f"Ligne invalide ignorée : {ligne}")
return donnees
import csv
import os
def valider_ligne(ligne):
"""Valide une ligne de données CSV"""
# Vérifier que les champs obligatoires sont présents
champs_obligatoires = ['nom', 'email', 'age']
for champ in champs_obligatoires:
if not ligne.get(champ, '').strip():
return False
# Vérifier le format de l'email
import re
email_pattern = r'^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$'
if not re.match(email_pattern, ligne['email']):
return False
# Vérifier que l'âge est un nombre valide
try:
age = int(ligne['age'])
if age < 0 or age > 150:
return False
except ValueError:
return False
return True
def lire_et_valider_csv(nom_fichier):
"""Lit et valide un fichier CSV"""
if not os.path.exists(nom_fichier):
print(f"Erreur : Fichier {nom_fichier} non trouvé")
return []
try:
with open(nom_fichier, 'r', encoding='utf-8') as f:
lecteur = csv.DictReader(f)
donnees_valides = []
erreurs = []
for i, ligne in enumerate(lecteur, start=1):
if valider_ligne(ligne):
# Convertir l'âge en entier
ligne['age'] = int(ligne['age'])
donnees_valides.append(ligne)
else:
erreurs.append(f"Ligne {i} invalide : {ligne}")
# Afficher les erreurs
if erreurs:
print("Erreurs détectées :")
for erreur in erreurs:
print(erreur)
return donnees_valides
except Exception as e:
print(f"Erreur lors de la lecture : {e}")
return []
# Exemple d'utilisation
donnees = lire_et_valider_csv("contacts.csv")
print(f"{len(donnees)} contacts valides lus")
• Existence du fichier : Vérifier avant l'ouverture
• Validation ligne par ligne : Traiter chaque ligne individuellement
• Conversion des types : Convertir les données après validation
Intégration de base de données : Connexion d'une application à une base de données pour stocker et récupérer des données.
- Connexion à la base
- Création des tables
- Insertion des données
- Requêtes de lecture
- Fermeture de la connexion
import sqlite3
def initialiser_base():
connexion = sqlite3.connect('donnees.db')
curseur = connexion.cursor()
# Création de la table
curseur.execute('''
CREATE TABLE IF NOT EXISTS contacts (
id INTEGER PRIMARY KEY AUTOINCREMENT,
nom TEXT NOT NULL,
email TEXT UNIQUE NOT NULL,
telephone TEXT
)
''')
connexion.commit()
return connexion
def ajouter_contact(connexion, nom, email, telephone=None):
curseur = connexion.cursor()
try:
curseur.execute(
"INSERT INTO contacts (nom, email, telephone) VALUES (?, ?, ?)",
(nom, email, telephone)
)
connexion.commit()
print("Contact ajouté avec succès")
except sqlite3.IntegrityError:
print("Erreur : Email déjà existant")
import sqlite3
class BaseDeDonnees:
def __init__(self, nom_fichier):
self.connexion = sqlite3.connect(nom_fichier)
self.creer_tables()
def creer_tables(self):
"""Crée les tables nécessaires"""
curseur = self.connexion.cursor()
curseur.execute('''
CREATE TABLE IF NOT EXISTS contacts (
id INTEGER PRIMARY KEY AUTOINCREMENT,
nom TEXT NOT NULL,
email TEXT UNIQUE NOT NULL,
telephone TEXT,
date_creation TIMESTAMP DEFAULT CURRENT_TIMESTAMP
)
''')
self.connexion.commit()
def ajouter_contact(self, nom, email, telephone=None):
"""Ajoute un contact à la base"""
curseur = self.connexion.cursor()
try:
curseur.execute(
"INSERT INTO contacts (nom, email, telephone) VALUES (?, ?, ?)",
(nom, email, telephone)
)
self.connexion.commit()
print(f"Contact {nom} ajouté avec succès")
except sqlite3.IntegrityError:
print(f"Erreur : Contact avec email {email} déjà existant")
def recuperer_contacts(self):
"""Récupère tous les contacts"""
curseur = self.connexion.cursor()
curseur.execute("SELECT * FROM contacts ORDER BY nom")
return curseur.fetchall()
def rechercher_par_email(self, email):
"""Recherche un contact par email"""
curseur = self.connexion.cursor()
curseur.execute("SELECT * FROM contacts WHERE email = ?", (email,))
return curseur.fetchone()
def fermer_connexion(self):
"""Ferme la connexion à la base"""
self.connexion.close()
# Exemple d'utilisation
base = BaseDeDonnees('contacts.db')
base.ajouter_contact("Alice Martin", "alice@email.com", "0123456789")
base.ajouter_contact("Bob Dupont", "bob@email.com")
contacts = base.recuperer_contacts()
for contact in contacts:
print(contact)
base.fermer_connexion()
• Sécurité des requêtes : Utiliser des paramètres pour éviter l'injection SQL
• Connexion sécurisée : Toujours fermer la connexion après utilisation
• Validation des données : Vérifier les données avant insertion
API (Application Programming Interface) : Interface permettant à des programmes de communiquer entre eux.
- URL de l'endpoint
- Méthode HTTP (GET, POST, etc.)
- Headers (authentification)
- Paramètres de requête
- Gestion des réponses
import requests
import json
def recuperer_donnees_api(url):
try:
reponse = requests.get(url)
if reponse.status_code == 200:
return reponse.json()
else:
print(f"Erreur : Code {reponse.status_code}")
return None
except requests.RequestException as e:
print(f"Erreur de requête : {e}")
return None
def afficher_donnees(donnees):
if donnees:
for item in donnees:
print(f"ID: {item.get('id')}, Nom: {item.get('name')}")
import requests
import json
class ConsommateurAPI:
def __init__(self, base_url):
self.base_url = base_url
self.headers = {'Content-Type': 'application/json'}
def envoyer_requete(self, endpoint, params=None):
"""Envoie une requête GET à l'API"""
url_complet = f"{self.base_url}/{endpoint}"
try:
reponse = requests.get(url_complet, params=params, headers=self.headers)
if reponse.status_code == 200:
return reponse.json()
elif reponse.status_code == 404:
print("Erreur 404 : Ressource non trouvée")
return None
elif reponse.status_code == 401:
print("Erreur 401 : Non autorisé")
return None
else:
print(f"Erreur {reponse.status_code} : {reponse.text}")
return None
except requests.ConnectionError:
print("Erreur de connexion")
return None
except requests.Timeout:
print("Délai de connexion dépassé")
return None
except Exception as e:
print(f"Erreur inattendue : {e}")
return None
def recuperer_utilisateur(self, user_id):
"""Récupère un utilisateur par son ID"""
return self.envoyer_requete(f"users/{user_id}")
def recuperer_liste_utilisateurs(self, page=1):
"""Récupère une liste d'utilisateurs"""
params = {'page': page}
return self.envoyer_requete("users", params)
def afficher_utilisateur(self, utilisateur):
"""Affiche les informations d'un utilisateur"""
if utilisateur:
print(f"Nom: {utilisateur.get('name', 'N/A')}")
print(f"Email: {utilisateur.get('email', 'N/A')}")
print(f"Site web: {utilisateur.get('website', 'N/A')}")
else:
print("Aucun utilisateur à afficher")
# Exemple d'utilisation avec une API publique
api = ConsommateurAPI("https://jsonplaceholder.typicode.com")
utilisateur = api.recuperer_utilisateur(1)
api.afficher_utilisateur(utilisateur)
• Codes de statut : Vérifier le code de réponse HTTP
• Gestion des erreurs : Capturer les exceptions de réseau
• Sécurité : Utiliser HTTPS et authentification si nécessaire
Jeu interactif : Programme qui réagit aux actions de l'utilisateur en temps réel.
- États du jeu
- Gestion des entrées
- Logique du jeu
- Affichage
- Boucle principale
class JeuSimple:
def __init__(self):
self.etat = "menu" # menu, jeu, pause, fin
self.score = 0
self.vie = 3
def boucle_principale(self):
while self.etat != "quitte":
self.mettre_a_jour()
self.afficher()
self.gerer_entrees()
def gerer_entrees(self):
# Dans une vraie application, capturer les événements clavier/souris
commande = input("Entrez une commande (haut/bas/gauche/droite/quitter): ")
if commande.lower() == "quitter":
self.etat = "quitte"
elif commande.lower() in ["haut", "bas", "gauche", "droite"]:
self.deplacer_joueur(commande.lower())
def deplacer_joueur(self, direction):
# Mettre à jour la position du joueur
if direction == "haut":
self.joueur_y -= 1
elif direction == "bas":
self.joueur_y += 1
# ... autres directions
class JeuDevinette:
def __init__(self):
self.nombre_secret = self.generer_nombre_secret()
self.tentatives = 0
self.max_tentatives = 5
self.termine = False
def generer_nombre_secret(self):
import random
return random.randint(1, 100)
def valider_entree(self, entree):
"""Valide que l'entrée est un nombre entre 1 et 100"""
try:
nombre = int(entree)
return 1 <= nombre <= 100
except ValueError:
return False
def gerer_entree_utilisateur(self):
"""Demande et valide l'entrée de l'utilisateur"""
while True:
entree = input(f"Tentative {self.tentatives + 1}/{self.max_tentatives} - Devinez un nombre entre 1 et 100 : ")
if self.valider_entree(entree):
return int(entree)
else:
print("Erreur : Veuillez entrer un nombre entre 1 et 100")
def verifier_proposition(self, proposition):
"""Vérifie la proposition et met à jour l'état du jeu"""
self.tentatives += 1
if proposition == self.nombre_secret:
print(f"Félicitations ! Vous avez trouvé le nombre {self.nombre_secret} en {self.tentatives} tentatives !")
self.termine = True
elif proposition < self.nombre_secret:
print("Trop petit ! Essayez un nombre plus grand.")
else:
print("Trop grand ! Essayez un nombre plus petit.")
if self.tentatives >= self.max_tentatives and not self.termine:
print(f"Dommage ! Le nombre était {self.nombre_secret}")
self.termine = True
def jouer(self):
"""Boucle principale du jeu"""
print("=== Jeu de Devinette ===")
print("Devinez un nombre entre 1 et 100")
print(f"Vous avez {self.max_tentatives} tentatives")
while not self.termine:
proposition = self.gerer_entree_utilisateur()
self.verifier_proposition(proposition)
print("Partie terminée !")
# Exemple d'utilisation
jeu = JeuDevinette()
jeu.jouer()
• Validation continue : Vérifier chaque entrée utilisateur
• Retours immédiats : Informer l'utilisateur des résultats
• Limites de jeu : Définir des contraintes claires
- Analyse des besoins : Identifier les types d'entrées/sorties
- Conception : Planifier l'interface et les validations
- Implémentation : Créer les composants et la logique
- Validation : Tester avec diverses données
- Sécurité : Protéger contre les attaques
- Documentation : Expliquer l'utilisation
- La validation des données est essentielle pour la sécurité
- Les interfaces doivent être intuitives pour l'utilisateur
- La gestion des erreurs améliore l'expérience utilisateur
- Les API doivent être consommées de manière sécurisée
- Les bases de données nécessitent des requêtes paramétrées
Spécifications → Conception → Développement → Validation → Sécurité → Déploiement