DDD dans le frontend : quand Domain-Driven Design a du sens | POLPROG Aller au contenu

DDD dans le frontend : quand Domain-Driven Design a du sens

Domain-Driven Design n'est ni une convention de dossiers ni une méthode réservée au backend. Son objectif est de rendre un domaine métier complexe plus maîtrisable grâce à un langage partagé, des modèles explicites et des frontières de contexte claires. Dans le frontend, DDD peut être très utile pour de grandes applications produit, mais peut aussi devenir une surarchitecture coûteuse. La question essentielle est de savoir où le client porte réellement de la complexité métier et où il reste surtout une couche de présentation.

Publié Rédigé par Temps de lecture 9 min de lecture

Domain-Driven Design n'est ni une convention de dossiers ni une méthode réservée au backend. Son objectif est de rendre un domaine métier complexe plus maîtrisable grâce à un langage partagé, des modèles explicites et des frontières de contexte claires. Dans le frontend, DDD peut être très utile pour de grandes applications produit, mais peut aussi devenir une surarchitecture coûteuse. La question essentielle est de savoir où le client porte réellement de la complexité métier et où il reste surtout une couche de présentation.

Sur cette page
  1. 1DDD ne commence pas par un dossier `domain`
  2. 2DDD stratégique et DDD tactique se situent à des niveaux différents
  3. 3Un Bounded Context n'est pas une couche technique
  4. 4Quand DDD dans le frontend a du sens
  5. 5Quand DDD devient de la surarchitecture
  6. 6Ubiquitous Language doit aussi apparaître dans le code UI
  7. 7Organiser un grand frontend par domaines, pas seulement par types de fichiers
  8. 8Séparer comportement de présentation et comportement métier
  9. 9Des couches pratiques dans un contexte frontend
  10. 10Le modèle API et le modèle de domaine frontend n'ont pas besoin d'être identiques
  11. 11Entities, Value Objects et Aggregates : les utiliser sélectivement
  12. 12L'état UI n'est pas l'état de domaine
  13. 13Les frontières doivent être imposées, pas seulement documentées
  14. 14Frontend et backend peuvent partager le domaine sans partager un modèle identique
  15. 15La testabilité est un argument fort pour isoler la logique de domaine
  16. 16Introduire DDD dans un frontend existant sans grand rewrite

DDD ne commence pas par un dossier `domain`

Eric Evans présente DDD comme un ensemble de patterns et de définitions pour travailler avec des modèles de domaine. Martin Fowler insiste sur la modélisation d'un domaine complexe et sur un langage commun entre développeurs et experts métier. [1][2][4]

Une structure `domain/application/infrastructure` ne suffit donc pas à faire du DDD. Un projet peut avoir des dossiers parfaitement nommés tout en restant composé de DTO et de logique procédurale. Le DDD stratégique peut aussi être appliqué sans structure de couches canonique.

DDD stratégique et DDD tactique se situent à des niveaux différents

Le DDD stratégique traite la décomposition d'une grande domaine en sous-domaines et Bounded Contexts ainsi que leurs relations. Microsoft décrit l'analyse de domaine comme l'identification des sous-domaines et contextes, tandis que Fowler place Bounded Context au centre du DDD stratégique. [3][7]

Le DDD tactique agit à l'intérieur d'un contexte donné et comprend notamment Entities, Value Objects, Aggregates et Domain Services. Microsoft sépare explicitement analyse stratégique et modélisation tactique. [8]

Dans le frontend, il est souvent plus pertinent de commencer par le stratégique puis de décider quels contextes nécessitent réellement un modèle tactique riche.

Un Bounded Context n'est pas une couche technique

Fowler décrit un Bounded Context comme une frontière dans laquelle un modèle reste cohérent et les termes gardent un sens non ambigu. Le même concept, comme `Customer` ou `Product`, peut légitimement avoir une autre signification ailleurs. [3]

Dans une architecture frontend, `frontend`, `backend`, `React app`, `route` ou `micro-frontend` ne sont donc pas automatiquement des Bounded Contexts. Les frontières viennent du modèle et du langage métier, pas de la technologie. Des praticiens du DDD frontend rappellent la même distinction. [15][16]

Quand DDD dans le frontend a du sens

SignalDirectionPourquoi
Nombreuses règles métier changeantesDDDUn modèle de domaine évite la dispersion des règles
Les mêmes concepts ont des sens différents dans le produitDDDLes Bounded Contexts maintiennent plusieurs modèles cohérents
Plusieurs équipes et experts métier collaborentDDDUbiquitous Language réduit l'ambiguïté
CRUD simple et formulairesModularité plus simpleLe coût du DDD tactique peut dépasser son bénéfice
Le frontend reflète surtout une APIModularité plus simplePeu de logique métier propre au client à modéliser
Petite application avec une seule domaine cohérenteModularité plus simpleDes frontières et couches supplémentaires peuvent apporter peu de valeur

Le signal le plus fort est la présence de règles métier complexes et changeantes côté client : configurateurs, processus multi-étapes, tarification, permissions, transitions d'état, workflows ou plusieurs modèles d'un même concept dans différentes zones du produit.

DDD est aussi utile lorsque plusieurs équipes développent un grand produit et que les mêmes mots ont des sens différents selon les zones. Les Bounded Contexts servent précisément à gérer plusieurs modèles cohérents et plusieurs équipes. [3]

DDD Crew recommande d'abord de comprendre le domaine, d'identifier les sous-domaines stratégiques, puis de définir les responsabilités des Bounded Contexts avant de coder le modèle. [10]

Quand DDD devient de la surarchitecture

Si le frontend récupère surtout des données, les affiche, gère des formulaires et envoie des commandes CRUD simples sans règles métier importantes côté client, l'ensemble des patterns tactiques DDD résout rarement un problème réel.

Microsoft indique explicitement qu'un contexte CRUD simple peut se contenter d'un modèle de données anémique et que des patterns DDD plus complexes ne sont pas toujours justifiés. Un modèle riche devient plus pertinent lorsqu'il existe de nombreuses règles métier changeantes. [9]

Le même principe s'applique au frontend : la sophistication de l'architecture doit suivre la complexité métier, pas l'ambition technique de l'équipe.

Ubiquitous Language doit aussi apparaître dans le code UI

Ubiquitous Language est un langage commun et rigoureux construit par les développeurs et les experts métier autour du modèle. Fowler souligne qu'il doit évoluer avec la compréhension de le domaine. [4]

Dans le frontend, les noms des cas d'utilisation, actions, types, modules, écrans et états devraient donc utiliser le vocabulaire métier lorsqu'ils décrivent un comportement de domaine.

Si le métier parle de `approveApplication` mais que le code n'utilise que `setFlag2` ou `handleData`, le code cesse d'être une représentation claire du langage de le domaine.

Organiser un grand frontend par domaines, pas seulement par types de fichiers

Fowler indique qu'une organisation racine `view/model/data` peut convenir à un petit système, mais qu'en grandissant il est souvent préférable d'avoir des modules de haut niveau orientés domaine, chacun possédant ses propres couches internes. [5]

La documentation actuelle de Nx suit une idée similaire : les dossiers peuvent devenir des frontières d'ownership par domaine et les bibliothèques internes être classées comme `feature`, `ui`, `data-access` et `util`. [12]

Une structure pratique peut donc être `libs/orders/...`, `libs/billing/...`, `libs/identity/...` plutôt qu'un arbre global `components/`, `services/`, `models/`.

Séparer comportement de présentation et comportement métier

Fowler présente la séparation entre présentation, logique de domaine et accès aux données comme une modularisation efficace. Il note aussi que l'UI est généralement plus difficile à tester, ce qui rend utile le déplacement de la logique de domaine hors de la présentation. [5][6]

Un composant frontend devrait principalement afficher, gérer les événements UI et déléguer les opérations. Des règles comme l'annulation d'une commande, le calcul d'une remise ou la validité d'une transition d'état devraient avoir un emplacement explicite hors JSX, template ou classe de composant.

Cela n'interdit pas la logique de présentation dans les composants. Validation de vue, visibilité, focus local et animation ne sont pas des règles métier.

Des couches pratiques dans un contexte frontend

CoucheResponsabilitéExemples
presentation / uiRendu et comportement d'interfacecomponents, routes, view state
applicationCoordination des cas d'utilisationcommands, use cases, orchestration
domainRègles, concepts et invariants métierentities, value objects, policies
infrastructure / data-accessIntégrations techniquesHTTP, storage, SDKs, mappers

DDD n'impose aucune structure de dossiers obligatoire. Séparer `presentation`, `application`, `domain` et `infrastructure` est une interprétation pratique de la séparation des responsabilités, pas une règle formelle d'Evans. [1][5]

La couche domain peut contenir règles, concepts et comportements indépendants du framework ; application coordonne les cas d'utilisation ; infrastructure adapte HTTP, stockage et SDK externes ; presentation contient composants, routage et état purement UI.

Le modèle API et le modèle de domaine frontend n'ont pas besoin d'être identiques

Un Bounded Context peut avoir son propre modèle d'un concept et différents contextes peuvent mapper différentes représentations. Fowler cite `Customer` et `Product` comme exemples classiques de termes dont le sens varie selon le contexte. [3]

Un DTO backend n'a donc pas besoin de traverser directement chaque composant. Un mapper ou adapter peut convertir le contrat de transport vers le modèle utilisé dans un contexte frontend.

Cette frontière est surtout utile lorsqu'une API sert plusieurs clients, est héritée, combine plusieurs domaines ou évolue séparément. Pour un endpoint CRUD simple, une couche de mapping supplémentaire peut être inutile.

Entities, Value Objects et Aggregates : les utiliser sélectivement

DDD distingue notamment Entities, Value Objects, Services et Aggregates. Fowler les présente comme partie du vocabulaire d'Evans, tandis que Microsoft décrit les agrégats comme un pattern tactique de cohérence du modèle. [2][8]

Le frontend ne devrait pas copier le modèle backend à l'identique seulement pour avoir les mêmes classes. Un Value Object est pertinent pour `Money`, `DateRange` ou `Email` s'il protège de vrais invariants. Un Aggregate est utile si le client doit réellement garantir des règles de cohérence.

Si un type ne sert qu'à afficher une ligne de tableau, un simple type TypeScript peut être préférable à Entity, Factory, Repository et Service.

L'état UI n'est pas l'état de domaine

React traite l'organisation de l'état comme un problème de conception et recommande d'éviter l'état redondant ou dupliqué. C'est une bonne base technique, mais reducers, stores ou signals ne créent pas à eux seuls un modèle de domaine. [14]

Un état comme `isModalOpen`, l'onglet actif ou la position de scroll appartient à la présentation. Le cycle de vie d'une commande, les transitions autorisées ou les règles d'un configurateur peuvent appartenir au modèle de domaine.

Séparer ces catégories évite les stores globaux qui mélangent données serveur, comportement métier et détails UI.

Les frontières doivent être imposées, pas seulement documentées

Nx permet de définir des tags de projet et des contraintes de dépendances déclaratives, par exemple pour interdire des imports entre scopes ou types de bibliothèques. La règle `@nx/enforce-module-boundaries` peut vérifier les imports pendant le lint. [11]

Nx prend aussi en charge plusieurs dimensions de tags, ce qui permet de modéliser séparément `scope`, type de bibliothèque, stabilité ou séparation client/server. [13]

Les décisions DDD peuvent ainsi devenir des règles CI : `billing` n'importe pas les internes de `identity`, `ui` ne dépend pas de `data-access` et `domain` reste indépendant du framework.

Frontend et backend peuvent partager le domaine sans partager un modèle identique

Un Bounded Context est une frontière de modèle et de langage, il ne devrait donc pas être tracé automatiquement sur la frontière réseau entre navigateur et serveur. Des guides pratiques du DDD frontend soulignent que les contextes peuvent traverser les couches techniques et être réalisés conjointement côté frontend et backend. [15][16]

La représentation cliente peut néanmoins différer de la représentation serveur, car interaction, état local et présentation ont d'autres besoins. L'essentiel est de préserver la sémantique et de mapper explicitement plutôt que de copier les classes.

Un micro-frontend ne doit pas non plus être créé simplement parce qu'un Bounded Context existe. Frontière métier et frontière de déploiement sont deux décisions différentes.

La testabilité est un argument fort pour isoler la logique de domaine

Fowler cite la testabilité comme bénéfice de la séparation entre présentation et domaine. Une logique hors UI peut être testée sans rendu de composants ni dépendance aux détails de l'interface. [5][6]

Dans le frontend, cela permet des tests rapides des règles, Value Objects, cas d'utilisation et transitions d'état en TypeScript ou JavaScript ordinaire. Les tests de composants restent utiles, mais ne doivent pas être le seul endroit où vérifier les règles métier.

Un signal d'alerte apparaît lorsque chaque changement de règle exige de monter un composant complet et de mocker routeur, store, HTTP et APIs navigateur.

Introduire DDD dans un frontend existant sans grand rewrite

DDD Crew recommande une démarche itérative : comprendre le domaine, identifier les sous-domaines importants, définir les responsabilités des Bounded Contexts, puis coder le modèle. [10]

Dans un frontend existant, il est plus sûr de choisir une zone métier douloureuse, nommer son langage, fixer une frontière, séparer présentation et règles, définir l'API publique du module puis migrer progressivement d'autres fonctionnalités.

Toute l'application n'a pas besoin d'être migrée. DDD peut être utilisé là où la complexité métier rembourse le coût de modélisation, tandis que les zones simples restent des modules fonctionnels légers.

  • Commencer par un problème métier, pas par les dossiers.
  • Identifier termes, règles et concepts ambigus.
  • Définir un Bounded Context et son contrat public.
  • Séparer règles métier, composants et DTO de transport.
  • Ajouter uniquement les patterns tactiques qui résolvent une complexité réelle.
  • Transformer les frontières en règles de lint ou CI.
  • Mesurer dépendances, cycles, régressions et coût des changements transversaux.
  • Ne pas migrer les zones CRUD simples uniquement pour la symétrie architecturale.

DDD dans le frontend a du sens lorsque le client fait partie d'un produit complexe et ne se contente pas d'afficher des données. Le meilleur retour vient souvent du DDD stratégique : langage commun, contextes bien délimités et frontières de modules réellement imposées. Les patterns tactiques doivent être ajoutés seulement là où des règles, invariants et comportements le justifient. Pour une application principalement CRUD, formulaires et lecture d'API, une bonne modularité et une séparation claire entre présentation et données sont souvent préférables à un DDD complet.

DDD Domain-Driven Design Frontend Architecture Software Architecture Bounded Context Ubiquitous Language TypeScript Nx React Angular

Questions fréquentes

DDD a-t-il du sens dans le frontend ?

Oui, lorsque le frontend participe à un domaine complexe et bénéficie de frontières explicites, d'un langage partagé ou de règles métier côté client. DDD n'est pas réservé au backend. [1][2][15]

Tous les frontends devraient-ils utiliser DDD ?

Non. Pour des applications CRUD simples, le DDD tactique complet peut être inutile. Microsoft indique explicitement qu'un contexte CRUD simple ne justifie pas toujours un modèle riche. [9]

Le frontend est-il un Bounded Context séparé ?

Pas automatiquement. Un Bounded Context délimite un modèle et un langage cohérents, pas une technologie. [3][16]

Chaque Bounded Context doit-il devenir un micro-frontend ?

Non. Une frontière métier n'impose pas un déploiement séparé. L'architecture micro-frontend est une décision supplémentaire. [3][15]

Faut-il un dossier domain ?

Non. DDD ne prescrit pas de structure de répertoires obligatoire. Un dossier peut aider, mais ne crée pas un modèle de domaine à lui seul. [1][5]

Où placer la logique métier dans le frontend ?

Hors de la présentation pure, dans un modèle explicite ou une couche de cas d'utilisation du contexte. Fowler recommande la séparation présentation-domaine. [5][6]

Un DTO API peut-il être le modèle de domaine ?

Dans un cas trivial, oui, mais ce n'est pas obligatoire. Différents contextes peuvent modéliser le même concept différemment, donc le mapping est souvent une bonne frontière. [3]

Repository a-t-il du sens dans le frontend ?

Seulement s'il résout un vrai problème d'abstraction autour de l'accès au modèle. Pour un fetch simple, une couche Repository supplémentaire peut être inutile. [1][9]

Redux, NgRx, Zustand ou Signals font-ils partie du DDD ?

Non. Ce sont des mécanismes de gestion d'état. Ils peuvent contenir un état de domaine, mais ne définissent ni modèle, ni langage, ni Bounded Context. [14]

Le modèle de domaine frontend doit-il être identique à celui du backend ?

Non. Il doit préserver la bonne sémantique métier, mais sa représentation peut être adaptée aux besoins du client. [3]

Comment imposer les frontières de domaine dans un monorepo ?

Nx peut utiliser des tags et @nx/enforce-module-boundaries pour bloquer automatiquement les dépendances interdites. [11][13]

Par où commencer dans une application existante ?

Commencez par une zone métier complexe : comprendre son langage, ses règles et sa frontière. DDD Crew recommande un chemin itératif de le domaine vers les contextes puis le code. [10]

Sources et références

  1. Eric Evans, DDD Reference12345
  2. Martin Fowler, Domain Driven Design123
  3. Martin Fowler, Bounded Context12345678
  4. Martin Fowler, Ubiquitous Language12
  5. Martin Fowler, Presentation Domain Data Layering123456
  6. Martin Fowler, Presentation Domain Separation123
  7. Microsoft Azure Architecture Center, Use Domain Analysis to Model Microservices
  8. Microsoft Azure Architecture Center, Use Tactical DDD to Design Microservices12
  9. Microsoft .NET, Design a microservice domain model123
  10. DDD Crew, DDD Starter Modelling Process123
  11. Nx, Enforce Module Boundaries12
  12. Nx, Monorepo Folder Structure
  13. Nx, Tag in Multiple Dimensions12
  14. React, Managing State12
  15. ANGULARarchitects, DDD in Angular & Frontend Architecture1234
  16. Tomasz Ducin, Your Frontend itself is NOT a Bounded Context123

Cela vous a-t-il été utile ?

Recevez les nouveaux articles par e-mail

Un court e-mail par nouvel article d'apprentissage. Pas de spam, désinscription en un clic.

Nous utilisons uniquement votre e-mail pour envoyer de nouveaux articles. Aucun partage avec des tiers.

Retour à l'apprentissage