Ostatnio pracuję nad aplikacją, która udostępnia poprzez WebService dane dla stronki napisanej w AngularJS. Architektura jest 3-warstwowa (WS -> Service -> DAO).
Używam frameworków Jersey oraz Spring, a zapytania są w napisane w czystym JDBC + JdbcTemplate.
Mam stworzone encje, które są dokładnym odwzorowaniem struktury bazy danych, oraz kilka metod w DAO (np. findById, findByCriteria) więc mogę już wystawić prostą ewidencję klientów na świat poprzez API, np. "/api/customer/", czy "/api/customer/1/".
Wszystko jest fajnie do momentu, gdy użytkownik będzie chciał na widoku widzieć coś więcej...
Tutaj pojawia problem i pytania. W której warstwie powinienem łączyć encje - DAO czy Service? Czy do każdego widoku tworzyć nowe struktury danych? Czy do każdego widoku tworzyć nowe metody w DAO?
Załóżmy, że mam klasy: Klient, Zamówienie, Produkt oraz widoki:
a) Zwykła lista klientów z domyślnym adresem zamieszkania,
b) Lista klientów, numer i data ostatniego zamówienia, liczba wszystkich zamówień w ciągu ostatniego miesiąca,
c) Lista zamówień, do każdego z nich lista produktów oraz do każdego produktu flaga, czy zamawiający kupował ten produkt już wcześniej (jeśli tak to data i numer tego zamówienia)
Jak widać - większość danych z encji będzie się powtarzać, jedynie dochodzi jedno lub dwa dodatkowe pola.
Rozważałem kilka podejść, każde ma swoje wady i zalety:
- dodać brakujące pola do istniejących klas: raczej odpada, po kilku zmianach na widokach tych dodatkowych pól może być więcej, niektóre niepowiązane bezpośrednio,
- dodać nową klasę i metodę w DAO, która pobiera dane dla wybranego widoku. Z jednej strony okej, bo pobieram tylko niezbędne dane, a z drugiej warstwa DAO nie powinna być zależna od warstwy wyższej.
- w warstwie Service pobrać dane za pomocą istniejących metod i spróbować je łączyć ze sobą. Wydaje się najbardziej czytelne rozwiązanie - w końcu widok zależy trochę od logiki biznesowej :).
Najpierw pobrałbym listę klientów, a później dla każdego z nich ostatnie zamówienie (problem 1 + n). Alternatywnie pobrać ostatnie zamówienia wg listy klientów. Natomiast nie będzie to tak wydajne jak zwykły JOIN bezpośrednio w zapytaniu... Dla widoku z punktu c) i tak musiałbym utworzyć specjalne metody w DAO.
Macie jakiś sprawdzone rozwiązania dla tego typu problemów?