interface Module_Facturation { public function est_actif() : bool; public function initialiser() : void; } — cette déclaration, aussi modeste soit-elle, change complètement la façon dont une extension volumineuse peut décider, à chaque requête, quels blocs de code charger réellement en mémoire plutôt que de tout instancier par précaution.
Ce billet ne traite pas le découpage d’une extension en plusieurs extensions séparées, publiées et activées indépendamment. Il porte sur l’architecture interne d’une seule et même extension devenue volumineuse au fil des ans, dont toutes les fonctionnalités ne sont pas utilisées sur tous les sites qui l’installent.
Le problème : tout charger, même ce qui ne sert jamais
Une extension qui a grandi par ajouts successifs — module de facturation, module d’export, module de notifications, module de rapports — finit souvent par tout charger au démarrage, via un unique fichier principal qui inclut chaque classe sans condition. Un site qui n’utilise que le module de notifications paie pourtant le coût mémoire et le temps d’autoload de l’ensemble, y compris des modules jamais sollicités.
Définir un contrat commun via une interface
La première étape consiste à définir une interface partagée par tous les modules, indépendamment de leur fonctionnalité propre. Cette interface ne décrit pas ce que fait le module, mais comment l’extension principale doit interagir avec lui : peut-il être activé sur ce site, et comment s’initialise-t-il si c’est le cas.
interface Module_Interface {
public function est_actif() : bool;
public function initialiser() : void;
}
final class Module_Facturation implements Module_Interface {
public function est_actif() : bool {
return class_exists( 'WooCommerce' );
}
public function initialiser() : void {
require_once __DIR__ . '/facturation/class-gestionnaire-factures.php';
add_action( 'woocommerce_order_status_completed', [ new Gestionnaire_Factures(), 'generer' ] );
}
}
Un registre central qui n’instancie que ce qui est actif

Le fichier principal de l’extension ne connaît plus le détail de chaque module : il se contente de parcourir un registre de classes candidates, d’interroger leur méthode est_actif(), et de n’appeler initialiser() que pour celles qui répondent positivement. Le fichier PHP du module lui-même n’est chargé — via require_once — qu’à l’intérieur de cette méthode initialiser(), jamais avant.