Formation  ·  Conception logicielle  ·  Domain-Driven Design

Concevoir
avant de coder

La plupart des projets ne meurent pas d'un mauvais code, mais d'une mauvaise compréhension du problème. Cette formation est une carte pour explorer le métier, le modéliser, le découper — et n'ouvrir l'éditeur qu'une fois qu'on sait quoi construire.

Du besoin → au modèle → aux specs → au code. Dans cet ordre.

Introduction

Pourquoi concevoir d'abord

Coder, c'est facile. Coder la bonne chose, c'est tout le problème. On peut écrire un module impeccable, testé, performant… qui résout un besoin que personne n'avait. La conception, c'est l'art de décider quoi construire et comment l'organiser — avant de se battre avec la syntaxe.

Le réflexe naturel du développeur est de sauter au clavier : choisir un framework, dessiner des tables, écrire des classes. Mais à ce stade, on ignore encore la moitié des règles métier. On construit alors très bien la mauvaise chose, et on découvre les vraies contraintes une fois le code coulé dans le béton.

Problème le besoin réel Domaine on comprend Modèle on découpe Specs CdCF/CdCT <code/> là se joue 80 % de la valeur l'exécution
La conception se passe en amont — le code n'est que la dernière traduction.
⚖️
Pas de Big Design Up Front non plus

« Concevoir d'abord » ne veut pas dire tout figer dans un document de 200 pages avant la première ligne. La compréhension du domaine s'affine en avançant. L'idée est de penser assez pour ne pas se tromper de direction — puis d'itérer, en gardant le modèle vivant.

Cette formation suit ce fil : comprendre le métier, en extraire un langage commun, le découper en territoires, le modéliser en briques solides, puis le protéger par une architecture saine. Le Domain-Driven Design (DDD) sera notre boîte à outils principale.

Introduction

Les fondations

Quatre réflexes valent plus que n'importe quelle technique. Ils tiennent en une phrase chacun, mais ils décident de tout.

1 · Comprendre le problème avant la solution

Il y a deux espaces : l'espace du problème (problem space) — ce que le métier veut vraiment — et l'espace de la solution (solution space) — comment on y répond. Le débutant fonce dans le second. L'erreur la plus chère, c'est de répondre vite à la mauvaise question. Posez « pourquoi ? » trois fois avant de dessiner quoi que ce soit.

2 · Séparer le métier de la technique

Le cœur d'un logiciel, c'est ses règles métier — pas son framework, sa base de données ou son protocole HTTP. Ceux-là sont des détails interchangeables. Toute la conception consiste à garder le métier au centre et la technique en périphérie, jamais l'inverse.

3 · Modéliser, pas tout documenter

Un modèle est une simplification utile de la réalité, taillée pour un objectif précis. Une carte de métro ne montre pas la géographie exacte : elle montre ce qui sert à voyager. Un bon modèle métier ignore délibérément ce qui ne sert pas à résoudre ce problème.

4 · La structure du logiciel suivra celle de l'équipe

🪞
Loi de Conway

« Toute organisation qui conçoit un système produira une copie de sa propre structure de communication. » Autrement dit : vos découpages techniques refléteront vos découpages humains. Concevoir les frontières du système, c'est aussi concevoir qui parle à qui.

Ces quatre principes pointent tous vers la même chose : avant le code, il faut un modèle partagé du métier et des frontières claires. C'est précisément ce que le DDD outille.

Introduction

Du besoin aux spécifications

Entre « j'ai compris le métier » et « je code », il y a une étape qu'on saute trop souvent : écrire ce qu'on va construire. Deux documents structurent ce passage.

Le CdCF — Cahier des Charges Fonctionnel

Il décrit le quoi et le pourquoi, en langage métier, sans présupposer de solution technique. Il exprime des besoins et des exigences fonctionnelles : ce que le système doit permettre, pour qui, sous quelles règles et contraintes. Un bon CdCF pourrait être lu et validé par un expert métier qui ne code pas.

On y met les objectifs, les acteurs, les cas d'usage, les règles de gestion, les contraintes (légales, délais, volumétrie), les critères d'acceptation.

On n'y met pas de choix de base de données, de framework, d'API ou d'algorithme. Le « comment » n'a rien à faire ici.

Le CdCT — Cahier des Charges Technique

Il répond au CdCF par le comment : architecture, choix technologiques, modèle de données, intégrations, contraintes de performance et de sécurité, découpage en composants. Il découle du fonctionnel — jamais l'inverse.

🧭
Le lien avec le DDD

Le travail stratégique du DDD (langage omniprésent, sous-domaines, bounded contexts) nourrit directement le CdCF : il fixe le vocabulaire et les frontières. Le travail tactique (agrégats, services, événements) et le choix d'architecture alimentent le CdCT. Concevoir, c'est en grande partie remplir ces deux cahiers avec lucidité.

📏
Juste ce qu'il faut

Spécifier n'est pas tout verrouiller. Sur un produit incertain, un CdCF léger + des itérations battent un pavé exhaustif qui sera faux dans trois semaines. Calibrez la profondeur sur le risque et la durée de vie du projet.

Introduction

Le DDD en une idée

Le Domain-Driven Design (Eric Evans, 2003) tient dans une phrase : placez le métier au centre du logiciel, et faites parler le code la même langue que les experts métier.

Tout le reste — les agrégats, les contextes, les événements — n'est que de l'outillage au service de cette idée. Le DDD se divise en deux moitiés complémentaires :

Stratégique — la vue d'ensemble : le langage, les sous-domaines, les frontières (bounded contexts) et leurs relations (context map). C'est de la conception pure, sur tableau blanc, avant tout code.

Tactique — les briques de modélisation dans le code : value objects, entités, agrégats, événements, repositories. C'est la traduction fidèle du modèle.

Notion clé : les sous-domaines

Tout métier se décompose en sous-domaines. Ils n'ont pas la même importance :

  • Cœur de métier (core domain) — ce qui vous différencie, votre avantage concurrentiel. C'est là qu'on investit le plus d'effort de conception.
  • Sous-domaines de support — nécessaires mais non différenciants (ex. un back-office interne).
  • Sous-domaines génériques — résolus par tout le monde pareil (authentification, envoi d'e-mails) : on achète ou on prend une lib, on ne réinvente rien.
🎚️
Le DDD n'est pas gratuit

Tout ce rituel a un coût. Sur un CRUD simple ou une appli jetable, c'est de la sur-ingénierie. Le DDD brille quand le métier est complexe et durable, et que plusieurs personnes doivent partager sa compréhension. Réservez la grosse artillerie au cœur de métier.

Stratégique · 04

Le langage omniprésent

L'idée — Un seul vocabulaire, partagé par les experts métier ET le code. Les mêmes mots dans les réunions, le modèle, les classes, les tests.

Le problème

Le métier parle de « bénéficiaire », le code dit User2, la base dit tbl_clients, et le chef de projet dit « le client final ». Chaque traduction est une occasion de se tromper. Les bugs naissent souvent dans ces glissements de sens entre humains.

La solution

On construit un langage omniprésent (ubiquitous language) : un glossaire vivant, négocié avec les experts, et appliqué littéralement dans le code. Si le métier dit « résilier un abonnement », alors il existe une méthode subscription.resilier() — pas updateStatus(3).

🗣️
Test concret

Lisez une méthode de votre domaine à voix haute devant un expert métier. S'il comprend ce qu'elle fait sans que vous traduisiez, le langage est bon. S'il faut un interprète, le modèle ment.

Bénéfice — moins de malentendus, un code qui se lit comme le métier, et un onboarding où la doc est le code.

Piège — un langage figé. Le vocabulaire évolue avec la compréhension : quand un mot change de sens, on renomme partout, sans pitié.

Stratégique · 05

Bounded Contexts

L'idée — Un modèle (et son langage) n'est valable que dans une frontière précise. Le même mot peut signifier des choses différentes ailleurs — et c'est sain.

Le problème

On rêve d'un seul grand modèle unifié pour tout le système : un objet Client qui sert aux ventes, au support, à la facturation et au marketing. Résultat : une classe obèse de 80 champs, où chaque équipe ajoute les siens, et que plus personne ne maîtrise. C'est le chemin vers le Big Ball of Mud.

La solution

On accepte que « Client » ne soit pas la même chose selon le contexte, et on trace des frontières — les contextes délimités (bounded contexts). Dans chacun, le modèle et le langage sont cohérents et autonomes.

VENTES SUPPORT FACTURATION « Client » « Client » « Client » = un prospect à convertir = un dossier avec un historique = un débiteur avec un IBAN
Trois contextes, trois « Client ». Vouloir les fusionner crée le monstre ; les séparer libère.
🧩
Aligner avec les sous-domaines

Idéalement, un bounded context correspond à un sous-domaine et à une équipe (souvenez-vous de Conway). C'est l'unité d'autonomie : on peut faire évoluer l'intérieur d'un contexte sans casser les autres, tant qu'on respecte les contrats à la frontière.

Stratégique · 06

La Context Map

L'idée — Dessiner la carte des contextes et, surtout, la nature de leurs relations. C'est le plan stratégique du système entier.

Une fois les contextes posés, ils doivent collaborer. La context map rend visible qui dépend de qui, et comment. C'est l'artefact de conception le plus précieux pour une vue d'ensemble — et il tient sur un tableau blanc.

N Ventes ★ cœur de métier commandes, panier Catalogue produits, prix Facturation factures, TVA Expédition colis, suivi Transporteur API externe (legacy) U → D · C/S U → D · C/S U → D ACL U = amont (upstream) · D = aval (downstream) · C/S = Client/Fournisseur · ACL = couche anticorruption
Une context map : les territoires, le sens des dépendances, et le type de chaque relation.

Les principaux types de relation

Le vocabulaire des relations dit comment deux contextes s'accordent — et qui subit l'autre :

PartnershipDeux contextes évoluent ensemble, réussite ou échec partagés. Forte coordination.
Shared KernelUn petit modèle commun partagé entre deux contextes. Puissant mais dangereux : tout changement impacte les deux.
Customer / SupplierL'aval (client) dépend de l'amont (fournisseur), mais l'amont tient compte de ses besoins.
ConformistL'aval se plie au modèle de l'amont sans négociation (souvent un système qu'on ne contrôle pas).
Anticorruption LayerUne couche de traduction qui protège votre modèle d'un modèle externe « sale ». Indispensable face au legacy.
Open Host / Published LanguageL'amont publie une API et un langage stables pour tous ses consommateurs.
Separate WaysPas d'intégration du tout : parfois la meilleure décision est de ne pas connecter.
🛡️
L'ACL : votre meilleur allié

Quand vous intégrez un système externe ou legacy, ne laissez jamais son modèle fuir chez vous. Une couche anticorruption traduit son langage vers le vôtre à la frontière — votre cœur de métier reste propre, quoi qu'il arrive dehors.

Stratégique · 07

EventStorming

L'idée — Un atelier collaboratif où l'on explore le métier avec des post-it de couleur sur un mur — devs et experts ensemble, sans une ligne de code.

Inventé par Alberto Brandolini, l'EventStorming est l'une des meilleures façons de démarrer une conception. On déroule le métier comme une frise d'événements dans le temps, et la discussion fait émerger les règles, les zones floues et les frontières naturelles (les futurs bounded contexts).

Acteur déclenche Commande PasserCommande Agrégat Commande Événement CommandePassée Politique « alors… » une politique peut déclencher une nouvelle commande Le code couleur (les post-it) : Événement (fait passé) Commande (intention) Agrégat (qui décide) Politique (réaction) Acteur (qui agit) Système externe
Acteur → Commande → Agrégat → Événement → Politique. Le métier raconté au passé, en post-it.
🌩️
Pourquoi ça marche

Parce que les experts métier participent vraiment : pas de jargon technique, juste des faits et des règles. Les désaccords sur un post-it révèlent les vraies questions, et les « grappes » d'événements dessinent d'elles-mêmes les frontières des contextes. On repart avec un modèle partagé avant d'avoir codé quoi que ce soit.

Tactique · 08

Value Objects

L'idée — Un objet défini par sa valeur, sans identité propre, et immuable. Deux value objects égaux sont interchangeables.

Le problème : l'obsession des primitifs

On modélise tout avec des types bruts : un prix est un number, un e-mail une string, une devise une autre string. Du coup, la validation et les règles se dispersent partout, et rien n'empêche d'additionner des euros avec des dollars.

La solution

On crée des value objects qui portent leur sens et leurs règles : Money, Email, DateRange. Validés à la création, immuables ensuite, comparés par valeur.

Des string/number partout : aucune garantie, des règles dispersées, des bugs silencieux.
Chaque concept porte son sens et ses règles. Les états invalides deviennent impossibles à exprimer.
💡
Le réflexe le plus rentable

« Make illegal states unrepresentable. » Dès qu'un primitif a des règles (un format, des bornes, une unité), enveloppez-le dans un value object. C'est souvent le premier pas concret du DDD tactique, et le plus payant.

Tactique · 09

Entities

L'idée — Un objet doté d'une identité stable dans le temps. Son état change, mais c'est toujours « le même », identifié par son id.

Entity ou Value Object ?

La question à se poser : « deux exemplaires avec les mêmes attributs sont-ils la même chose ? » Deux billets de 10 € sont interchangeables → value object. Deux clients homonymes restent deux personnes distinctes → entity. L'identité prime sur les attributs.

Entity quand l'objet a un cycle de vie et une continuité : Commande, Client, Compte, Article de stock.

Value object quand seule la valeur compte : Argent, Adresse, Couleur, Plage de dates.

Tactique · 10

Aggregates

L'idée — Un groupe d'objets traité comme une seule unité de cohérence. Une racine (aggregate root) en est la seule porte d'entrée et garde ses invariants.

C'est le concept tactique le plus subtil — et le plus structurant. Un agrégat définit une frontière transactionnelle : tout ce qui doit rester cohérent ensemble vit dedans, et on n'y touche que par la racine.

FRONTIÈRE DE L'AGRÉGAT « Commande » Commande ★ racine Ligne entity interne Montant value object Client autre agrégat par ID seulement on ne touche aux Lignes et au Montant qu'À TRAVERS la Commande
À l'intérieur : cohérence forte via la racine. Vers l'extérieur : on référence les autres agrégats par leur ID.

Les trois règles d'or des agrégats

  • Petits — un agrégat le plus réduit possible. S'il grossit, c'est souvent plusieurs agrégats déguisés.
  • Référencés par ID — un agrégat ne contient jamais un autre agrégat ; il garde seulement son identifiant.
  • Une transaction = un agrégat — une opération ne modifie qu'un seul agrégat à la fois. La cohérence entre agrégats devient éventuelle, via des événements.
🎯
La vraie question

« Qu'est-ce qui doit rester cohérent dans la même transaction ? » La réponse dessine la frontière de l'agrégat. Tout le reste peut être cohérent un peu plus tard — et c'est presque toujours suffisant.

Tactique · 11

Domain Events

L'idée — Un fait métier qui s'est produit, nommé au passé et immuable. Les autres parties du système peuvent y réagir.

Le problème

Quand une commande est passée, il faut décrémenter le stock, envoyer un e-mail, créer une facture… Tout coder dans la méthode passer() la couple à la terre entière, et fait franchir plusieurs agrégats dans une même transaction.

La solution

L'agrégat publie un domain event : CommandePassée. Les autres contextes s'y abonnent et réagissent de leur côté. C'est ce qui permet aux agrégats de rester petits et découplés (cohérence éventuelle).

Commande vs Événement

Une commande exprime une volonté qui peut être refusée (« PasserCommande »). Un événement constate quelque chose qui s'est produit et ne peut plus être annulé (« CommandePassée »). Cette distinction, repérée dès l'EventStorming, structure tout le modèle.

Tactique · 12

Repositories

L'idée — Une interface qui se comporte comme une collection en mémoire d'agrégats. Le domaine y range et y retrouve ses objets — sans rien savoir de la base.

Le problème

Si le modèle métier appelle directement du SQL ou un ORM, il devient prisonnier de la technique. Impossible de le tester sans base, impossible d'en changer sans tout casser.

La solution

On définit l'interface du repository dans le domaine, et son implémentation concrète dans l'infrastructure. Le domaine dépend d'une abstraction ; la technique s'y branche. (C'est l'inversion de dépendance — on y revient avec l'architecture.)

🧪
Le test qui ne ment pas

Si vous pouvez écrire les tests de vos règles métier sans démarrer de base de données, votre domaine est bien isolé. Sinon, la technique a fui dans le métier — et la conception a une fuite à colmater.

Tactique · 13

Services & Factories

L'idée — Deux compléments aux objets du domaine : un endroit pour les opérations sans propriétaire naturel, et un endroit pour la création complexe.

Domain Service

Parfois, une opération métier n'appartient à aucune entité ni value object en particulier — elle concerne plusieurs objets. On la place alors dans un domain service : sans état, nommé d'après le métier, vivant dans le domaine. Exemple : un TransfertDeFonds qui débite un compte et en crédite un autre.

🧲
N'en abusez pas

Le domain service est un aimant à logique : on est tenté d'y mettre tout, et de vider les entités (retour du modèle anémique). Règle : le comportement va d'abord dans l'objet à qui il appartient. Le service ne récupère que ce qui n'a vraiment pas de propriétaire.

Factory

Quand créer un agrégat valide demande plusieurs étapes ou des règles non triviales, on encapsule cette création dans une factory (souvent une méthode statique create(...), comme vu sur Order). Le reste du code obtient un objet toujours valide, sans connaître les détails de fabrication.

Et l'Application Service ?

À ne pas confondre : l'application service orchestre un cas d'usage (charger l'agrégat via le repository, appeler une méthode métier, sauvegarder, publier l'événement) — mais il ne contient aucune règle métier. Les règles restent dans le domaine ; l'application ne fait que coordonner.

Tactique · 14

Modèle riche vs anémique

L'idée — La leçon centrale du DDD tactique : les données et les règles qui les protègent vivent ensemble. Séparer les deux, c'est l'anti-modèle.

Le modèle anémique ressemble à du DDD (il y a des classes « métier »), mais ce ne sont que des sacs de données : que des getters/setters, et toute la logique exilée dans des services. Les objets ne se protègent pas : n'importe qui peut les mettre dans un état invalide.

Données et règles séparées : les invariants ne sont garantis nulle part. C'est de la programmation procédurale déguisée.
Le comportement protège l'état. L'objet est toujours valide, et le métier se lit directement dans le code.
🏛️
La règle qui résume tout

« Tell, don't ask. » Ne demandez pas son état à un objet pour décider à sa place — dites-lui quoi faire, et laissez-le garder ses propres règles. C'est la différence entre des objets vivants et de simples structures de données.

Charpente · 15

Protéger le domaine

L'idée — Une seule règle d'architecture à retenir : les dépendances pointent vers l'intérieur. Le domaine ne dépend de rien ; tout dépend du domaine.

Tout le travail de conception serait gâché si le métier finissait noyé dans le framework et la base. Les architectures dites hexagonale (ports & adapters), en oignon ou propre (clean) disent toutes la même chose, en couches concentriques.

Domaine entités · VO · règles Application cas d'usage, orchestration Infrastructure & adapters DB · HTTP · UI · messaging · libs les dépendances pointent vers le cœur
Le domaine au centre, pur et ignorant de la technique. Les détails (DB, HTTP, UI) restent en périphérie.

Concrètement : le domaine ne contient aucun import de framework web, d'ORM ou de client HTTP. Il expose des ports (des interfaces, comme le OrderRepository), que l'infrastructure vient remplir avec des adapters. On peut alors remplacer Postgres par Mongo, REST par gRPC, ou tester le cœur en isolation — sans jamais toucher au métier.

🔌
Ports & Adapters en deux mots

Un port = une interface définie par le domaine (ce dont il a besoin). Un adapter = une implémentation côté infrastructure (comment c'est réalisé). Le métier dicte le contrat ; la technique s'y conforme. L'inversion de dépendance rend cette pureté possible.

Charpente · 16

Le processus, de bout en bout

Voici comment tout s'enchaîne, du flou initial à la première ligne de code. Pas une cascade rigide : une spirale qu'on parcourt en affinant.

Explorer le domaine

Discussions avec les experts, EventStorming, exemples concrets. On cherche à comprendre, pas encore à décider.

Dégager le langage & les sous-domaines

On fixe le vocabulaire commun et on identifie le cœur de métier (là où l'effort comptera vraiment).

Découper en bounded contexts

On trace les frontières et on dessine la context map : qui dépend de qui, et comment.

Rédiger le CdCF

Le fonctionnel, en langage métier : objectifs, acteurs, cas d'usage, règles, critères d'acceptation. Toujours pas de technique.

Modéliser le tactique

Sur tableau blanc d'abord : agrégats et leurs frontières, value objects, événements. On valide les invariants avant de coder.

Choisir l'architecture & rédiger le CdCT

Le comment : couches, ports/adapters, choix techniques, modèle de données. Il découle du fonctionnel et du modèle.

Coder — en gardant le modèle vivant

Enfin ! Le code reflète le langage et le modèle. Et quand la compréhension progresse, on boucle : on raffine le modèle, et le code suit.

🌀
Itérer, toujours

On ne fait pas toutes ces étapes à fond une seule fois. On prend une tranche de métier, on la déroule jusqu'au code, on apprend, et on recommence. Le modèle est vivant : il s'enrichit à chaque boucle. « Concevoir avant de coder » est un réflexe permanent, pas une phase qu'on coche.

Pour finir

Pièges & antipatterns

Les erreurs qui reviennent le plus — à repérer avant qu'elles ne s'installent.

Big Ball of MudAucune frontière : tout dépend de tout. Le résultat par défaut quand on ne conçoit pas les contextes.
Modèle anémiqueDes classes sans comportement + des services qui font tout. Le faux DDD le plus courant.
Obsession des primitifsTout en string/number. Les règles se dispersent et les bugs se cachent. → Value Objects.
DDD partoutSortir l'artillerie sur un CRUD ou un sous-domaine générique. Sur-ingénierie pure.
Ignorer le cœur de métierSoigner le générique (auth, e-mails) et bâcler ce qui vous différencie vraiment.
Modèle couplé à la baseConcevoir les tables d'abord et en déduire le métier. Le schéma SQL n'est pas le modèle du domaine.
Paralysie d'analyseTout vouloir spécifier avant de commencer. La compréhension vient aussi en faisant : itérez.
Agrégats géantsTout charger en une transaction « pour être sûr ». Tue la performance et la concurrence. → petits agrégats + événements.
Pour finir

La checklist de conception

À se poser avant d'ouvrir l'éditeur. Si une case résiste, c'est là qu'il faut creuser.

Je sais quel problème métier je résous, et pour qui — pas juste quelle fonctionnalité livrer.
J'ai un langage commun avec les experts métier, et je l'utiliserai tel quel dans le code.
J'ai identifié le cœur de métier et j'y concentre mon effort de conception.
J'ai tracé les bounded contexts et la nature de leurs relations (context map).
Mon CdCF décrit le quoi/pourquoi sans aucun choix technique.
J'ai défini mes agrégats en répondant à « qu'est-ce qui doit être cohérent dans la même transaction ? ».
Mes concepts à règles sont des value objects, pas des primitifs nus.
Mon modèle est riche : le comportement vit avec les données qu'il protège.
Mon domaine ne dépend ni de la base, ni du framework — je pourrais le tester sans eux.
Je suis prêt à itérer : ce modèle évoluera, et c'est prévu.
Pour finir

Antisèche & lectures

Le vocabulaire essentiel, à épingler — et par où continuer.

Stratégique — la vue d'ensemble
DomaineLe métier que sert le logiciel.
Sous-domaineUne partie du métier : cœur, support ou générique.
Langage omniprésentUn vocabulaire unique, des réunions jusqu'au code.
Bounded ContextLa frontière dans laquelle un modèle et son langage sont valides.
Context MapLa carte des contextes et de leurs relations.
ACLCouche anticorruption : protège votre modèle d'un modèle externe.
Tactique — les briques
Value ObjectDéfini par sa valeur, immuable, sans identité.
EntityIdentité stable dans le temps, état mutable.
AggregateUnité de cohérence ; on y accède par sa racine.
Domain EventUn fait métier survenu, nommé au passé.
RepositoryCollection d'agrégats, abstraite de la base.
Domain ServiceOpération métier sans propriétaire naturel.
FactoryCréation encapsulée d'agrégats valides.
Charpente
HexagonalePorts (interfaces du domaine) & adapters (implémentations infra).
Règle de dépendanceLes dépendances pointent vers le domaine, jamais l'inverse.
Modèle richeDonnées + règles ensemble. « Tell, don't ask. »

Pour aller plus loin

Les références qui font autorité (plusieurs existent en français) :

  • Eric EvansDomain-Driven Design (le « livre bleu », fondateur). Dense, mais c'est la source.
  • Vaughn VernonImplementing DDD (le « livre rouge ») et Domain-Driven Design Distilled (l'introduction la plus accessible).
  • Vlad KhononovLearning Domain-Driven Design : moderne, pragmatique, idéal pour démarrer.
  • Scott WlaschinDomain Modeling Made Functional : modéliser avec les types, très complémentaire de l'approche value objects.
  • Côté méthode : explorez l'EventStorming (Alberto Brandolini) et l'architecture hexagonale (Alistair Cockburn).
🧭
Le mot de la fin

La meilleure conception n'est pas la plus sophistiquée : c'est celle qui partage la bonne compréhension du métier et garde ce cœur protégé. Le code n'est que la dernière traduction d'un modèle bien pensé. Comprenez le territoire, dessinez la carte — et le code suivra droit. Bonne exploration ! 🧭