Les expressions de code longues et enchevêtrées sont souvent un obstacle à la compréhension. Ce document présente des techniques éprouvées pour les décomposer et rendre le code plus clair et maintenable.
Utiliser des variables descritpives
Extraire des sous-expressions dans des variables nommées de manière explicite.
# Avant : expression directe dans la condition
if line.split(':')[0].strip() == "root":
# Après : variable explicative pour la clarté
extracted_user = line.split(':')[0].strip()
if extracted_user == "root":
Recourir à des variables de synthèse
Créer des variables booléennes pour résumer des conditions complexes et répétées.
// Avant : conditions dupliquées
if (request.user.id == document.owner_id) {
// Autorisation de modification
}
if (request.user.id != document.owner_id) {
// Mode lecture seule
}
// Après : variable de synthèse
boolean is_document_owner = (request.user.id == document.owner_id);
if (is_document_owner) {
// Autorisation de modification
}
if (!is_document_owner) {
// Mode lecture seule
}
Appliquer le théorème de De Morgan
Transformer les négations complexes en expressions plus lisibles grâce aux équivalences logiques.
// Théorème : ¬(A ∧ B) ≡ ¬A ∨ ¬B
// Exemple avant simplification
if (!(file_available && !is_read_only)) {
showError("Accès impossible.");
}
// Exemple après application du théorème
if (!file_available || is_read_only) {
showError("Accès impossible.");
}
Éviter les abus de logique à court-circuit
Préférer des structures de contrôle claires aux expressions complexes utilisant la logique à court-circuit.
// Avant : expression dense avec court-circuit
assert((!(container = LocateContainer(id))) || !container->IsFull());
// Après : logique séparée pour une meilleure lisibilité
container = LocateContainer(id);
if (container != nullptr) {
assert(!container->IsFull());
}
Chercher une approche plus élégante
Identifier des méthodes plus intuitives pour représenter la logique métier.
bool Interval::Intersects(Interval other) {
// Logique simplifiée pour détecter le chevauchement
if (other.end <= start) return false;
if (other.begin >= finish) return false;
return true;
}
Simplifier avec des macros ou fonctions utilitaires
Réduire la répétition dans les opérations similaires en utilisant des abstractions.
// Version avec répétition manuelle
void MergeStatistics(const Stats& source, Stats* target) {
target->set_total_memory(source.total_memory() + target->total_memory());
target->set_free_memory(source.free_memory() + target->free_memory());
// Autres champs...
}
// Version avec macro pour éviter la duplication
void MergeStatistics(const Stats& source, Stats* target) {
#define MERGE_FIELD(fieldName) target->set_##fieldName(source.fieldName() + target->fieldName())
MERGE_FIELD(total_memory);
MERGE_FIELD(free_memory);
// Autres champs...
#undef MERGE_FIELD
}