Domaines et cycles de vie - 03 - Le cycle de vie d'une entité

Comment modéliser le cycle de vie d'une entité avec des états explicites. Le lifecycle est l'ossature de toute architecture DDD solide.

03 - Le cycle de vie d'une entité

Ce que tu vas apprendre

  • Ce qu'est un cycle de vie (lifecycle) et pourquoi c'est l'ossature d'un domaine
  • Les regles d'un cycle de vie bien conçu
  • Un exemple complet avec le domaine Place
  • Comment representer un cycle de vie visuellement

Prerequisites


Qu'est-ce qu'un cycle de vie ?

Le cycle de vie (lifecycle) d'une entité decrit les états successifs qu'elle traverse de sa création a sa forme finale. C'est la colonne vertebrale d'un domaine.

Pense a une commande en ligne : elle passe de "créée" a "payee" a "expediee" a "livree". Ce n'est pas du hasard : c'est un cycle de vie. Chaque état a un sens métier precis, et le passage d'un état a l'autre suit des regles.

Sans cycle de vie explicite, l'état de tes entités est implicite : il faut lire le code pour deviner ou en est une entité. Avec un cycle de vie, un seul champ (status) te dit tout.

Les regles d'un cycle de vie

1. Les états sont explicites et nommes

Chaque état a un nom clair, en majuscules par convention : DRAFT, ENRICHED, PUBLISHED. Pas de "en cours", pas de booleen isReady, pas de champ calcule.

2. Les états sont finis

Il y a un nombre défini d'états. Tu peux tous les lister. Si tu ne peux pas lister tous les états possibles, tu n'as pas de cycle de vie -- tu as du chaos.

3. Les transitions sont unidirectionnelles

On avance dans le cycle de vie, on ne recule pas au hasard. DRAFT -> ENRICHED est autorise. ENRICHED -> DRAFT ne l'est pas (sauf si tu le decides explicitement, avec une transition nommee comme RESET).

4. Pas d'états caches

Si une entité peut etre dans un état, cet état doit apparaître dans la définition du cycle de vie. Pas d'état "entre deux", pas d'état "temporaire", pas d'état "on verra plus tard".

Exemple concret : le cycle de vie d'une Place

Une Place (lieu touristique) traverse ces états :

DRAFT                    La place vient d'etre creee, donnees minimales
     |
     |  enrich()
     v
ENRICHED                 Categories, traductions, horaires remplis
     |
     |  request_images()
     v
READY_FOR_IMAGES         Prete pour le traitement d'images
     |
     |  process_images()
     v
IMAGES_PROCESSING        Les images sont en cours de generation
     |
     |  images_done()
     v
IMAGES_PROCESSED         Les images sont generees, en attente de validation
     |
     |  validate_images()
     v
READY_FOR_PUBLICATION    Images validees, prete a etre publiee
     |
     |  publish()
     v
PUBLISHED                En ligne, visible par les utilisateurs

Chaque état est un fait métier. ENRICHED signifie quelque chose de precis : "cette Place a ses categories, ses traductions et ses horaires d'ouverture". Ce n'est pas un flag technique, c'est une réalité du domaine.

Diagramme ASCII

+-------+    +----------+    +-----------------+    +-------------------+
| DRAFT |--->| ENRICHED |--->| READY_FOR_IMAGES|--->| IMAGES_PROCESSING |
+-------+    +----------+    +-----------------+    +-------------------+
                                                            |
                                                            v
+-----------+    +-----------------------+    +------------------+
| PUBLISHED |<---| READY_FOR_PUBLICATION |<---| IMAGES_PROCESSED |
+-----------+    +-----------------------+    +------------------+

Pourquoi c'est l'ossature du domaine

Le cycle de vie est ce qui donne du sens a tout le reste :

  • Les features se mappent a des transitions du cycle de vie (on verra ca dans l'article 10)
  • Les invariants se definissent par rapport a un état (article 07)
  • Les guards controlent les transitions (article 05)
  • La source de vérité stocke l'état courant (article 06)

Sans cycle de vie, tu as des features qui font "des trucs" sans structure. Avec un cycle de vie, chaque feature a un rôle clair : elle prend une entité dans un état et la fait passer a l'état suivant.

Le status comme champ unique

En pratique, le cycle de vie se materialise par un seul champ dans ta base de donnees :

sqlCREATE TABLE places (
  id          UUID PRIMARY KEY,
  name        TEXT NOT NULL,
  status      TEXT NOT NULL DEFAULT 'DRAFT',
  -- ...
);

Ce champ status est la vérité. Pour savoir ou en est une Place, tu fais :

sqlSELECT id, name, status FROM places WHERE id = 'place_42';
-- Resultat : place_42 | Cafe de Flore | ENRICHED

Pas besoin de recalculer, pas besoin de croiser 4 sources. Un champ, une vérité.

Ce qui arrive sans cycle de vie

Sans cycle de vie explicite, l'état est derive : on le recalcule a la volee à partir de multiples sources. "Est-ce que cette Place a des images ? Est-ce que les categories sont remplies ? Est-ce que le flag is_closed est a true ?". C'est fragile, non testable, et ca change de comportement selon d'ou on regarde.


Résumé

  • Le cycle de vie est la suite ordonnee d'états qu'une entité traverse
  • Les états sont explicites, finis, nommes, et les transitions sont unidirectionnelles
  • Pas d'état cache : si ca existe, ca doit etre dans la définition
  • Un seul champ status dans la base suffit a materialiser tout le cycle de vie
  • C'est l'ossature du domaine : features, invariants, guards -- tout s'accroche au lifecycle

Article précédent : 02 - Entités, Value Objects et identité Article suivant : 04 - La machine a états (State Machine / FSM)

Sources

Réservez un audit gratuit de 30 minutes. Je vous montre concrètement ce qu'on peut automatiser.