L'utilisation d'interfaces individuelles avec les entités de domaine est-elle une bonne ou une mauvaise pratique? Pourquoi?

StackOverflow https://stackoverflow.com/questions/825919

Question

Certaines applications d'entreprise DDD sur lesquelles je travaille ont notamment recours à des interfaces identiques aux entités de domaine, avec un mappage un à un des propriétés et des fonctions. En effet, un objet de domaine est toujours utilisé via son interface un-à-un, et toutes les entités de domaine ont une interface un-à-un dans ce style.

Par exemple:

Compte d'objet de domaine:

public class Account : IAccount
{
     public string Name {get;set;}
     //...some more fields that are also in IAccount
     public decimal Balance {get;set;}
}

Et c'est l'interface correspondante

public interface IAccount
{
   string Name {get;set;}
   //... all the fields in Account
   decimal Balance {get;set;}
}

Mais ces derniers temps, je suis de plus en plus convaincu que c’est en fait un anti-modèle.
Je l'ai dirigé par des architectes de la communauté open source, et ils disent que cela est basé sur des erreurs ou des défauts de conception, quelque part dans la chaîne de conception.

Je dis donc à mes collègues de cesser de créer des interfaces pour les objets de domaine. Parce qu'ils ne servent à rien et que vous devez mettre à jour l'interface chaque fois que vous mettez à jour les entités de domaine.

Tout d'abord, il a été affirmé que ces interfaces fournissaient un "découplage", mais je pense que, parce que les interfaces ont une relation un-à-un avec les entités de domaine, elles ne fournissent pas vraiment de découplage, mais une modification des moyens d'interface. un changement dans l'entité du domaine et vice-versa.

La revendication suivante est que nous avons besoin d’interfaces à des fins de test. Mon contre est que Rhino-mock assure le moquage et l’abaissement de classes concrètes. Mais ils prétendent que Rhino-mock a des problèmes avec les classes concrètes. Je ne sais pas si j'achète cela, même si rhino-mock a des problèmes avec des classes concrètes, cela ne signifie pas nécessairement que nous devrions utiliser des interfaces pour les entités de domaine.

Alors je suis curieux:

Pourquoi voudriez-vous des interfaces un-à-un pour vos entités de domaine?

Pourquoi pas?

Pourquoi est-ce une bonne ou une mauvaise pratique?

Merci d'avoir lu!

MODIFIER : je dois noter que j'utilise les interfaces tout le temps, et je pense que s'il le faut, j'utiliserai une interface en un rien de temps. Mais je fais spécifiquement référence aux entités de domaine avec des interfaces un-à-un.

Était-ce utile?

La solution

C'est une mauvaise pratique telle que décrite, mais ...

Il n'y a pas de raison particulière pour que vos interfaces doivent être différentes de vos entités de domaine; Parfois, c'est vraiment la bonne cartographie. Mais il est suspect que ce soit toujours le cas. Le problème est de savoir si les interfaces ont vraiment été conçues ou si elles ont été simplement mises en place par manque de temps / paresse.

Pour utiliser votre exemple, l'interface IAccount que vous décrivez expose les getters et les setters sur l'objet Account; il semble un peu étrange et peu probable que tout ce qui utilise un compte ait besoin de définir le solde du compte et que cette autorisation implicite soit spécifiée à ce niveau d'interface. N'y a-t-il pas d'endroit dans votre système où vous voulez simplement vérifier sans régler le solde du compte?

Autres conseils

La principale raison pour toujours spécifier les objets de domaine comme interfaces plutôt que directement comme classes est de vous donner un degré de liberté quant à la mise en œuvre. Dans votre exemple, vous n’avez qu’un seul type de compte IA, c’est donc un peu redondant.

Mais si vous aviez, par exemple:

public class Account : IAccount { ... }       // Usual account, persistent
public class MockAccount : IAccount { ... }   // Test mock object
public class TransAccount : IAccount { ... }  // Account, not persistent
public class SimAccount : IAccount { ... }    // Account in a performance sim

et ainsi de suite?

En définissant les objets de domaine en tant qu'interfaces, vous pouvez remplacer les implémentations sans perturber la définition de votre domaine.

En général, si mes classes ne font pas partie d'un modèle de conception tel que Stratégie ou Visiteur, je n'ajoute pas d'interface.

L'ajout d'interfaces est très utile pour les modèles de conception tels que Strategy et Visitor, mais dans ce cas, je ne copie pas en carbone les accesseurs et les régleurs des classes de domaine. Au lieu de cela, je crée des interfaces spécifiques aux interfaces de modèle de conception que je crée.

interface SomeStrategy {
   void doSomething(StrategyData data);
}

interface StrategyData {
   String getProperty1();

   String getProperty2();
} 

Cela me permet de laisser les classes de domaine implémenter ces interfaces ou d'utiliser le modèle Adapter. Je trouve que c’est une approche beaucoup plus propre qui ne fait que créer des interfaces pour le plaisir de le faire.

La conception doit toujours réduire les incertitudes. Créer des interfaces pour le plaisir ne réduit pas l'incertitude, en fait, cela augmente probablement la confusion, car cela n'a aucun sens.

Les interfaces un-à-un sur les entités sont un anti-motif

James Gregory l'a dit mieux que moi ici .

Je suis d'accord avec vous. Les interfaces doivent agir en tant que contrat. Il est donc inutile de disposer d'interfaces un-à-un avec des entités de domaine. Cela peut être utile si vous souhaitez abstraire un certain comportement. Mais cela fonctionnera dans certains cas.

Pourquoi celui-ci a-t-il échoué?

Je trouve qu'avoir une interface pour un objet de domaine, comme l'a dit Charlie Martin, me permet de choisir mon implémentation.

Un exemple fondamental est l'identifiant (object.Id) d'un objet. Il sera différent selon le lieu où vous stockez cet objet et la responsabilité de le créer peut reposer ou non sur l'implémentation des données ultérieurement. Dans SQL Server, vous pouvez rechercher un numéro automatique, mais dans Azure, vous pouvez choisir un GUID, mais vous ne souhaitez pas modifier la logique commerciale de votre application, car vous modifiez l'emplacement de stockage de vos données.

Je peux choisir de ne pas conserver mon objet de domaine, voire de l’utiliser dans la couche de présentation - cela dépend de la portée de mon application, qui est la meilleure. Mais l’ajout d’un ensemble d’interfaces de domaine commun dans une couche commune me permet d’écrire des services et de les réutiliser plusieurs fois.

Nous reprendrions le même argument à propos de ce qui devrait être une adresse si nous n'avions pas reçu IAddress, les nouveaux programmeurs réécriraient les éléments pour les cartes de crédit sans la carte ICreditCard.

Le label anti-modèle est un mauvais usage du langage, c'est une simplification excessive pour décrire la valeur des solutions à des tâches complexes et variées.

Il y a une place pour la plupart des modèles, même le Singleton maligné, ce qui signifie que ce n'est pas un "anti-modèle", du moins dans la mesure suggérée par le terme.

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