Je plonge dans les concepts de la conception pilotée par domaine (DDD) et j'ai trouvé certains principes étranges, en particulier en ce qui concerne l'isolement du domaine et le modèle de persistance. Voici ma compréhension de base:
- Un service sur la couche application (fournissant un ensemble de fonctionnalités) demande des objets de domaine à un référentiel dont il a besoin pour exécuter sa fonction.
- L'implémentation concrète de ce référentiel récupère les données du stockage pour lequel il a été implémenté
- Le service indique à l'objet de domaine, qui encapsule la logique métier, d'effectuer certaines tâches qui modifient son état.
- Le service indique au référentiel de conserver l'objet de domaine modifié.
- Le référentiel doit mapper l'objet de domaine à la représentation correspondante dans le stockage.
Maintenant, compte tenu des hypothèses ci-dessus, les éléments suivants semblent maladroits:
Annonce 2:
Le modèle de domaine semble charger l'intégralité de l'objet de domaine (y compris tous les champs et références), même s'ils ne sont pas nécessaires pour la fonction qui l'a demandé. Le chargement complet peut même ne pas être possible si d'autres objets de domaine sont référencés, sauf si vous chargez également ces objets de domaine et tous les objets qu'ils référencent tour à tour, etc. Le chargement paresseux vient à l'esprit, ce qui signifie cependant que vous commencez à interroger vos objets de domaine, ce qui devrait être la responsabilité du référentiel en premier lieu.
Compte tenu de ce problème, la façon «correcte» de charger les objets de domaine semble avoir une fonction de chargement dédiée pour chaque cas d'utilisation. Ces fonctions dédiées ne chargeraient alors que les données requises par le cas d'utilisation pour lequel elles ont été conçues. Voici où la maladresse entre en jeu: Premièrement, je devrais maintenir une quantité considérable de fonctions de chargement pour chaque implémentation du référentiel, et les objets de domaine se retrouveraient dans des états incomplets transportés null
dans leurs domaines. Ce dernier ne devrait techniquement pas être un problème car si une valeur n'était pas chargée, elle ne devrait de toute façon pas être requise par la fonctionnalité qui la demandait. C'est toujours maladroit et un danger potentiel.
Annonce 3:
Comment un objet de domaine vérifierait-il les contraintes d'unicité lors de la construction s'il n'a aucune notion du référentiel? Par exemple, si je voulais créer un nouveau User
avec un numéro de sécurité sociale unique (qui est donné), le conflit le plus précoce se produirait en demandant au référentiel de sauvegarder l'objet, uniquement si une contrainte d'unicité était définie sur la base de données. Sinon, je pourrais chercher un User
avec la sécurité sociale donnée et signaler une erreur si elle existe, avant d'en créer une nouvelle. Mais alors les vérifications de contraintes vivraient dans le service et non dans l'objet de domaine auquel elles appartiennent. Je viens de réaliser que les objets de domaine sont très bien autorisés à utiliser des référentiels (injectés) pour la validation.
Annonce 5:
Je perçois le mappage des objets de domaine à un backend de stockage comme un processus exigeant en termes de travail par rapport au fait que les objets de domaine modifient directement les données sous-jacentes. Il s'agit bien sûr d'une condition préalable essentielle pour dissocier l'implémentation concrète du stockage du code de domaine. Cependant, cela coûte-t-il vraiment si cher?
Vous avez apparemment la possibilité d'utiliser des outils ORM pour effectuer le mappage pour vous. Cependant, cela nécessiterait souvent que vous conceviez le modèle de domaine en fonction des restrictions de l'ORM, ou même introduisiez une dépendance du domaine à la couche d'infrastructure (en utilisant des annotations ORM dans les objets de domaine, par exemple). J'ai également lu que les ORM introduisent une surcharge de calcul considérable.
Dans le cas des bases de données NoSQL, pour lesquelles il n'existe pratiquement aucun concept de type ORM, comment pouvez-vous suivre les propriétés modifiées dans les modèles de domaine save()
?
Modifier : pour qu'un référentiel accède à l'état de l'objet domaine (c'est-à-dire la valeur de chaque champ), l'objet domaine doit révéler son état interne qui rompt l'encapsulation.
En général:
- Où irait la logique transactionnelle? Ceci est certainement spécifique à la persistance. Certaines infrastructures de stockage peuvent même ne pas prendre en charge les transactions (comme les référentiels fictifs en mémoire).
- Pour les opérations en bloc qui modifient plusieurs objets, devrais-je charger, modifier et stocker chaque objet individuellement afin de passer par la logique de validation encapsulée de l'objet? Cela s'oppose à l'exécution d'une seule requête directement sur la base de données.
J'apprécierais quelques éclaircissements sur ce sujet. Mes hypothèses sont-elles correctes? Sinon, quelle est la bonne façon de résoudre ces problèmes?