En una de mis aplicaciones actuales, necesito obtener datos del cliente de un servicio remoto (CRM) a través del servicio web/SOAP. Pero también quiero almacenar en caché los datos en la base de datos mysql, de modo que no necesito conectarme al servicio web para la próxima vez (los datos no cambian a menudo, el servicio remoto es lento y tiene un límite de ancho de banda, entonces el almacenamiento en caché es correcto/a debe)Obtención de datos del servicio remoto si no se almacena en la base de datos en caché - sugerencia necesaria
Estoy bastante seguro acerca de la parte técnica de esta tarea, pero no estoy tan seguro de cómo implementar esta aplicación limpia y transparente en mi aplicación web.
Todos mis otros datos provienen de una sola base de datos mysql, así que los repositorios que devuelven listas o entidades individuales son consultadas desde la base de datos con NHibernate.
Mis ideas hasta ahora:
1, todo en un
Utilice un CustomerRepository, lo que busca el cliente mediante la identificación, si es exitosa, después lo devuelve, de lo contrario llamar al servicio web y guardar los datos recuperados en la base de datos.
controlador se ve así:
class Controller
{
private CustomerRepository Rep;
public ActionResult SomeAction(int id)
{
return Json(Rep.GetCustomerById(id));
}
}
Repositorio de seudo/código simple como esto:
class CustomerRepository
{
public Customer GetCustomerById(int id)
{
var cached = Database.FindByPK(id);
if(cached != null) return cached;
var webserviceData = Webservice.GetData(id);
var customer = ConvertDataToCustomer(webserviceData);
SaveCustomer(customer);
return customer;
}
}
Aunque lo anterior parece algo sencillo, creo que la clase CustomerRepository crecerá bastante grande y fea . Así que no me gusta ese enfoque en absoluto.
Un repositorio solo debe cargar datos de la base de datos, que debe ser su "contrato" en mi aplicación al menos.
2 sepereate y pegado juntos en el controlador
Use clases separadas para el repositorio (acceso db) y el servicio web (acceso remoto) y dejar que el controlador de hacer el trabajo:
Controlador se ve así:
class Controller
{
private CustomerRepository Rep;
private Webservice Service;
public ActionResult SomeAction(int id)
{
var customer = Rep.GetCustomerById(id);
if(customer != null) return Json(customer);
var remote = Service.GetCustomerById(id);
Rep.SaveCustomer(remote);
return Json(remote);
}
}
Aunque esto se ve un poco mejor, todavía no me gusta poner todo lo logi c en el controlador, porque se omite el manejo de errores si el servicio no devuelve datos y probablemente podría complicar un poco más las cosas.
Tal vez podría hacer otra capa de servicio utilizada por el Controlador, pero el código sería bastante similar, pero en otra clase.
En realidad, me gustaría que mi Controlador use una única Interfaz/Clase, que encapsula esas cosas, pero no quiero una clase que "lo haga todo": acceder al repositorio, acceder al servicio web, guardar los datos ... . se siente un poco mal a mí ...
Todas las ideas hasta ahora son/probablemente llegar a ser bastante hinchado con código de almacenamiento en caché, control de errores, etc. Creo.
Tal vez podría limpiar algunas cosas usando AOP?
¿Cómo sería implementar cosas como las de arriba?
Marcos técnicos utilizados: ASP.NET MVC, Spring.NET para DI, NHibernate como ORM, mysql como base de datos, se accede al servicio remoto a través de SOAP.
¡Oh, me gusta tu respuesta incluso más que la mía! Bonito. –
ahora que es de hecho un enfoque interesante – Max
@Max: Decorator es un patrón que tiene un gran uso en DI, entre otras cosas en escenarios exactamente como este :) –