Stabilité avant suppression : stratégies pour coexister avec le code hérité dans les grands projets
Dans les systèmes longtemps maintenus et à forte charge, supprimer le code hérité comporte des risques de régressions et d'instabilité. Plutôt que de refactoriser en profondeur, il est plus intelligent de laisser le vieux et le nouveau code coexister grâce aux toggles de fonctionnalités et aux façades. Cette approche permet un développement continu sans interruption, tout en conservant les composants éprouvés comme sauvegardes.
Risques d'une suppression agressive
Même la suppression de code mort peut provoquer des échecs en raison de dépendances cachées — réflexion, chargement dynamique, appels RPC. Les tests des systèmes hérités couvrent rarement les cas limites, et les données de production activent souvent des chemins d'exécution rares. La perte de connaissances institutionnelles aggrave encore le problème : les équipes qui partent laissent derrière elles du code essentiel pour des scénarios spécifiques comme les migrations ou la conformité.
Dans les environnements enterprise, les modules personnalisés propres aux fournisseurs deviennent vulnérables : toute modification peut rompre le support du fournisseur.
Le principe "Laissez bien tranquille" en action
Un exemple classique est la sonde Deep Space 1 de NASA : du code datant des années 1970 est resté inchangé, encapsulé dans des adaptateurs. Les composants stables doivent rester intacts s'ils fonctionnent correctement. Cette stratégie mûre convient aux systèmes âgés de plus de cinq ans.
Architecture de coexistence : le figuier étrangleur à l’envers
Ne détruisez pas le code ancien — construisez le nouveau système en parallèle et transférez progressivement le trafic. Deux stratégies :
| Stratégie | Actions | Quand l’appliquer |
|----------|---------|------------------|
| Suppression | Réécriture sur une nouvelle pile | Logique simple, couverture de test à 100 %, aucune dépendance |
| Coexistence | Nouveau code exécuté aux côtés du vieux, routage progressif | Fonctionnalité critique, tests faibles, risque élevé |
Les toggles de fonctionnalités garantissent la sécurité :
- Développez la nouvelle implémentation.
- Enveloppez-la dans un contrôle d’activation.
- Faites-la tourner sur 1 % du trafic.
- Augmentez progressivement si tout se passe bien.
- Revenez en arrière via le toggle si des problèmes surviennent.
Le code hérité reste dans le dépôt pendant 2 à 3 ans pour analyser sa fiabilité.
Implémentation dans Spring Boot
Enveloppez le code ancien dans une interface sans modifier l’original.
// Service hérité (inchangé)
@Service
public class LegacyDiscountService {
public double calculateDiscount(Order order) {
// Logique d’il y a cinq ans
return order.getTotal() * 0.1;
}
}
// Nouveau service
@Service
public class NewDiscountService {
public double calculateDiscount(Order order) {
return applyComplexRules(order);
}
}
Façade avec toggle :
@Component
public class DiscountServiceFacade {
private final LegacyDiscountService legacyService;
private final NewDiscountService newService;
@Value("${feature.discount.new.enabled:false}")
private boolean useNewService;
public DiscountServiceFacade(LegacyDiscountService legacyService,
NewDiscountService newService) {
this.legacyService = legacyService;
this.newService = newService;
}
public double calculateDiscount(Order order) {
if (useNewService) {
return newService.calculateDiscount(order);
}
return legacyService.calculateDiscount(order);
}
}
Isolation via profils :
@Configuration
public class DiscountConfiguration {
@Bean
@ConditionalOnProperty(name = "feature.discount.new", havingValue = "false", matchIfMissing = true)
public DiscountService legacyDiscountService() {
return new LegacyDiscountService();
}
@Bean
@ConditionalOnProperty(name = "feature.discount.new", havingValue = "true")
public DiscountService newDiscountService() {
return new NewDiscountService();
}
}
Tests excluant le code ancien :
@Test
@DisabledIf("!${feature.discount.new.enabled}")
void testNewDiscountLogic() {
// Seulement la logique nouvelle
}
Flux de basculement du trafic
La passerelle API route selon les indicateurs : le monolithe comme sauvegarde, le microservice évolue progressivement. Le service de toggle de fonctionnalités gère les pourcentages en temps réel. Le code ancien reste en production pendant 2 à 3 ans.
Quand la suppression est inévitable
- Sécurité : CVEs dans des bibliothèques obsolètes.
- Conformité : violations du RGPD.
- Technologie EOL : versions Java sans correctifs.
- Absence d’expertise : aucun spécialiste disponible.
Même dans ces cas — utilisez un déploiement progressif avec possibilité de rollback.
Points clés
- La stabilité du système prime sur l’esthétique du code : la disponibilité compte plus que la suppression de lignes anciennes.
- Les dépendances cachées exigent une surveillance des appels réels en production avant toute suppression.
- Les toggles de fonctionnalités réduisent les risques de migration.
- La dette technique paie si les coûts de maintenance sont inférieurs à ceux du refactorisation.
- La mémoire technique dans le code : ne supprimez rien sans 100 % de certitude.
— Editorial Team
Aucun commentaire pour le moment.