Modèles de domaine anémique et injection de services de domaine

19

Le modèle de domaine anémique est décrit comme un anti-modèle dans la conception pilotée par domaine par Martin Fowler. Pour avoir une logique métier sur les modèles de domaine, des services de domaine sont souvent utilisés. Mais l'injection de services de domaine dans des modèles de domaine est considérée comme nuisible par Vaughn Vernon (voir «Implémentation d'une conception pilotée par domaine, Page 387).

À mon avis, ces opinions sont contradictoires, est-ce vrai? Comment considérer les deux points?

Est-ce un modèle de domaine vraiment riche avec des services de domaine injectés par rapport au modèle de domaine anémique et aux services de domaine normaux ?

Sjoerd222888
la source
4
Je ne suis nullement un expert en la matière, mais je pensais que le type de logique qui allait dans les services de domaine et dans les entités de domaine était fondamentalement différent. La logique qui entre dans les entités est la logique nécessaire pour maintenir l'objet dans un état correct. Cela implique une logique de validation et de transformation. Les services de domaine, en revanche, sont destinés à une logique de niveau supérieur. Ainsi, par exemple, un service de domaine modéliserait un processus métier impliquant plusieurs types d'entités différents de manière complexe.
MetaFight
2
@MetaFight: même si un processus métier affecte plusieurs entités de manière complexe, vous pouvez y parvenir sans services étant donné un bon modèle de domaine racine agrégée, c'est-à-dire un modèle de domaine qui a accès à toutes les entités affectées en tant que propriétés ou champs sur lui-même.
Greg Burghardt
Cela a du sens :)
MetaFight

Réponses:

16

Un modèle anémique est simplement un conteneur de données. Il ne contient pas de comportement. (Cela pourrait en fait être considéré comme une bonne chose dans le paradigme fonctionnel.) Le contraire d'un modèle anémique n'est pas un modèle injecté plein de services de domaine. Vous décrivez deux extrêmes - les deux sont mauvais.

Si vous avez un modèle anémique, vous n'acceptez pas pleinement ce que propose la POO. Si vous commencez à injecter des services dans ces modèles, vous injectez probablement des préoccupations qui n'y appartiennent pas. Soit cela, soit votre modèle est plus anémique que vous ne le pensez. Sinon, pourquoi auriez-vous besoin du service autre qu'il fournit quelque chose qui est requis mais manquant? (Manquer pourrait signifier anémique.)

Éviter les deux «raconte» conduit à une conception plus solide. Avez-vous quelque chose dans un service dont un modèle a besoin? Il faudrait peut-être le déplacer vers le modèle. Sinon, vous devriez peut-être reconsidérer vos préoccupations. Le comportement d'un modèle doit fonctionner à l' intérieur du modèle. Il devrait principalement (sinon seulement) se préoccuper des membres. Mais rappelez-vous, il y aura toujours des choses qui fonctionnent sur ou avec le modèle. Par exemple, les modèles ne devraient pas ouvrir de connexions TCP ni écouter les événements d'interface utilisateur, même s'ils sont en quelque sorte impliqués. C'est quelqu'un d'autre la responsabilité et que quelqu'un appartient jamais à l' intérieur du modèle.

Scant Roger
la source
7
Une bonne distinction dont je me souviens est que votre modèle de domaine implémente la logique métier et que vos services de domaine exécutent la logique métier sur les modèles de domaine. La différence est qui appelle qui. Les services peuvent appeler des méthodes de modèle de domaine. Si les modèles de domaine appellent des méthodes de service, vous avez inversé le modèle au-dessus de sa tête.
Greg Burghardt
7

Ce n'est pas contradictoire. Les deux promoteurs aimeraient que vous mettiez votre code réel dans l'objet de domaine lui-même.

c'est à dire.

public class Order
{
    private string status = "not bought";
    public void Buy()
    {
        this.status = "bought";
    }
}

vs ADM

public class Order
{
    public string Status = "not bought";
}

public class BuyingService
{
    public Order Buy(Order order)
    {
         Order o = new Order();
         o.status = "bought";
         return o;
    }
}

vs services injectés

public class Order
{
    public Order(IBuyingService bs)
    {
        _bs = bs;
    }
    private IbuyingService _bs;
    private string status = "not bought";
    public void Buy()
    {
        this.status = _bs.Buy();
    }
}

public class BuyingService : IBuyingService
{
    public string Buy()
    {
         return = "bought";
    }
}

Franchement, chaque approche a ses avantages et ses inconvénients. Celui que vous choisissez est en grande partie une question de préférence personnelle

Ewan
la source