Nous sommes dépendants d'un service tiers qui expose une interface gigantesque dont nous n'avons besoin que de 3 méthodes. De plus, l'interface change fréquemment ...
J'ai décidé d'envelopper l'interface dans une classe de notre projet et d'exposer uniquement les méthodes dont nous avons besoin.
Mais je ne sais pas comment je dois gérer les valeurs de retour ... L'interface renvoie un objet de type Storage
. Nous avons en interne un type StorageModel
qui est notre représentation interne d'un Storage
.
Que voudriez-vous retourner dans le mappeur: Storage
ou StorageModel
? Nous avons un DataService StorageService
qui obtient une dépendance du wrapper injecté.
Actuellement, je le fais essentiellement comme ceci:
public class StorageService
{
private readonly IExternalStorageWrapper externalStorageWrapper;
public StorageService(IExternalStorageWrapper externalStorageWrapper)
{
this.externalStorageWrapper = externalStorageWrapper;
}
public StorageModel GetStorage(int storageId)
{
return this.externalStorageWrapper.GetStorage(storageId).ConvertToStorageModel();
}
}
public class ExternalStorageWrapper : IExternalStorageWrapper
{
public Storage GetStorage(int storageId)
{
using(var ext = new ExternalStorage())
{
return ext.GetStorage(storageId);
}
}
}
Que dirais-tu:
- Est-ce bien comme ci-dessus, que le wrapper retourne l'
Storage
objet externe et que le interneStorageService
renvoie le interneStorageModel
? - Ou retourneriez-vous déjà un
StorageModel
dans l'emballage?
Réponses:
À mon avis, le wrapper devrait traiter de tout ce qui concerne la bibliothèque externe. Cela signifie que l'interface publique du wrapper ne doit nommer aucun type externe.
Le mappage de types externes aux types respectifs de votre application fait partie des fonctions de l'encapsuleur. Si ce n'est pas une opération banale, vous pouvez utiliser les différents outils disponibles pour décomposer le problème, par exemple en injectant un objet traducteur. Cependant, le traducteur doit toujours faire partie de votre module wrapper et aucune autre partie de votre application ne peut en dépendre.
De cette façon, le reste de votre application est complètement immunisé non seulement aux changements dans la bibliothèque, mais aussi aux remplacements de la bibliothèque pour une autre.
la source
C'est bon. Ceci est également appelé adaptateur .
Vous choisissez le modèle d' adaptateur , donc l'objectif ici est de transformer une interface (modèle de bibliothèque) en une autre (modèle de domaine). Donc, si quelque chose de l'ancien atteint le modèle de domaine, l'adaptateur ne parvient pas à son objectif .
Selon les arguments précédents, l'adaptateur doit renvoyer le
StorageModel
.En fin de compte, votre domaine "parle" une langue spécifique, où
Storage
est un étranger .La clé ici est de savoir pour quelle raison vous enveloppez / adaptez la bibliothèque .
Les modèles d'adaptateur, de décorateur et de façade peuvent avoir des similitudes, mais ils sont assez différents. Aussi différents que les problèmes qu'ils résolvent.
Cela dit, vous pourriez également être intéressé par:
Motif de façade (cachant la complexité)
Motif décorateur (amélioration de l'interface) . Quand l'utiliser
Différences entre le modèle d'adaptateur et le modèle de proxy .
Qu'est-ce qu'une couche anti-corruption et comment elle est utilisée (masquage de code de mauvaise qualité et désordonné)
la source
Vous ne pouvez pas envelopper efficacement une bibliothèque en la dupliquant.
Ce que vous devez envelopper est votre utilisation de la bibliothèque et cela signifie ne pas l'exposer aux objets, dans ce cas, le stockage. N'essayez pas non plus de les dupliquer.
Utilisez la bibliothèque, mais gardez-la contenue. Donc, dans votre cas, en supposant que vous utilisez le StorageService pour stocker des choses, vous devez l'envelopper dans des référentiels
où MyPocoObject est entièrement vos données et votre logique métier. Pas une duplication du stockage ou d'un DataReader ou quoi que ce soit
la source
La réponse est que cela dépend si vous avez ou non besoin d'accéder
Storage
directement à partir d'une classe qui ne l'est pasStorageModel
.Si vous allez encapsuler la bibliothèque, il est logique d'envelopper également l'objet renvoyé par celle-ci pour vous permettre de modifier à l'avenir les modifications apportées par la bibliothèque à l'avenir. Cependant, si vous devez utiliser
Storage
directement, cela signifie qu'il peut être nécessaire de revenir enStorage
fonction de la situation. Un argument pourrait être invoqué pour obliger l'Storage
utilisation ici à êtreStorageModel
telle que vous voulez probablement rester cohérente tout au long de votre programme.Je vous recommande fortement d'envelopper à la fois l'interface et l'objet retourné si vous ne le faites pas déjà, mais là encore, cela n'a de sens que si vous utilisez uniquement
StorageModel
tout au long de votre programme et nonStorage
.la source