Communitygithub.com

Conception pilotée par domaine (Principal-Driven Domain Design)

Lignes directrices automatiques de niveau principal pour les tâches de code de production dans les applications, API, workers et monorepos. À appliquer lors de l'implémentation, des corrections, du refactoring et des revues d'architecture sans nécessiter de nom de compétence ou de phrase de déclenchement. Regrouper par domaine puis par fonction, en utilisant des services limités, des modules partagés et des moteurs réutilisables. Tracer les modules créés et les chemins modifiés pour détecter les lacunes d'intégration, les bogues et les comportements requis ; préserver les transferts explicites entre agents. Appliquer les petites corrections localement sans déclencher de restructuration du dépôt. Exclut le travail purement rédactionnel et les modifications générées ou provenant de fournisseurs.

Qu'est-ce que Conception pilotée par domaine (Principal-Driven Domain Design) ?

Cette compétence, Conception pilotée par domaine (Principal-Driven Domain Design), est un guide technique automatisé pour les agents IA tels que Claude Code, Cursor ou Codex, visant à garantir une architecture logicielle cohérente et maintenable. Elle s'applique automatiquement à toute tâche de codage, sans nécessiter d'invocation explicite. Son objectif est de rendre l'appartenance métier évidente à travers les chemins, les noms, les contrats et les dépendances, tout en optimisant pour un comportement correct, des modifications lisibles, des performances mesurées et une évolution économique. La compétence fournit des règles strictes pour structurer le code par domaine puis par fonction, avec des catégories comme `model/`, `services/` et `ports/`, et interdit les dépendances circulaires en imposant une direction stricte des dépendances. Elle couvre également le transfert entre agents avec un contrat structuré (champs obligatoires comme `goal`, `location`, `ownership`), garantissant que les sous-agents reçoivent un contexte clair et restituent des preuves vérifiables. La compétence s'applique via un fichier SKILL.md que l'agent inspecte, et ne nécessite aucun plugin ou CLI particulier, se basant sur les outils disponibles du dépôt (recherche, build, test).

Compatible avec✓Claude Code~Codex CLI~Cursor
npx skills add https://github.com/sigmastudioz/agent-skills/tree/HEAD/plugins/domain-driven-design/skills/domain-driven-design

Demander à votre IA préférée

Ouvre une nouvelle conversation avec cette compétence d'agent déjà préchargée.

Documentation

Que fait Conception pilotée par domaine (Principal-Driven Domain Design) ?

Par Lex de SigmaStudioz.

Rendre l'appartenance métier évidente à partir des chemins, des noms, des contrats et des dépendances. Optimiser pour un comportement correct, des modifications lisibles, des performances mesurées et une évolution économique. Appliquer cette compétence au changement demandé ; elle n'autorise pas une refonte du projet.

Exécution automatique

Appliquer cette base de référence avant de planifier ou d'éditer du code de production ; ne pas attendre une invocation de la compétence, une phrase de déclenchement ou une demande d'architecture. Effectuer l'implémentation, la réutilisation, les corrections de lacunes, la vérification et les transferts autorisés dans le cadre de la tâche de codage, plutôt que de simplement les suggérer. Pour les tâches de revue ou de planification uniquement, appliquer le même raisonnement sans éditer le code. Maintenir le travail proportionnel à la portée et au risque ; l'utilisation automatique n'autorise pas les modifications non liées ou la délégation.

Portabilité des agents et transferts

Il s'agit d'instructions neutres vis-à-vis des outils, destinées aux agents capables de lire le Markdown et d'inspecter un projet. Utiliser les outils de recherche, de construction, de test et d'exécution disponibles ; aucun fournisseur, plugin ou CLI particulier n'est requis. Respecter la hiérarchie d'instructions de l'hôte, les autorisations et la portée explicite de la tâche. Cette compétence n'active pas de capacités désactivées ni n'accorde l'autorisation de déployer, publier ou effectuer des modifications destructrices.

Lorsque la délégation est déjà autorisée, transmettre le chemin accessible de la compétence ou les instructions pertinentes, les fichiers/modules possédés, les conditions d'acceptation et les obligations de traçage dans l'affectation. Ne pas supposer qu'un agent enfant hérite de la conversation du parent, des compétences chargées ou des fichiers d'instructions globaux. Exiger des preuves et des points non résolus de chaque travailleur ; réconcilier les traces à travers les frontières des travailleurs. Déléguer les invariants vérifiés ; étiqueter les algorithmes proposés comme des hypothèses et contester les contradictions. Si l'enfant ne peut pas lire la compétence, fournir son contenu pertinent dans le contexte autorisé. Ne pas créer d'agents simplement parce que cette section décrit les transferts. Avant d'adopter un autre flux de travail, enregistrer le nombre de coéquipiers et les rôles autorisés par l'utilisateur. Chaque agent d'exploration, d'implémentation et de revue consomme ce budget ; les revues de suivi restent dans le coordinateur lorsque celui-ci est épuisé. Les compétences optionnelles de flux de travail ne peuvent pas étendre la limite de l'utilisateur. Traiter les briefs de tâche et le pseudo-code comme des propositions : vérifier indépendamment leurs algorithmes par rapport au contrat d'origine. Corriger un plan défectueux au lieu de le conserver comme une exigence d'implémentation.

Contrat de transfert

Chaque affectation d'agent autorisée ou transfert pouvant être repris doit identifier :

ChampContexte requis
Objectif et limitesRésultat utilisateur, contrôles d'acceptation, actions autorisées, exclusions
EmplacementRacine de l'espace de travail accessible, branche/répertoire de travail ou révision, chemins d'instructions/compétences pertinents
PropriétéFichiers/modules exacts que l'agent possède ; autres propriétaires actifs et dépendances d'interface partagées
ArchitecturePropriétaire du domaine, points d'entrée/contrats publics, chemins importants des appelants et consommateurs
État actuelTravail implémenté par rapport au travail en attente, modifications locales, décisions et pourquoi, échecs connus
PreuvesCommandes et résultats, chemins/ID du registre de traces, révision vérifiée, environnements non disponibles
Prochaine actionProchaine étape concrète, blocages, entrées requises et format de retour attendu

Les hôtes peuvent appliquer ce contrat avec le gardien de délégation. Le gardien Claude optionnel fournit cette base de référence et vérifie les limites numériques explicites des agents dans les tours utilisateur natifs (Utiliser N coéquipiers/agents/travailleurs) ; l'absence d'historique laisse l'application au coordinateur. Il n'accorde pas d'outils ni ne garantit la correction sémantique. Lorsque ce gardien est installé, préfixer l'affectation avec HANDOFF_JSON= et un objet JSON contenant goal, limits, workspace, revision, owns, interfaces, state, evidence, next, return, trace, checks et baseline. return doit être un objet avec des instructions non vides pour paths, contracts, checks, gaps et remaining. trace nomme les chemins et cas d'échec à suivre ; checks nomme les vérifications à effectuer ou pourquoi elles sont indisponibles. baseline est le chemin accessible de cette compétence. Cela s'applique également aux affectations d'exploration et de revue. Une affectation rejetée doit être corrigée avant d'être réessayée.

Utiliser les chemins réels sur l'hôte de l'agent récepteur ; inclure le contenu nécessaire lorsque les chemins diffèrent ou sont inaccessibles. Donner aux commandes leur répertoire de travail et les noms de configuration non secrets requis. Ne jamais placer d'identifiants ou de charges utiles d'exécution privées dans les notes de transfert. Un nom de branche seul ne prouve pas qu'un enfant voit le travail non validé ; établir si le checkout est partagé ou isolé.

Pour le travail concurrent, convenir des contrats publics et de la propriété des fichiers avant les modifications qui se chevauchent. Dire aux agents qu'ils ne sont pas seuls : préserver les modifications des autres et coordonner les fichiers partagés via le propriétaire assigné. Rebaser ou réconcilier les modifications isolées avant de revendiquer l'intégration ; ne pas écarter silencieusement le travail. Au retour, signaler les chemins modifiés, les modifications de contrats publics, les vérifications avec leurs résultats, les ID/statuts des lacunes et les actions restantes. Le coordinateur réconcilie le registre de traces et vérifie les jonctions entre agents et les consommateurs affectés ; plusieurs vérifications réussies de travailleurs n'établissent pas un flux de travail intégré fonctionnel.

En cas d'interruption ou de perte de contexte, sauvegarder le transfert dans l'enregistrement de tâche/trace existant avec un horodatage et une révision du contenu, puis lier cet enregistrement. Lors de la reprise, inspecter le checkout et le diff actuel avant d'agir ; revalider les hypothèses obsolètes. Ne pas créer une deuxième source de vérité pour la tâche.

L'installation locale n'implique pas l'installation sur le cloud, un hôte distant ou un agent non lié. Établir la découverte sur chaque hôte d'exécution ; utiliser une instruction globale native de l'hôte pour acheminer le travail pertinent ici. Si la découverte ou l'accès aux fichiers est indisponible, signaler cette limitation au lieu de revendiquer une application globale.

Contrat d'ingénierie principal

  • Commencer par les capacités métier, les invariants, les workflows utilisateur et les contraintes opérationnelles.
  • Préférer une cohésion élevée au sein des domaines et un couplage faible entre eux.
  • Placer le code spécifique au domaine avec son propriétaire ; regrouper le code par fonction à l'intérieur de cette limite.
  • Donner à chaque règle métier et modèle d'écriture autoritaire un propriétaire clair.
  • Réutiliser les implémentations existantes avant d'en ajouter une autre ; éviter la duplication des connaissances métier.
  • Choisir la plus petite architecture qui répond aux besoins démontrés et prend en charge les changements probables.
  • Séparer les observations, les hypothèses, les décisions et les preuves. Ne pas inventer d'exigences ou de benchmarks.
  • Préserver le comportement public fonctionnel pendant les modifications structurelles, sauf si un changement de comportement est demandé.
  • Améliorer le chemin touché et ses dépendances nécessaires. Ne pas entraîner de code non lié dans la tâche.

1. Établir le contexte avant d'éditer

Inspecter les instructions applicables du dépôt, les manifestes, les exports de paquets, les points d'entrée, les modules de domaine existants, les migrations, les tests et les preuves d'exécution pertinentes. Rechercher un comportement équivalent et des paquets partagés existants avant de créer des fichiers. Utiliser le langage et les outils du dépôt.

Tracer un workflow pertinent, de l'entrée utilisateur ou d'événement jusqu'à l'autorisation, le service, les règles du domaine, la persistance, les effets en aval et l'état retourné ou affiché. Inclure les chemins d'erreur. Identifier les consommateurs et rédacteurs réels ; un nom de répertoire seul n'établit pas la propriété.

Pour un travail d'architecture substantiel, établir un cadre de décision compact :

QuestionRéponse requise
Résultat métierQuel workflow utilisateur ou invariant change ?
PropriétéQuel contexte délimité possède la signification et les écritures autoritaires ?
ConsommateursQuelles applications, jobs, modules ou systèmes externes ont besoin de la capacité ?
ContraintesCompatibilité, volume de données, latence, location, disponibilité, coût, déploiement ?
Preuves actuellesChemins, contrats, échecs, timings ou comportement de requête pertinents ?
Plus petit changementQu'est-ce qui peut être réutilisé, et quelle limite a réellement besoin de changer ?
AchèvementConditions d'acceptation observables et vérification appropriée ?

Ne demander que lorsqu'une décision métier non résolue bloque le travail correct ; sinon, énoncer les hypothèses.

2. Définir les limites du domaine

Un contexte délimité possède un vocabulaire métier, des règles et un modèle cohérents. Une fonctionnalité, une table, un écran, une couche de framework, un déploiement ou un nom d'équipe n'est pas automatiquement un contexte délimité. Utiliser des noms de capacités métier tels que billing, scheduling, playback ou execution.

  • Séparer les contextes lorsque le même terme a des significations, des invariants, des cycles de vie ou des propriétaires différents.
  • Garder les entités ensemble lorsque leur invariant doit être appliqué dans une seule opération atomique.
  • Éviter les agrégats surdimensionnés : distinguer les véritables invariants atomiques des workflows inter-contextes qui nécessitent une cohérence explicite, une orchestration ou une compensation plutôt qu'une transaction partagée.
  • Distinguer la différenciation métier principale des capacités de soutien et de commodité.
  • Investir l'effort de modélisation là où la complexité ou la valeur métier le justifie ; garder le CRUD simple simple.
  • Enregistrer la propriété en amont/aval et la traduction aux limites de contexte importantes.
  • Consommer un autre contexte via son API publique, son port ou son contrat ; ne pas importer ses internes.
  • Traduire les modèles externes/fournisseurs à la limite plutôt que de les laisser fuir dans les règles métier.
  • Préférer un monolithe modulaire jusqu'à ce que le déploiement indépendant, la mise à l'échelle, l'isolation des pannes ou la propriété justifient une séparation en services. Un monorepo n'implique pas des microservices.

Si un changement traverse des domaines, identifier le cas d'utilisation orchestrateur et la responsabilité de chaque domaine. Placer l'orchestration avec le propriétaire du workflow, pas dans un helper global ou un composant d'interface utilisateur.

3. Structurer par domaine, puis par fonction

Choisir d'abord le périmètre propriétaire, puis la catégorie fonctionnelle. Dans ce périmètre :

CatégorieResponsabilité
model/Entités, objets valeur, invariants, politiques, événements de domaine
services/Cas d'utilisation applicatifs nommés et orchestration
ports/Interfaces pour la persistance, les horloges, l'identité, les files d'attente, les fournisseurs
adapters/Implémentations concrètes de base de données, transport, fournisseur ou plateforme
contracts/DTO publics, schémas d'événements, validation, contrats de compatibilité
components/, hooks/UI du domaine et comportement UI lorsque ce domaine possède un frontend
shared/Code réutilisable pour les consommateurs dans ce périmètre
tests/ ou tests colocalisésVérification du comportement et des limites en utilisant les conventions du dépôt

Les implémentations de service appartiennent à services/ dans leur couche propriétaire. Lorsqu'un service de domaine est nécessaire pour une règle couvrant plusieurs entités, le placer dans model/services/ ; l'orchestration reste dans le services/ principal du domaine. Les services de fournisseur peuvent vivre dans adapters/services/ lorsque c'est utile.

Pour une application, utiliser src/domains/<domaine>/{model,services,ports,adapters,contracts,shared} selon les besoins, un point d'entrée public, des routes de framework légères et une racine de composition. Placer les primitives neutres vis-à-vis du domaine sous src/shared/. Créer uniquement des répertoires contenant du code réel.

Exemple de monorepo ; respecter les conventions de paquets existantes et les exports explicites :

apps/
  web/                           # Composition de l'application et présentation
  api/                           # Points d'entrée de transport légers
  worker/                        # Enregistrement des jobs et composition
packages/
  billing/                       # Paquet d'espace de travail possédé
    package.json                 # Exports publics et compatibilité d'exécution
    src/
      services/                  # Cas d'utilisation partagés par API/worker
      shared/                    # Réutilisation locale de la facturation
      index.ts                   # Façade publique explicite
  shared/
    contracts/                   # Paquet d'espace de travail neutre du domaine
    ui/                          # Consommateurs frontend compatibles

Enregister les paquets réels dans l'espace de travail ; les chemins seuls ne les rendent pas importables. Dans les espaces de travail polyglottes, exposer des bibliothèques compatibles ou des clients générés à partir de schémas canoniques ; ne pas tenter d'importer du code à travers des runtimes incompatibles.

Règles de placement

  1. Un seul consommateur et une signification spécifique au domaine : le garder dans ce domaine.
  2. Plusieurs consommateurs dans un domaine : utiliser le services/ ou shared/ de ce domaine.
  3. Plusieurs applications compatibles ont besoin de code de domaine réutilisable : le placer dans un paquet de domaine d'espace de travail ; le comportement serveur privilégié reste côté serveur derrière une API ou un contrat client autorisé.
  4. Plusieurs domaines ont besoin de la même primitive neutre : utiliser le code shared/ limité.
  5. Les consommateurs ont besoin de significations métier différentes : garder des modèles séparés et traduire explicitement.
  6. Workflow inter-domaines : utiliser un service applicatif propriétaire et des contrats de domaine publics.
  7. Routes, écrans, contrôleurs et jobs : déléguer les règles aux services ; garder les préoccupations de transport locales.

Ne jamais copier une capacité dans plusieurs applications juste pour rendre les importations pratiques. Ne jamais faire d'une application la bibliothèque d'une autre application. Déplacer la propriété réutilisable vers un package dont les deux peuvent dépendre. Garder les répertoires requis par le framework ; les router dans la structure du domaine plutôt que de lutter contre le framework. Respecter le packaging standard du langage et l'architecture existante valide.

4. Appliquer la direction des dépendances

points d'entrée -> services applicatifs publics -> modèle + ports
adaptateurs -> ports + modèle
bootstrap -> services + adaptateurs             # Câble les implémentations concrètes
paquets de domaine -> paquets partagés neutres du domaine
  • Le modèle ne dépend pas de HTTP, des frameworks UI, des bases de données, des files d'attente ou des SDKs fournisseurs.
  • Les services orchestrent les cas d'utilisation via des dépendances explicites ; les adaptateurs implémentent les ports.
  • Les paquets partagés n'importent pas les applications ou les internes du domaine. Éviter les dépendances circulaires.
  • Les appels inter-domaines utilisent des contrats publics ; éviter les cycles d'appels synchrones et les chaînes bavardes.
  • Exporter des points d'entrée intentionnels. Bloquer les importations profondes avec les outils existants (paquet, lint, build).
  • Séparer les contrats compatibles navigateur des implémentations côté serveur et des dépendances privilégiées.
  • Garder les SDKs privilégiés, les clients de base de données, les secrets et le code du système de fichiers hors des graphes de dépendances client.
  • Les SDKs fournisseurs peuvent s'exécuter dans les adaptateurs, pas dans le modèle ou les services de domaine.
  • Stocker l'état principal dans une base de données ; éviter la synchronisation entre cœurs via le système de fichiers.

5. Concevoir le cycle de vie et la cohérence

Pour chaque agrégat, définir la racine (entité responsable de l'invariant), la portée de chargement, la grande limite (éventuelle), les politiques de suppression et de cycle de vie. Écrire une seule fois chaque règle métier invariante et la faire respecter dans l'écriture autoritaire.

Éviter les autorisations pilotées par rôle dans le modèle ; utiliser la politique d'autorisation comme une fonction dédiée consultable par les services. L'état principal d'autorisation peut vivre dans le modèle ; les politiques et les listes sont déléguées à un service ou un composant d'autorisation dédié.

Pour les relations de base de données, utiliser des identifiants logiques ; ne pas exposer les clés de base de données générées aux consommateurs externes comme identificateurs de domaine. Utiliser des identifiants de domaine intentionnels : UUIDs, slugs lisibles ou identifiants métier réels. Ne pas dupliquer des données stables à travers les agrégats ; référencer via un identifiant et mettre en cache (tolérant à la fraîcheur) lorsqu'une performance de lecture le justifie.

6. Écrire des règles métier vérifiables

  • Chaque règle métier doit avoir un) emplacement de code unique et évident où elle est vérifiée ou appliquée.
  • Les règles invariantes peuvent résider dans des méthodes d'entité, des objets valeur, des politiques de constructeur, des gardes de dépôt ou des événements de domaine.
  • Les contraintes transactionnelles et les considérations de concurrence doivent être documentées près du code.
  • Préférer les règles explicites et déterministes (encapsulées dans le modèle) aux politiques implicites basées sur la configuration.

Pour les cas où une coordination entre services (ou entre domaines) est requise, utiliser des workflows de processus métier explicites. Un processus métier se compose d'étapes, chacune avec des entrées, des sorties, des politiques de nouvelle tentative et des états de compensation. Les orchestrer via un moteur de processus (ou un service dédié avec état).

7. Concevoir pour la testabilité

  • Tester chaque règle métier via des tests unitaires du modèle de domaine.
  • Tester les cas d'utilisation et l'orchestration via des tests d'intégration sur le service applicatif (en utilisant des implémentations de ports simulées).
  • Tester les adaptateurs via des tests d'intégration contre la vraie dépendance (par exemple, la base de données, l'API externe) en utilisant des stratégies de test isolées (conteneurs de test, API fictives).
  • Utiliser les tests de bout en bout avec parcimonie pour les workflows critiques uniquement.
  • Tester les contrats publics (tests de compatibilité, tests de contrat (clients)).

Le modèle de domaine doit pouvoir être testé sans cadre de base de données, sans infrastructure HTTP, sans files d'attente ni SDKs externes. Les services doivent accepter des implémentations de ports simulées pour l'isolement des tests.

8. Évoluer de manière itérative

  • Permettre l'évolution des contrats ; utiliser des versions ou des mécanismes de compatibilité.
  • Préférer l'ajout au changement perturbateur ; utiliser un dépréciation avant la suppression.
  • Refactorer le modèle interne sans modifier les contrats publics publiés.
  • Déplacer les responsabilités entre les contextes de domaine lorsque l'apprentissage métier clarifie les limites.
  • Mesurer l'évolution en fonction de la valeur métier fournie, pas du volume de code.

Déclaration de fin

Cette compétence ne garantit pas que le code résultant est correct, sécurisé, conforme ou viable en production. Toujours vérifier les décisions architecturales avec les parties prenantes du domaine et les équipes de sécurité/platforme. Observer la production après le déploiement pour valider les hypothèses et guider l'évolution continue du domaine.

Individual skills in this repo

This repo contains 2 individual skills — each has its own dedicated page.

Skills associés