DDD - Le modèle de domaine anémique est-il un contre-modèle? Devrions-nous utiliser des modèles de domaine riches? [fermé]

11

Le modèle de domaine anémique a été critiqué il y a longtemps par Evans et Fowler , car il va apparemment à l'encontre des principes orientés objet, etc. La communauté DDD est clairement alignée sur ces affirmations.

Cependant, ces dernières années, il y a eu des voix en désaccord affirmant que ce n'est pas du tout un contre-modèle et que c'est un exemple de suivre les principes SOLIDES.

Je travaille depuis tant d'années avec Spring Framework. Chaque projet dans chaque entreprise a toujours eu une couche de service contenant la logique métier, en utilisant des référentiels qui fonctionnent sur des modèles anémiques (entités JPA). De plus, la plupart des échantillons, même les échantillons officiels des gars de Spring, présentent cette façon de travailler.

Mes questions sont les suivantes: le modèle de domaine anémique est-il toujours considéré comme un contre-modèle? Avons-nous tous fait des choses (concernant DDD) mal? Ne pensez-vous pas qu'avoir des modèles Rich Domain viole les principes SOLID?

codépendant
la source
2
"Le modèle de domaine anémique est-il toujours considéré comme un contre-modèle? ". Par certains, oui. Pour d'autres, moi y compris, voyez-le comme la meilleure façon d'écrire du code la plupart du temps, mais si le RDM vous convient, utilisez-le. Donc, voter pour clore cela comme purement basé sur l'opinion.
David Arno
1
Ce serait une question fantastique pour un forum de discussion / débat; mais il n'y a actuellement aucune réponse faisant autorité. Nous préférons les questions auxquelles on peut répondre, pas seulement discutées.
VoiceOfUnreason

Réponses:

9

ADM est un bon modèle pour une solution de services distribués tels que des microservices. Il convient à de nombreuses analyses de rentabilisation basées sur le Web d'aujourd'hui.

Considérez si nous avons un objet Order Domain. Avec une approche POO, nous ajouterions Order.Purchase () Order.Cancel () etc. Cela fonctionnerait bien dans une application de bureau, où nous conservons des commandes en mémoire et faisons plusieurs choses dans la même instance.

Mais si nous avons un système distribué, avec des programmes qui ne servent qu’à une chose, c.-à-d. Accéder à une liste de commandes et les acheter à tour de rôle, ou obtenir une liste de commandes et les annuler à tour de rôle, alors avoir les deux méthodes sur le même objet ne fait aucun sens. Il faudrait avoir deux domaines ou contextes délimités:

PurchaseSystemOrder.Purchase()

et

CancelSystemOrder.Cancel();

La seule chose que ces objets partageraient serait la structure de données des propriétés.

À mesure que vous ajoutez de plus en plus de microservices, vous vous retrouvez avec des dizaines de types de commandes. Il n'est plus logique de parler d' un ordre en tant qu'objet domaine, même s'il s'agit du même ordre conceptuel qui est traité par tous ces systèmes.

Il est beaucoup plus logique d'avoir un modèle anémique, Order, qui n'encapsule que les données et de renommer vos services en conséquence:

PurchaseService.Purchase(Order order)

Maintenant, nous pouvons à nouveau parler d'Ordre et nous pouvons ajouter tous les nouveaux services que nous pensons pour traiter, sans affecter les autres services actuellement déployés.

Fowler and Co sont issus d'un système monolithique, dans leur monde, une approche ADM signifierait une seule application avec tous ces services séparés instanciés en mémoire et le OrderDTO transmis et muté. Ce serait bien pire que de mettre les méthodes sur un modèle d'Ordre riche.

Mais dans un système distribué, il existe de nombreux programmes, chacun ne nécessite qu'une seule méthode Order et l'exécute sur plusieurs commandes, en chargeant chacun, en exécutant la méthode puis en la rejetant. Il ne nécessite qu'un seul service et un flux d'objets de données.

Remplir complètement un modèle riche, s'inquiéter des exigences et des dépendances de toutes les méthodes pour n'en appeler qu'un seul puis rejeter l'objet presque immédiatement est inutile.

De plus, la modification d'une seule des méthodes nécessiterait la mise à jour de tous les composants distribués car ils dépendent tous du modèle riche pour leur logique.

Je n'ai pas de place dans mes bases de code pour des trucs dont ils n'ont pas besoin

Ewan
la source
4
J'ai voté contre parce que je pense que DDD est particulièrement bien adapté aux microservices précisément en raison du concept de contexte borné. Je pense que le problème avec votre réponse est que le concept et la classe de votre commande seraient les mêmes pour chaque micro-service, mais je pense que ce n'est ni nécessaire ni exact.
RibaldEddie
Je ne suis pas en désaccord, ADM peut être DDD si vous appelez votre PurchaseService CashRegister et que vous en faites partie de la langue de votre domaine
Ewan
peux-tu élaborer? J'ai toujours pensé que YMMV lorsque ADM et DDD étaient dans une base de code EF SOLIDE J2EE ou .NET C # MVC.
RibaldEddie
Ce que je veux dire, c'est que le contexte de commande Order, PurchaseSystemOrder.Purchase () sera un code à peu près identique à CashRegister.Purchase (Order order) c'est juste un changement de nom dans la langue de votre domaine. Un modèle de domaine riche signifie que les méthodes d'achat et d'annulation sont sur la même classe.
Ewan
1
@RibaldEddie, Dans la veine de l'épaisseur du livre "javaScript, the good parts", je propose cette image comme un argument (pas complètement sérieux) contre l'utilisation de DDD pour implémenter des microservices;)
David Arno
3

SOLID et DDD sont orthogonaux l'un à l'autre, ce qui signifie qu'ils vont vraiment dans des directions différentes. Vous ne devez pas dire que l'un est utilisé à l'exclusion de l'autre, car ils peuvent et doivent probablement exister ensemble dans la même base de code.

Les modèles de domaine anémiques ne deviennent un anti-modèle que lorsque votre domaine problématique a beaucoup de comportement et que vous avez des centaines de méthodes de service avec beaucoup de logiques ou de dépendances copiées-collées où les méthodes de couche service doivent appeler d'autres méthodes de couche service pour faire quoi que ce soit.

DDD est un excellent paradigme pour les micro-services en raison du concept de contexte borné .

Méfiez-vous de la tentation de voir le code d'infrastructure dans le cadre de votre domaine. Le code d'infrastructure est tout ce que vous n'avez pas écrit vous-même ou tout ce qui est couplé à un cadre ou une bibliothèque qui interagit avec un système tiers. Connexions à la base de données, mailers SMTP, bibliothèques ORM, temps d'exécution du serveur d'applications, tout cela est une infrastructure et vous ne devriez pas l'inclure ou en dépendre dans votre domaine si vous pouvez l'éviter.

Les principes SOLID sont un ensemble de concepts OOP à usage général que vous pouvez utiliser pour créer un meilleur code OOP. Vous pouvez écrire une bonne base de code DDD en les utilisant.

RibaldEddie
la source
Concernant la séparation du code d'infrastructure du domaine. Jusqu'à présent, j'avais considéré les entités JPA comme mon domaine, avec les couches d'application suivantes: contrôleur -> service -> référentiel -> domaine (entités JPA). Quelles seraient les bonnes (ou l'une des bonnes) façons de les modéliser selon votre point de vue? Quelque chose comme: contrôleur -> modèle riche -> x? Comment et où pourrais-je gérer la transactionnalité? Et qu'en est-il de la cartographie JPA? Ne serions-nous pas obligés de dupliquer notre modèle riche avec des entités JPA séparées?
codépendant
Une entité JPA est un vieil objet Java simple. Le mappage fait partie de l'infrastructure mais la classe elle-même ne doit pas l'être. Si vous choisissez de le traiter comme faisant partie de l'infrastructure, vous devez le considérer comme un objet de transfert de données utilisé dans la fabrique ou le référentiel pour créer une entité de domaine.
RibaldEddie
1

Un domaine riche est agréable lorsqu'il est bien fait. Un cauchemar quand non. Un domaine anémique est toujours mauvais. Mais c'est une sorte de mal confortable et familier.

Si un domaine anémique est tout ce que vous voulez, vous avez choisi la mauvaise langue lorsque vous avez choisi une langue à usage général. Les langues de 4e génération se spécialisent autour d'une utilisation spécifique. Si l'anémie est assez bonne, leur utilisation vous aurait facilité la vie.

De nombreux frameworks se frayent un chemin dans l'espace linguistique jusqu'à ce que vous ne puissiez plus annoncer le travail comme un travail java. C'est un travail Java / Spring. Ce qu'ils font, en plus de vous faire dépendre d'eux, c'est de transformer un langage à usage général en une forme bâtarde d'un langage de 4e génération.

Est-ce une meilleure pratique ou un modèle anti? Eh bien, votre patron se soucie surtout de savoir si vous pouvez embaucher des gens pour travailler sur la base de code. Donc, si nous devons faire semblant d'utiliser un langage général pour embaucher des gens, nous le ferons.

Si vous êtes d'accord avec ça, alors très bien. Vous n'êtes certainement pas le seul.

Mais ne me dites pas que c'est comme ça que ça doit être. Ne me dites pas que ça fait plus pour moi que ça. Je sais comment m'en passer. Je sais comment le faire sortir, donc seules quelques choses en dépendent. Si vous me demandez de céder et de le laisser prendre le dessus juste parce que le combattre est trop dur, alors oui, je pense que c'est mauvais.

Je n'ai pas de place dans ma base de code pour des choses dont il n'a pas besoin.

En ce qui concerne SOLID et les autres principes de conception, je peux largement les suivre même dans un domaine anémique. Ne pas les suivre provoque un autre type de problème.

candied_orange
la source
J'apprécie votre réponse et je suis absolument d'accord que certains frameworks tels que Spring ou JPA-Hibernate ont conquis le paysage Java. Cependant, il est également indéniable qu'ils ont fourni un tas de bonnes pratiques et de simplifications que Java (JEE) n'a pas abordées du tout ou ont mal faites.Je suis vraiment enthousiaste à propos de DDD et je voudrais comprendre tous les principes qu'ils disent. expérience, quelles sont les meilleures plates-formes / langages / frameworks pour travailler avec des applications DDD pures (avec des modèles de domaine riches)? Tout bon échantillon Github que vous connaissez? Comme vous dites, je veux bien faire les choses, ne pas me conformer aux mauvaises pratiques.
codependent
Nous ne faisons pas de recommandations de ressources ici. Mais je crois qu'une couche d'infrastructure appropriée qui traite des cadres signifie que vous pouvez utiliser n'importe quel type de votre choix. Traitez-les simplement comme une bibliothèque. Gardez leur connaissance hors du domaine. Ne comptez pas non plus sur la magie. Résistez à l'envie d'utiliser des choses que vous ne pourriez pas fabriquer vous-même. Parce qu'un jour vous en aurez peut-être besoin.
candied_orange
Revenons au point d'origine. Qu'en est-il des principes SOLID? Les modèles de domaine riches assument de nombreuses responsabilités, la persistance (JPA), la logique métier (devoir gérer la transactionnalité), etc. Les sons sont également plus faciles à tester. Qu'est-ce qui ne va pas alors?
codépendant
L'essentiel est de commencer à faire des choix de conception en fonction des besoins du système plutôt que des besoins sémantiques. Son subtil, facile à ignorer, le coût n'est pas évident et difficile à justifier la correction. En bref, c'est comme faire valoir que les lignes électriques devraient être enterrées plutôt que dans les bureaux de scrutin. Une fois que les gens s'habitueront à l'alternative au jeu, il est peu probable que cela change. Même lorsque les ouragans coupent le courant.
candied_orange
1
J'allais vous donner le bénéfice du doute sur votre affirmation selon laquelle "Un domaine riche est bien quand il est bien fait. Un cauchemar quand ce n'est pas le cas." Peut-être que je ne l'ai jamais vu bien fait, mais alors vous dites que "un domaine anémique est toujours mauvais". Un non-sens avisé qui rend votre réponse sans valeur. -1
David Arno