Lorsque j'ai utilisé IoC Container dans mon dernier projet, je me suis retrouvé avec des entités anémiques et la plupart de ma logique métier dans Stateless Services.
J'ai vu des projets écrits par d'autres développeurs qui utilisent "Inversion of Control" et ils sont toujours "Anemic".
Étant donné que le «modèle de domaine anémique» est anti-modèle, est-il possible d'utiliser l'IoC et le domaine riche? Y a-t-il de bons exemples, des projets open source qui font ça?
Réponses:
Pour commencer: DI et IoC ne sont pas synonymes. Je suis désolé mais je dois le signaler (il me semble que vous pensez qu'ils le sont).
Quant à votre demande ... Eh bien, l'injection de dépendance n'est qu'un outil. Comment vous allez utiliser cet outil est une chose complètement distincte. Il existe également d'autres outils (modèles de conception) qui pourraient s'ajouter au problème. Par exemple, je pense qu'une large adoption du modèle MVC est l'un des ingrédients clés de la formation de l'anti-modèle du modèle de domaine anémique: les contrôleurs (dans les applications plus simples, dans les plus complexes qui seraient une couche de service supplémentaire) assument la responsabilité de la validation des règles métier. , en les appliquant ainsi qu'en transformant les entités de base de données en quelque chose d'utile, tandis que Business Layer se transforme en simple couche d'accès aux données qui est un ORM simple avec un mappage un à un vers les entités de base de données.
C'est certainement la façon dont vous concevez votre application - vous pouvez créer un modèle de domaine correct si vous le souhaitez, et tous ces IoC, DI, MVC ne vous arrêtent pas. Ce qui pourrait vous arrêter, c'est votre équipe. Vous devez en quelque sorte les convaincre d'utiliser le bon chemin et cela peut être difficile car de nombreux développeurs de logiciels n'ont pas une solide expérience architecturale.
la source
La plupart (sinon la totalité) des applications sont un mélange de problèmes d'infrastructure et de domaine. Lorsque vous atteignez un certain niveau de complexité, vous faciliterez la gestion si le domaine est séparé de l'infrastructure afin qu'il soit plus facile de raisonner et d'évoluer indépendamment.
Bien sûr, le modèle de domaine doit toujours communiquer avec le reste du système et ce sera généralement avec des services sans état (qui font partie du domaine) qui ont des problèmes d'infrastructure (tels que l'accès à la base de données) qui leur sont injectés. L'utilisation d'un conteneur IoC ne supprime pas cette dépendance, il déplace sa configuration dans une zone distincte - ce qui facilite encore plus le raisonnement et la maintenance.
Les entités stockent l'état et devraient être responsables des règles commerciales. Si vos services appliquent tous les invariants et autres règles métier, il est probable que la logique est au mauvais endroit.
Maintenant, si vous avez la logique aux bons endroits et que vous vous êtes quand même retrouvé avec des services qui ne sont que des enveloppes autour d'infrastructures et d'entités qui ne sont que des sacs de propriété, il est très probable que le domaine ne soit pas assez complexe pour justifier les frais généraux de son propre modèle. À peu près tout ce que vous lirez sur DDD contiendra une clause de non-responsabilité qui n'est vraiment destinée qu'aux domaines complexes, mais cela semble trop souvent oublié.
la source
Allez à la source. Commencez avec l'article de Fowler sur les modèles de domaine anémique . Il fait référence à la conception pilotée par le domaine d'Eric Evan comme exemple de bonne pratique. Le code source pour cela est ici . Télécharge le.
Notez qu'il utilise Inversion of Control (recherchez @Autowired), et a des classes de service (BookingService) et des classes "processus métier" (par exemple ItineraryUpdater).
L'article original de Fowler ouvre la voie à l'exemple que vous recherchez.
la source
VoyageRepositoryHibernate
classe, qui a été placée dans la couche infrastructure mais dépend en fait de la couche domaine.save(foo)
un code susceptible de changer lorsque le modèle de domaine change (par exemple, si un nouvel attribut est ajouté àMyDomainObject
), il doit (par définition) appartenir à la couche domaine; sinon, vous ne pouvez plus parler d'avoir des "couches".Je suppose que vous voulez dire DI au lieu d'IoC, et le projet sur lequel vous avez travaillé utilise un conteneur DI comme Spring. IoC a deux saveurs principales: DI et modèle de localisateur. Je ne vois pas pourquoi le modèle de localisateur devrait être un problème, alors concentrons-nous sur DI.
Je ne pense pas que ce soit possible, ou du moins ce serait très impraticable. L'aspect principal des conteneurs DI est qu'ils contrôlent la création d'objets lorsqu'ils les injectent dans d'autres ("objets gérés"). L'ensemble d'objets gérés qui est vivant lorsque les projets s'exécutent est indépendant des éléments de domaine qui existent dans votre projet, mais dépend de la façon dont les objets sont câblés et des étendues (singleton, prototype) qui leur sont affectées.
C'est pourquoi vous ne voulez pas laisser le conteneur DI gérer vos objets de domaine. Mais si vous créez des objets manuellement (avec de nouveaux), vous ne pouvez pas obtenir d'autres objets injectés dans vos objets de domaine. (Laissant de côté les solutions de contournement potentielles avec un câblage manuel.) Étant donné que vous avez besoin de ces injections pour remplacer les implémentations par d'autres, vous ne pouvez pas remplacer la fonctionnalité des objets de domaine riche à l'aide de DI. Par conséquent, vous ne voudrez pas placer de fonctionnalité dans les objets de domaine, ou vous perdriez les fonctionnalités de la DI.
Je ne vois pas comment un conteneur DI hypothétique pourrait fonctionner sans gérer vos objets, et aucune des implémentations existantes ne le permet. Il est donc juste de prétendre que DI repose sur la gestion des objets. Il vous tentera donc toujours de diviser les objets Rich Domain potentiels en une classe anémique et une ou plusieurs classes de script de transaction.
la source