2011-08-10 2 views
1

Je travaille sur une application où nous essayons d'utiliser un modèle de domaine. L'idée est de conserver la logique métier dans les objets du modèle de domaine. Les objets qui s'abonnent à des objets associés ont maintenant beaucoup à faire pour réagir aux changements qui les affectent. Ceci est fait par PropertyChanged et CollectionChanged. Ce travail fonctionne correctement, sauf dans les cas suivants:un modèle de domaine doit-il rester cohérent à l'aide d'événements?

Actions complexes: lorsqu'un grand nombre de modifications doivent être traitées en tant que groupe (et non des modifications de propriété/de collection individuelles). Devrais-je/comment puis-je «construire» des transactions? Persistance: J'utilise NHibernate pour la persistance et cela utilise aussi les setters de propriétés publiques des classes. Lorsque NHibernate atteint la propriété, une grande partie de la logique métier est effectuée (ce qui semble inutile). Dois-je utiliser des setters personnalisés pour NHibernate? En général, il semble que pousser toute la logique dans le modèle de domaine rend le modèle de domaine plutôt complexe. Des idées???

est ici un problème « échantillon » (désolé pour l'outillage merdique je l'utilise):

enter image description here

Vous pouvez voir le projet de mon conteneur et les objets au-dessous réagissent les uns aux autres en vous inscrivant. Maintenant, les modifications apportées au réseau sont effectuées via NetworkEditor mais cet éditeur n'a aucune connaissance de NetworkData. Ces données peuvent même être définies dans un autre assembly parfois. Le flux va de user-> NetworkEditor-> Network-> NetworkData et tous les autres objets intéressés. Cela ne semble pas à l'échelle.

Répondre

2

Je crains que la combinaison d'événements DDD et PropertyChanged/CollactionChanged soit maintenant la meilleure idée. Le problème est que si vous basez votre logique autour de ces événements, il est extrêmement difficile de gérer la complexité car un PropertyChanged conduit à un autre et à un autre et bientôt vous perdez le contrôle.

Une autre raison pour laquelle les événements ProportyChanged et DDD ne correspondent pas exactement est que dans DDD, chaque opération métier doit être aussi explicite que possible. Gardez à l'esprit que DDD est censé apporter des éléments techniques dans le monde des affaires, et non l'inverse. Et basé sur le PropertyChanged/CollectionChanged ne semble pas très explicite. Dans DDD, l'objectif principal est de conserver la cohérence dans l'agrégat. En d'autres termes, vous devez modéliser l'agrégat de telle sorte que toute opération que vous appelez l'agrégat soit valide et cohérente (si l'opération réussit bien sûr).

Si vous construisez correctement votre modèle, vous n'avez pas besoin de vous soucier de «construire» une transaction - une opération sur l'agrégat devrait être une transaction elle-même. Je ne sais pas à quoi ressemble votre modèle, mais vous pouvez envisager de déplacer les responsabilités d'un niveau vers le haut dans l'arborescence agrégée, en ajoutant éventuellement des entités logiques supplémentaires au processus, au lieu de s'appuyer sur les événements PropertyChanged.

Exemple:

laisse supposer que vous avez une collection de paiements avec des statuts et à chaque changement de paiement, vous voulez recalculer le solde total des commandes clients.Au lieu de souscrire des modifications à la collecte des paiements et appeler une méthode sur le client lors de la collecte des changements, vous pourriez faire quelque chose comme ceci:

public class CustomerOrder 
    { 
     public List<Payment> Payments { get; } 
     public Balance BalanceForOrder { get; } 

     public void SetPaymentAsReceived(Guid paymentId) 
     { 
      Payments.First(p => p.PaymentId == paymentId).Status = PaymentStatus.Received; 
      RecalculateBalance(); 
     } 
    } 

Vous avez sans doute remarqué, que nous recalcule l'équilibre de l'ordre unique et non l'équilibre des le client entier - et dans la plupart des cas, cela est acceptable car le client appartient à un autre agrégat et son solde peut être simplement interrogé en cas de besoin. C'est exactement la partie qui montre cette chose «cohérence uniquement dans l'agrégat» - nous ne nous soucions pas de tout autre agrégat à ce stade, nous ne traitons que de l'ordre unique. Si ce n'est pas le cas pour les exigences, le domaine est mal modélisé. Ce que je veux dire, c'est que dans DDD, il n'y a pas de bon modèle unique pour chaque scénario - vous devez comprendre comment l'entreprise fonctionne pour réussir. Si vous regardez l'exemple ci-dessus, vous verrez qu'il n'est pas nécessaire de 'construire' la transaction - la transaction entière est située dans la méthode SetPaymentAsReceived. Dans la plupart des cas, une action de l'utilisateur doit conduire à une méthode particulière sur une entité avec agrégat - cette méthode concerne explicitement le fonctionnement de l'entreprise (bien sûr, cette méthode peut appeler d'autres méthodes). En ce qui concerne les événements dans DDD, il existe un concept d'événements de domaine, mais ceux-ci ne sont pas directement liés aux événements techniques PropertyChanged/CollectionChanged. Les événements de domaine indiquent les opérations commerciales (transactions) complétées par un agrégat.

Overal il semble que pousser toute logique dans le modèle de domaine fait le modèle de domaine assez complexe

Bien sûr, il fait comme il est censé être utilisé pour les scénarios avec une logique métier complexe. Cependant, si le domaine est modélisé correctement, il est facile de gérer et de contrôler cette complexité et c'est l'un des avantages de DDD.

Ajouté après avoir fourni exemple:

Ok, et ce sur la création d'une racine globale appelée projet - lorsque vous créez racine globale à partir du référentiel, vous pouvez le remplir avec NetworkData et l'opération pourrait ressembler à ceci:

NetworkEditor ne fonctionnerait pas directement sur le réseau, mais plutôt via Project en utilisant NetworkId.

+0

Spot sur. Les entités DDD peuvent légitimement signaler les changements de propriété et de collection, mais seulement pour les observateurs extérieurs comme le code de présentation - jamais dans le but de la logique de domaine. – jnm2

Questions connexes