Efficience IT
·Projet

Conventions de codage : bonnes pratiques pour un code maintenable

Par Florian Chenot

Les conventions de codage sont souvent perçues comme un sujet de débutant. En réalité, leur impact se mesure à l'échelle : plus un projet grandit, plus l'absence de conventions cohérentes devient un frein systémique. Ce qui commence comme une préférence esthétique devient progressivement un levier d'architecture, de vélocité et de gouvernance technique.

Pourquoi les conventions sont un investissement, pas une contrainte

Un projet logiciel passe 80 % de son cycle de vie en maintenance. Le code est lu dix fois plus souvent qu'il n'est écrit. Les conventions réduisent la charge cognitive de cette lecture : un développeur qui rejoint un projet bien normé est productif en quelques jours plutôt qu'en quelques semaines.

Au-delà de la lisibilité, les conventions éliminent une catégorie entière de débats en code review. Quand l'outillage tranche automatiquement les questions de formatage, les revues se concentrent sur ce qui compte : la logique métier, les choix d'abstraction, la gestion des cas limites. Le retour sur investissement est mesurable : moins de commentaires cosmétiques, des pull requests mergées plus vite, une friction d'équipe réduite.

Les standards PSR : le socle commun en PHP

Les PHP Standards Recommendations (PSR) constituent le contrat social de l'écosystème PHP. Parmi elles, PSR-12 définit le style de code étendu : 4 espaces d'indentation, 120 caractères par ligne, placement des accolades, déclaration des namespaces et imports.

namespace App\Service;

use App\Repository\UserRepository;

class UserService
{
    public function __construct(
        private readonly UserRepository $userRepository,
    ) {
    }

    public function findActiveUsers(): array
    {
        return $this->userRepository->findBy([
            'active' => true,
        ]);
    }
}

PSR-12 s'appuie sur PSR-1 (codage de base) et PSR-4 (autoloading). Les autres PSR couvrent des domaines fonctionnels : logging (PSR-3), cache (PSR-6, PSR-16), HTTP (PSR-7, PSR-15, PSR-17, PSR-18), conteneur (PSR-11), événements (PSR-14). Connaître ces standards n'est pas optionnel pour un développeur PHP professionnel : ils définissent les interfaces d'interopérabilité entre frameworks et bibliothèques.

Nomenclature et conventions de nommage

Les conventions de nommage sont un prolongement naturel des PSR. En PHP et dans l'écosystème Symfony, le consensus est établi : PascalCase pour les classes, interfaces et enums ; camelCase pour les méthodes, fonctions et variables ; snake_case pour les clés de configuration YAML, les noms de colonnes SQL et les variables Twig ; kebab-case pour les URLs et les assets ; ALL_CAPS pour les constantes.

Ce consensus n'est pas arbitraire. Il permet à un développeur de déduire la nature d'un identifiant à partir de sa casse, sans consulter sa déclaration. C'est un gain cognitif concret sur les projets de taille significative.

PHP-CS-Fixer : du formatage manuel à l'automatisation

PHP-CS-Fixer est l'outil de référence pour appliquer automatiquement les conventions de style en PHP. Son usage minimal est trivial : une commande reformate l'ensemble du projet selon PSR-12 ou les conventions Symfony.

L'intérêt réel apparaît avec la configuration personnalisée. Un fichier .php-cs-fixer.dist.php à la racine du projet permet de définir un ruleset précis, adapté aux choix de l'équipe. On peut activer ou désactiver des règles individuellement, combiner plusieurs presets, et exclure certains répertoires.

Construire un ruleset d'équipe

Un ruleset efficace part d'un preset reconnu (Symfony, PSR-12, ou PER-CS) et ajuste les règles qui font débat. L'objectif est d'éliminer toute ambiguïté : chaque question de style doit avoir une réponse automatisée. Les règles les plus souvent personnalisées concernent l'import des classes (global ou par namespace), l'ordonnancement des use statements, le trailing comma dans les paramètres multi-lignes, et le style des PHPDoc.

Le fichier de configuration doit être versionné dans le dépôt. Il fait partie du contrat technique du projet, au même titre que le composer.json. Tout nouveau développeur qui clone le projet obtient les mêmes règles, sans configuration manuelle.

Conventions spécifiques à Symfony

Symfony impose ses propres conventions au-delà de PSR-12 : les services sont suffixés par leur rôle (UserHandler, OrderNormalizer), les commandes console héritent d'une structure précise, les voters et event subscribers suivent des conventions de nommage strictes. PHP-CS-Fixer avec le preset Symfony couvre une partie de ces règles, mais pas toutes.

Pour les conventions qui échappent au formatage automatique (structure des répertoires, nommage des services, patterns d'injection), la documentation d'équipe prend le relais. Un fichier CONVENTIONS.md versionné dans le dépôt, ou mieux, des Architecture Decision Records (ADR), formalisent ces choix et leur justification.

Intégration dans la CI : rendre les conventions incontournables

Les conventions non automatisées sont des suggestions. Seule l'intégration continue transforme une convention en règle. Un pipeline CI robuste pour un projet PHP comprend au minimum trois étapes : vérification du formatage (PHP-CS-Fixer en mode --dry-run --diff), analyse statique (PHPStan), et exécution des tests.

L'ordre compte. Le formatage est vérifié en premier car c'est le check le plus rapide et le plus fréquemment échoué par les nouveaux contributeurs. PHPStan vient ensuite, car ses erreurs sont souvent plus longues à corriger. Les tests passent en dernier.

Hooks Git et feedback local

Attendre le retour de la CI pour découvrir un problème de style est un gaspillage. Les hooks Git locaux, via GrumPHP ou un simple pre-commit hook, offrent un feedback instantané. Le développeur corrige avant même de pousser son code. Cette boucle de feedback courte accélère considérablement le cycle de développement.

Le fichier .editorconfig complète ce dispositif en normalisant les paramètres d'édition (indentation, fin de ligne, encodage) directement dans l'IDE, avant même la première frappe.

Analyse statique : des conventions qui vont au-delà du style

PHPStan et Psalm ne vérifient pas le formatage : ils analysent la sémantique du code. Types incorrects, appels à des méthodes inexistantes, variables potentiellement nulles, branches mortes. À des niveaux élevés (PHPStan niveau 8 ou 9), ils imposent une rigueur de typage comparable à celle des langages compilés.

L'analyse statique est une forme de convention avancée. Elle établit un contrat sur la qualité structurelle du code, pas seulement sur son apparence. Monter progressivement le niveau de PHPStan sur un projet existant est une stratégie d'amélioration continue plus efficace que la plupart des refactorings manuels.

SonarQube et les métriques de qualité

SonarQube ajoute une dimension supplémentaire : la mesure dans le temps. Complexité cyclomatique, couverture de tests, dette technique, duplications. Ces métriques permettent de détecter les dérives avant qu'elles ne deviennent critiques. Pour un lead ou un architecte, SonarQube est un outil de pilotage, pas simplement de vérification.

Les principes SOLID comme convention architecturale

Les principes SOLID transcendent le style pour atteindre l'architecture. Responsabilité unique : chaque classe a une seule raison de changer. Ouvert/Fermé : extension par ajout, pas par modification. Substitution de Liskov : les sous-types respectent le contrat du parent. Ségrégation des interfaces : pas de dépendance sur des méthodes inutilisées. Inversion des dépendances : dépendre des abstractions, pas des implémentations.

Ces principes ne sont pas des règles de style. Ce sont des conventions architecturales. Dans un projet Symfony, ils se traduisent concrètement : la logique métier vit dans des services dédiés (pas dans les contrôleurs), les dépendances sont injectées via le conteneur (pas instanciées manuellement), les interfaces définissent les contrats entre couches.

Scaler les conventions sur plusieurs équipes

Quand une organisation dépasse une seule équipe, les conventions deviennent un enjeu de gouvernance. Chaque équipe qui définit ses propres règles crée un dialecte. Un développeur qui change d'équipe doit réapprendre des habitudes. La mobilité interne ralentit, les revues croisées deviennent pénibles.

Architecture Decision Records (ADR)

Les ADR formalisent les décisions techniques et leur contexte. Pour les conventions, un ADR documente : quel choix a été fait, pourquoi, quelles alternatives ont été écartées, et dans quelles conditions la décision pourrait être révisée. Cette traçabilité est précieuse quand un nouveau lead reprend un projet et se demande pourquoi telle règle existe.

Un socle partagé, des extensions par équipe

La stratégie qui fonctionne à l'échelle est hiérarchique : un package de configuration partagé (un preset PHP-CS-Fixer interne, une baseline PHPStan commune) définit le socle. Chaque équipe peut ajouter des règles spécifiques à son domaine, mais ne peut pas désactiver les règles du socle. Ce modèle préserve la cohérence globale tout en laissant une marge d'adaptation locale.

Les design patterns jouent un rôle similaire à cette échelle. Singleton, Factory, Observer, Adapter, Composite : ils constituent un vocabulaire partagé entre équipes. Dire "on utilise un pattern Strategy ici" est immédiatement compréhensible par tout développeur de l'organisation, indépendamment de son équipe d'origine.

Vers des conventions vivantes

Les conventions ne sont pas un document figé rédigé une fois et oublié. Elles évoluent avec le projet, le langage, l'écosystème. PSR-12 sera remplacée par PER-CS (PHP Evolving Recommendation - Coding Style). PHPStan ajoute régulièrement de nouvelles règles. Les frameworks adoptent de nouveaux patterns.

L'enjeu pour un architecte est de maintenir des conventions vivantes : régulièrement révisées, automatiquement appliquées, et comprises par tous. Un rituel trimestriel de revue des conventions, combiné à un outillage solide, garantit que les standards restent pertinents sans devenir un carcan.

Pour aller plus loin