Question

Je viens de terminer la lecture de ce message de Greg Young, où il parle de la recommandation par Microsoft de modèles avec des objets de transfert de données stupides. Il a laissé entendre que, dans la communauté Java, les choses vont dans le sens inverse.

Ma question est la suivante: combien de logique devrait exister dans vos objets d'entité? Notre philosophie de travail (boutique C #) est que, si vous ne pouvez pas le sérialiser, ne le mettez pas dans l'entité.

Était-ce utile?

La solution

Matt,

Je dirais que votre boutique est en train d’écrire un code de procédure. Je tiens à préciser qu'il n'y a rien de mal à ce que de nombreux systèmes volumineux (y compris ceux sur lesquels j'ai travaillé) ont été écrits à l'aide d'un code de procédure. Il y a un moment et un lieu pour cela.

Le code de procédure n'a plus sa place dans un modèle de domaine. Si vous souhaitez utiliser un style plus procédural c'est très bien mais utilisez-le avec quelque chose comme un module de table ou un modèle d'enregistrement actif. Ce n’est pas le manque d’OO que je considère être si destructif dans les conseils, mais l’utilisation d’un modèle de domaine avec une logique procédurale.

Cela entraîne la dépense d'une grande quantité de ressources pour la construction de la couche de domaine (incompatibilité d'impédance, temps de réflexion pour la construction d'agrégats, isolation, langage omniprésent, etc.) sans bénéficier des avantages que la couche de domaine (en règle générale, la maintenabilité) fournir. En d’autres termes, même si vous répondez parfaitement à vos exigences fonctionnelles, vous finissez par dépenser une grande partie de votre budget sans presque aucun retour.

Maintenant, revenons à ce qu'est "le comportement". Je voudrais me concentrer sur la question d'un point de vue orienté objet par opposition à une "conception axée sur le domaine". point de vue. Un objet encapsulera généralement certains états et exposera généralement certains comportements.

répétition rapide: encapsulez l'état, exposez le comportement

Alors, quels comportements un objet devrait-il avoir? En termes simples, ce sont les comportements qui agissent sur l’état qu’il encapsule. Dans un monde OO comportemental idéal, l'État ne serait jamais exposé aux comportements d'objet uniquement. Mettez tactiquement dans le code si nous commençons à voir du code comme:

Customer c = GetCustomerFromRepository();
c.Status = CustomerStatuses.Deleted;
c.LastUpdated = DateTime.Now;
c.UpdatedBy = GetCurrentUser();
CustomerRepository.Save(c);

Nous avons une violation SRP ... Ce code est un code qui devrait être un comportement de l'objet client car l'option "Responsabilité". de l'objet client est de.

Encapsulez l’état concernant un client et exposez les comportements.

En tant que tel, nous pouvons voir qu'il serait préférable d'avoir une méthode Customer.Delete (). (oui c'est un mauvais exemple que je connais ...)

Nous y arriverions également en utilisant TDD. Il est beaucoup plus facile pour nous de faire des tests avec la couture fournie par le comportement que avec les coutures où tout l'État est exposé. La raison en est que je n'ai pas besoin de dupliquer la logique de mes tests. Le code client ne se soucie pas du fonctionnement d'une suppression ... il se soucie seulement que le client expose le comportement. En tant que tels dans nos tests au lieu d’affirmer que c.State == CustomerStates.Deleted et c.UpdatedBy == GetCurrentUser () etc etc, nous affirmerions simplement que la méthode delete a été appelée sur la couture client en utilisant un modèle.

Maintenant, revenons au titre. La quantité de logique qui devrait figurer dans un objet métier est la quantité de logique qui relève de sa responsabilité en ce qui concerne l'encapsulation de son état. Parfois c'est beaucoup, parfois ce n'est pas. Il existe des endroits où vous souhaitez également utiliser des services ... un bon exemple serait la coordination de l'interaction entre plusieurs objets de domaine pour un comportement donné, mais même dans ce cas, le service devrait appeler comportements sur les objets de domaine. .

Est-ce que cela vous aide à clarifier un peu les choses?

Greg

Autres conseils

Si vous les appelez vos "objets de modèle de domaine", alors je supposerai que vous vous référez au modèle de modèle de domaine de Fowler. http://martinfowler.com/eaaCatalog/domainModel.html

Compte tenu de cette hypothèse, la réponse à votre question est "toute la logique métier". puisque c'est essentiellement la définition du motif.

Malheureusement, le terme "modèle de domaine" semble avoir été dilué récemment pour désigner uniquement un modèle objet de vos données, sans comportement.

Si vous ne l'avez pas déjà fait, je vous encourage à lire PoEAA et à décider à quel endroit vous pensez que la logique de domaine appartient à votre situation. Si vous choisissez un modèle de domaine, je vous encourage à lire le livre DDD d'Evan et à vous familiariser avec les différences existant entre les entités, les objets de valeur et les services.

J'espère que ça aide!

Dernièrement, je me suis lancé dans l’idée de créer des modèles de domaine qui ont une structure et uniquement les comportements universels pour ce modèle (c.-à-d. des comportements pouvant être utilisés dans plusieurs contextes liés) avec des méthodes d’extension pour le comportement spécifique à un contexte borné. Cela maintient les modèles de domaine proches d'un DTO (pour ceux qui aiment ça) et limite l'utilisation de ce modèle de domaine aux seuls comportements autorisés dans un contexte limité. Cela pourrait donc être une option pour une intervention à mi-parcours. :)

Le point principal concerne la définition de la logique. Pour donner quelques exemples:

  1. Je ne catégoriserais pas une fonction getFullName () dans une entité Person, qui concaténerait simplement certaines chaînes, sous forme de logique.
  2. Le calcul d'une valeur de poste de commande est plus susceptible d'être qualifié de logique.
  3. Effectuer des transactions de réservation est sans aucun doute une logique.

Les points 1 et 2 iraient peut-être pour moi dans l’entité. Point 3 pas. Je définis donc la logique comme suit:

  • toute opération faisant quelque chose lié à la persistance (lecture / écriture)
  • toute opération impliquant toute autre entité (non directement liée, par exemple, maître-détail)

IMO, aucune de ces opérations n'appartient à une entité.

Maintenant, pourquoi / quand je ne mettrais pas aussi les opérations de type points 1 et 2 dans une entité? C'est une situation plutôt rare, mais je ne le ferais pas, dès lors que les données stockées dans l'entité doivent être interprétées d'une manière ou d'une autre avant de pouvoir être utilisées par l'application (par exemple, en fonction de l'utilisateur actuel, du contenu du champ X a une signification différente), cela signifie que les données de l'entité elle-même génèrent une certaine logique.

Pour autant que je sache, toute logique d’entreprise liée à une entité doit aller dans cette entité. Cela comprend toute logique qui définit le comportement ou la structure interne de l'entité en fonction des règles de gestion du système. Cela ne devrait pas inclure la logique de présentation ou la logique de persistance (l'exception évidente étant le modèle de conception Active Record), mais devrait inclure des éléments tels que la validation des données, les relations entre entités, les machines à états et d'autres éléments définissant le comportement réel de l'entité. chose du monde qu’il essaie de modéliser.

Ce que j’essaie de voir, c’est d’essayer de rendre mes modèles aussi résistants que possible. Essayez toujours de penser à la manière dont le modèle serait utilisé s’il devait être transféré vers un autre système où le code client (ou le code utilisant l’entité) pourrait être différent. Si la fonctionnalité ne fait pas partie de l'entité, se comportera-t-elle toujours de la même manière en suivant les mêmes règles commerciales? Si la réponse est non, la fonctionnalité doit alors figurer dans l'entité.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top