Aller au contenu

Plan de migration

Status: GOVERNANCE / GUIDE D’ÉVOLUTION

Ce document ne décrit pas une suite de phases obligatoires vers une future « Platform V2 » séparée du système actuel.

Il décrit comment faire évoluer l’architecture existante sans casser le Runtime, sans recopier la dette historique et sans confondre cible et état CURRENT.

Principe

Une migration sûre déplace une responsabilité vers la bonne frontière, puis prouve que le comportement reste correct.

Observation du CURRENT
        ↓
Caractérisation
        ↓
Design cible / Contract
        ↓
Petit changement réversible
        ↓
Validation
        ↓
Activation explicite si nécessaire
        ↓
Retrait éventuel de l’ancien chemin

L’ordre dépend du composant. Il n’existe pas de séquence universelle imposant, par exemple, de terminer tous les Contracts avant tout travail Runtime ou toutes les verticales avant tout travail Frontend.

Étape 1 — Observer l’état réel

Avant toute migration :

  • identifier les fichiers chargés ;
  • identifier le point d’entrée Runtime ;
  • vérifier les consommateurs ;
  • distinguer CURRENT, TARGET, CONTRACT et HISTORICAL ;
  • déterminer si le composant lit, décide, orchestre ou écrit ;
  • relever les tests, audits et métriques disponibles.

Une ancienne roadmap, un ancien audit ou la présence d’un fichier ne suffit pas à établir le CURRENT.

Étape 2 — Caractériser le comportement

Avant un déplacement risqué, protéger l’existant par :

  • tests de caractérisation ;
  • audits read-only ;
  • échantillons reproductibles ;
  • mesures avant changement ;
  • vérification des statuts resolved, unknown, ambiguous, conflict lorsque concernés.

Cette étape permet de distinguer un refactoring d’un changement fonctionnel.

Étape 3 — Choisir la bonne frontière

La cible respecte les responsabilités suivantes :

  • Domain Core : règles métier génériques ;
  • Vertical Modules : connaissance propre à une famille produit ;
  • Read Services / Readers : observation sans mutation persistante ;
  • Write Services : mutation explicite ;
  • Runtime : orchestration ;
  • Adapters : WordPress, CLI, HTTP, SQL et transports ;
  • Frontend : consommation des projections ;
  • Projections : vues dérivées et reconstructibles.

Une migration est utile lorsqu’elle rapproche une responsabilité de cette frontière sans créer de nouveau contournement.

Étape 4 — Introduire la nouvelle voie sans casser l’ancienne

Selon le risque, la nouvelle implémentation peut être introduite derrière :

  • un Contract ;
  • une façade ;
  • un Reader ;
  • un Write Service ;
  • un Adapter ;
  • un shim de compatibilité ;
  • une feature activée explicitement.

La compatibilité temporaire est acceptable si son rôle est documenté et borné.

Elle ne doit pas devenir une deuxième source de vérité permanente.

Étape 5 — Valider avant mutation ou activation

Pour les données, privilégier :

Observation
→ Audit
→ Simulation
→ Validation
→ Write
→ Vérification

Pour le code et le Runtime, utiliser les contrôles applicables, notamment :

composer test
make lint
make check
make guard-static
make guard-runtime
make doctor
make docs-check

Toutes ces commandes ne sont pas nécessairement requises pour chaque petit changement. Le niveau de validation doit correspondre au risque réel.

Étape 6 — Activer selon le mécanisme réel du composant

Il n’existe pas de workflow universel draft → readonly → active.

L’activation dépend de la responsabilité concernée.

Exemple Feed :

registre
≠ activation

CCX_ACTIVE_FEEDS
+ ccx_feed_runtime_active_feeds()
= autorité Runtime

Un feed PREPARED peut être inspecté en lecture seule sans devenir actif.

Pour un autre composant, l’activation peut être un bootstrap, une route, une configuration, un writer, une tâche Runtime ou un déploiement. Il faut vérifier le mécanisme réel dans le code.

Étape 7 — Retirer l’ancien chemin seulement après preuve

La suppression d’un ancien composant exige au minimum :

  • absence de consommateur actif ou remplacement vérifié ;
  • tests et audits verts ;
  • validation du nouveau chemin ;
  • vérification des bind mounts et points de chargement ;
  • possibilité de rollback adaptée au risque.

Une copie ancienne peut être conservée comme HISTORICAL si elle apporte du contexte, à condition qu’elle ne soit plus présentée comme CURRENT.

Types de migrations fréquentes

Logique métier dans Runtime ou Adapter

Cible : déplacer la décision vers Domain Core, Application ou Vertical Module, puis laisser Runtime/Adapter orchestrer ou transporter.

Lecture SQL directe dans Frontend

Cible : Reader / Read Service / projection, puis Adapter et rendu.

Écriture dispersée

Cible : Write Service explicite avec validation, traçabilité et vérification après écriture.

Règle verticale dans le Core

Cible : replacer la règle dans le Vertical Module sauf preuve qu’elle est réellement générique.

Payload historique Frontend

Cible : conserver temporairement un shim dans l’Adapter si nécessaire, sans réintroduire la conversion dans les Read Services.

Cible : conserver une seule source d’autorité. Pour la navigation publique CURRENT, vérifier plugins/ccx-feeds-industrial/includes/application/navigation-architecture.php.

Ce qu’il ne faut pas faire

Éviter :

  • déplacer un dossier entier uniquement parce qu’il paraît legacy ;
  • créer une nouvelle couche sans responsabilité claire ;
  • remplacer un comportement non caractérisé ;
  • transformer un audit en commande d’écriture implicite ;
  • faire du Frontend ou d’une projection une source de vérité ;
  • supprimer un wrapper de compatibilité avant migration de ses consommateurs ;
  • déclarer une migration terminée uniquement parce que le code compile.

Critère de fin d’une migration

Une migration locale est terminée lorsque :

  • la responsabilité est placée dans la bonne couche ;
  • les consommateurs utilisent la voie prévue ;
  • les tests/audits applicables sont verts ;
  • les effets de bord sont connus ;
  • la documentation décrit le CURRENT réel ;
  • les compatibilités restantes sont explicitement identifiées ;
  • l’ancien chemin est supprimé ou reclassé en HISTORICAL/COMPATIBILITY selon le cas.

Critère de réussite global

Le but n’est pas d’atteindre une arborescence parfaite en une seule migration.

Le but est qu’au fil des évolutions :

  • la vérité métier reste unique ;
  • les frontières deviennent plus nettes ;
  • les lectures et écritures restent séparées ;
  • les migrations restent réversibles ;
  • les composants historiques cessent de gouverner le design cible ;
  • la documentation reste alignée avec l’implémentation réellement vérifiée.

Voir aussi