Tenemos una dependencia a un servicio de terceros que expone una interfaz gigantesca de la que solo necesitamos como 3 métodos. Además, la interfaz cambia con frecuencia ...
He decidido incluir la interfaz en una clase en nuestro proyecto y solo exponer los métodos que necesitamos.
Pero no estoy seguro de cómo debo manejar los valores de retorno ... La interfaz devuelve un objeto de tipo Storage
. Internamente tenemos un tipo StorageModel
que es nuestra representación interna de a Storage
.
¿Qué devolverías en el mapeador: Storage
o StorageModel
? Tenemos un DataService StorageService
que obtiene una dependencia del contenedor inyectado.
Actualmente lo estoy haciendo básicamente así:
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);
}
}
}
Qué dirías:
- ¿Es bueno como el anterior, que el contenedor devuelve el
Storage
objeto externo y el internoStorageService
devuelve el internoStorageModel
? - ¿O ya devolverías un
StorageModel
envoltorio?
Respuestas:
En mi opinión, el contenedor debe tratar con todas las cosas relacionadas con la biblioteca externa. Esto significa que la interfaz pública del Wrapper no debe nombrar ningún tipo externo.
La asignación de tipos externos a los tipos respectivos de su aplicación es parte de las tareas del contenedor. Si no se trata de una operación trivial, puede utilizar las diversas herramientas disponibles para descomponer el problema, por ejemplo, inyectar un objeto traductor. Sin embargo, el traductor aún debe ser parte de su módulo contenedor y ninguna otra parte de su aplicación puede depender de él.
De esta manera, el resto de su aplicación es completamente inmune no solo a los cambios en la biblioteca, sino también a los reemplazos de la biblioteca por otro.
fuente
Está bien. Esto también se conoce como Adaptador .
Usted elige el patrón Adaptador , por lo que el objetivo aquí es transformar una interfaz (modelo de biblioteca) en otra (modelo de dominio). Entonces, si algo del primero alcanza el modelo de dominio, el adaptador está fallando en su propósito .
Según los argumentos anteriores, el adaptador debe devolver el
StorageModel
.En última instancia, su dominio "habla" un idioma específico, donde
Storage
es un extraño .La clave aquí es saber por qué razón está envolviendo / adaptando la biblioteca .
Los patrones de Adaptador, Decorador, Fachada pueden tener similitudes, pero son bastante diferentes. Tan diferentes como los problemas que resuelven.
Dicho esto, es posible que también te interese:
Patrón de fachada (complejidad de ocultación)
Patrón de decorador (mejora de la interfaz) . Cuando usarlo
Diferencias entre el patrón adaptador y el patrón proxy .
¿Qué es una capa anti-corrupción y cómo se utiliza (ocultando baja calidad y código desordenado)
fuente
No puede envolver una biblioteca de manera efectiva al duplicarla.
Lo que debe envolver es su uso de la biblioteca y eso significa no exponer sus objetos, en este caso Almacenamiento. No intentes duplicarlos tampoco.
Use la biblioteca, pero manténgala contenida. Entonces, en su caso, suponiendo que esté utilizando StorageService para almacenar cosas, debe envolverlo en repositorios
donde MyPocoObject es completamente su lógica de datos y negocios. No es una duplicación de almacenamiento o un DataReader ni nada
fuente
La respuesta es que depende de si alguna vez necesita acceder
Storage
directamente desde una clase que no lo esStorageModel
.Si va a ajustar la biblioteca, tiene sentido también ajustar el objeto devuelto por ella para permitirle realizar pruebas futuras de los cambios realizados por la biblioteca en el futuro. Sin embargo, si alguna vez necesita usar
Storage
directamente, significa que puede ser necesario regresar deStorage
acuerdo con la situación. Podría argumentarse que obligar a que elStorage
uso aquí seaStorageModel
como es probable que desee permanecer constante en todo su programa.Recomiendo encarecidamente que ajuste la interfaz y el objeto devuelto si aún no lo está haciendo, aunque de nuevo, eso solo tiene sentido si solo está usando
StorageModel
todo su programa y noStorage
.fuente