W jednej z moich bieżących aplikacji potrzebuję uzyskać dane klienta ze zdalnej usługi (CRM) za pośrednictwem usługi Webservice/SOAP. Ale chcę również buforować dane w bazie danych mysql, więc nie będę musiał łączyć się z serwisem internetowym po raz kolejny (dane nie zmieniają się często, usługa zdalna jest wolna i ma limit przepustowości - więc buforowanie jest w porządku/musi).Uzyskiwanie danych z usługi zdalnej, jeśli nie jest ona zapisana w pamięci podręcznej w bazie danych - potrzebna sugestia
Jestem dość pewien technicznej części tego zadania, ale nie jestem pewien, jak zaimplementować to czyste i przejrzyste w mojej aplikacji internetowej.
Wszystkie moje pozostałe dane pochodzą z jednej bazy danych mysql, więc mam repozytoria, które zwracają listy lub pojedyncze jednostki zapytane z bazy danych za pomocą NHibernate.
Moje pomysły do tej pory:
1 Wszystko w jednym
Użyj CustomerRepository, która wygląda dla klienta przez ID, czy udany, a następnie odesłać go, jeszcze wywołać usługa i zapisz pobrane dane do bazy danych.
Kontroler wygląda następująco:
class Controller
{
private CustomerRepository Rep;
public ActionResult SomeAction(int id)
{
return Json(Rep.GetCustomerById(id));
}
}
Repository w pseudo/prosty kod tak:
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;
}
}
Chociaż powyższe wygląda nieco proste, myślę, że klasa CustomerRepository wzrośnie dość duży i brzydki . Więc nie podoba mi się to podejście.
Repozytorium powinno ładować tylko dane z bazy danych, co powinno być jego "kontraktem" przynajmniej w mojej aplikacji.
2 sepereate i naklejane razem w kontrolerze
użyć klas oddzielne dla repozytorium (dostęp db) i usługa (zdalny dostęp) i niech kontroler do pracy:
Controller wygląda tak:
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);
}
}
Chociaż wygląda to nieco lepiej, nadal nie lubię wstawiać wszystkich logi c w kontrolerze, ponieważ obsługa błędów, gdy usługa nie zwraca danych, jest pomijana i prawdopodobnie może zająć trochę więcej rzeczy.
Może mógłbym utworzyć kolejną warstwę usługi używaną przez kontroler, ale kod byłby zupełnie taki sam, ale w innej klasie.
Właściwie chciałbym, aby mój kontroler używał pojedynczego interfejsu/klasy, który hermetyzuje te rzeczy, ale nie chcę jednej klasy, która "robi to wszystko": dostępu do repozytorium, dostępu do usługi sieciowej, zapisywania danych. . czuje się trochę źle do mnie ...
Wszystkie pomysły do tej pory są/będą prawdopodobnie się dość wleczenia z kodem buforowania, obsługi błędów itp myślę.
Może mógłbym posprzątać kilka rzeczy za pomocą AOP?
W jaki sposób jesteś zaimplementować rzeczy takie jak powyżej?
Zastosowane struktury techniczne: ASP.NET MVC, Spring.NET dla DI, NHibernate jako ORM, mysql jako baza danych, usługa zdalna jest dostępna za pośrednictwem protokołu SOAP.
Ooh, podoba mi się twoja odpowiedź nawet bardziej niż moja! Miły. –
to naprawdę interesujące podejście. – Max
@Max: Decorator to wzór, który widzi wiele zastosowań w DI - między innymi w scenariuszach dokładnie takich jak ten :) –