Bonnes pratiques
Principes de conception modulaire
1. Principe de responsabilité unique
## Mauvais exemple : Plusieurs responsabilités
class UserManager:
def create_user(self, username, password):
## Logique de création d'utilisateur
self.validate_password(password)
self.save_to_database()
self.send_welcome_email()
## Bon exemple : Responsabilités séparées
class UserValidator:
def validate_password(self, password):
## Logique de validation du mot de passe
pass
class UserRepository:
def save_user(self, user):
## Logique de sauvegarde en base de données
pass
class NotificationService:
def send_welcome_email(self, user):
## Logique d'envoi d'e-mail de bienvenue
pass
Gestion des dépendances
Injection de dépendances
graph TD
A[Module de haut niveau] -->|Dépend de l'abstraction| B[Interface d'abstraction]
C[Implémentation concrète 1] -.-> B
D[Implémentation concrète 2] -.-> B
from abc import ABC, abstractmethod
class DatabaseConnector(ABC):
@abstractmethod
def connect(self):
pass
class MySQLConnector(DatabaseConnector):
def connect(self):
## Logique de connexion spécifique à MySQL
pass
class PostgreSQLConnector(DatabaseConnector):
def connect(self):
## Logique de connexion spécifique à PostgreSQL
pass
class DataProcessor:
def __init__(self, connector: DatabaseConnector):
self._connector = connector
def process_data(self):
connection = self._connector.connect()
## Traiter les données en utilisant la connexion
Gestion des erreurs et journalisation
Gestion complète des erreurs
import logging
from typing import Optional
class CustomError(Exception):
"""Classe de base pour les erreurs personnalisées"""
pass
def configure_logging():
logging.basicConfig(
level=logging.INFO,
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
filename='application.log'
)
return logging.getLogger(__name__)
def safe_division(a: float, b: float) -> Optional[float]:
logger = configure_logging()
try:
result = a / b
logger.info(f"Division réussie de {a} par {b}")
return result
except ZeroDivisionError:
logger.error(f"Division par zéro : {a} / {b}")
raise CustomError("Impossible de diviser par zéro")
Métriques de qualité du code
Pratique |
Description |
Avantage |
Indication de type (Type Hinting) |
Utilisation d'annotations de type |
Amélioration de la lisibilité du code |
Docstrings |
Documentation complète |
Meilleure compréhension |
Tests unitaires |
Couverture de test étendue |
Réduction de l'introduction de bugs |
Vérification statique du code (Code Linting) |
Analyse statique du code |
Qualité du code cohérente |
Chargement paresseux (Lazy Loading) et générateurs
def large_file_processor(filename):
def line_generator():
with open(filename, 'r') as file:
for line in file:
## Traiter la ligne de manière paresseuse
yield line.strip()
for processed_line in line_generator():
## Traitement économisant la mémoire
process(processed_line)
Modèles de conception
Modèle de méthode fabrique (Factory Method Pattern)
class DatabaseFactory:
@staticmethod
def get_database(db_type: str):
if db_type == 'mysql':
return MySQLDatabase()
elif db_type == 'postgresql':
return PostgreSQLDatabase()
else:
raise ValueError(f"Type de base de données non pris en charge : {db_type}")
Considérations de sécurité
Validation des entrées
import re
from typing import Optional
def validate_email(email: str) -> Optional[str]:
email_pattern = r'^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$'
if re.match(email_pattern, email):
return email
else:
raise ValueError("Format d'e-mail invalide")
Recommandations pour l'intégration continue
- Utilisez des environnements virtuels
- Mettez en œuvre des tests automatisés
- Utilisez un système de contrôle de version (Git)
- Configurez des pipelines CI/CD
LabEx souligne que le respect de ces bonnes pratiques améliorera considérablement la maintenabilité, la lisibilité et la qualité globale de votre projet Python.