Generyczne repozytorium - używać?

0

Przerabiam tutorial z Pluralsight, w którym autor całkowicie oddziela warstwę dostępu do bazy od kontrolerów (tzn. kontrolery nie wiedzą nic o EF, mają wstrzykniętą implementację interfejsu UoW, która ma wstrzyknięte implementacje repozytorów). Aplikacja nie jest bardzo prostym CRUDem, w wielu miejscach trzeba filtrować dane, więc wydaje mi się, że te repozytoria mają sens. Działają one jak kolekcje, tzn. mają szereg metod zwracających encję lub kolekcję encji. Wszystko to po to, by umożliwić w razie potrzeby szybką zmianę EF na np. NHibernate (czy tak w firmach pisze się aplikacje, czy może zakłada się z góry, że np. tylko NHibernate będzie używany?). Tylko że to znowu oznacza, że w kontrolerach nie mogę korzystać jawnie z ORMa, a metody dodające, usuwające encje itd. muszą być w repozytoriach. Na YouTubie ten sam autor przedstawia, jak napisać generyczne repozytorium. Tylko że dziedziczenie z tego repozytorium nie zawsze ma sens, np. gdy mam encję, której klucz jest złożony z dwóch wartości. Ponadto niektóre metody, jak np. GetAll, mają sens tylko dla kilku encji. I co w takiej sytuacji zrobić?

2

Najlepiej zacząć od tego tematu: Wzorzec repozytorium.

IMO: Najlepiej zostawić ten wzorzec w spokoju. No chyba że coś tam rzeźbisz w DDD, ale wtedy to repozytorium nie wygląda tak jak na załączonym jutjubie

0

Ok, nie sądziłem, że jest to aż taki antywzorzec w aplikacjach bez DDD. Argumenty o trudności w utrzymaniu i małej powtarzalności zapytań przekonały mnie.

0

Co to znaczy bez DDD?

Bez albo z REST?

Z SOA albo bez?

Moim zdanie możesz, używać Repository w projekcie, który idzie w parze z praktykami, wzorcami oferowanymi przez DDD.

Możesz również używać Repository do pobieranie obiektów domenowych, które niekoniecznie idą w parze z DDD. Chociaż trudno zaprzeczyć większości praktyk związanych z DDD, ponieważ większość to po prostu dobre praktyki projektowania OOP.

4
nobody01 napisał(a):

Przerabiam tutorial z Pluralsight, w którym autor całkowicie oddziela warstwę dostępu do bazy od kontrolerów

To nie jest jakieś wielkie dokonanie, to pierwszy warunek konieczny aby w ogóle można było mówić o MVC.
Drugi jest taki, aby w kontrolerach nie korzystać z repozytoriów.

implementację interfejsu UoW, która ma wstrzyknięte implementacje repozytorów

No i dodając nowe repozytorium trzeba zmieniać też kod UoW? Jak to się ma do SOLID?

Aplikacja nie jest bardzo prostym CRUDem, w wielu miejscach trzeba filtrować dane

Ale to jest właśnie definicja prostego CRUDa. :)

Działają one jak kolekcje, tzn. mają szereg metod zwracających encję lub kolekcję encji. Wszystko to po to, by umożliwić w razie potrzeby szybką zmianę EF na np. NHibernate (czy tak w firmach pisze się aplikacje, czy może zakłada się z góry, że np. tylko NHibernate będzie używany?).

Celem stosowania repozytoriów nie jest umożliwienie wymiany ORMa, która to:

  1. prawdopodobnie nigdy nigdzie nie miała miejsca;
  2. jeśli nawet miała, to wymiana wszystkich mapowań było dużo większym wyzwaniem niż różnice w API między ORMami.

Tylko że dziedziczenie z tego repozytorium nie zawsze ma sens, np. gdy mam encję, której klucz jest złożony z dwóch wartości. Ponadto niektóre metody, jak np. GetAll, mają sens tylko dla kilku encji. I co w takiej sytuacji zrobić?

Podzielić aplikacje na klasy, które robią konkretne rzeczy, np. dostarczają dane do wyświetlenia w gridzie, dostarczają danych potrzebnych dla innych klas, wykonują jakąś logikę biznesową i zapisują nowe dane do bazy, itd. Każda z tych klas może sobie operować bezpośrednio na ORMie. A każdy ORM udostępnia API, które zachowuje się jak generyczne repozytorium i UoW w jednym, a więc nie ma żadnego sensu pisać warstwy bezużytecznych wrapperów zwanych jedynie "repozytoriami" bo tak mądrzej.

1

Celem stosowania repozytoriów nie jest umożliwienie wymiany ORMa, która to:

Jednym z celów repository jest ukrycie mechanizmu bazodanowego za abstrakcją. Dlatego, w warstwie domeny wystawia się interfejs dla repository a implementuje się je w warstwie Infrastruktury. Ukrywanie mechanizmu bazodanowego, jakim jest ORM, to jedna z praktyk Portów i Adapterów i nie ma w tym nic złego.

0

@somekind: Masz może link do przykładowej aplikacji pokazującej to, co powiedziałeś? A jeśli nie, to czy nie mógłbyś poświęcić kilku godzin i napisać coś prostego? Na pewno taka aplikacja pomogłaby bardzo wielu początkującym programistom ;)

0
nobody01 napisał(a):

...to czy nie mógłbyś poświęcić kilku godzin...

Sugerujesz wolontariat ;) ? Jednak to jest dobry pomysł - zacząć pisać i poprosić o review.

0

@somekind: Ok, spróbuję napisać aplikację z tutoriala bez repozytoriów, ale wciąż mam kilka pytań (pewnie głupich, przepraszam). Pisałeś, żeby odczyt i zapis danych przenieść do klas z warstwy aplikacji (providerów), a w kontrolerach operować na ich abstrakcjach, przynajmniej tak ja to zrozumiałem. Ale jak to zrobić? Jeśli mam np. CustomerController, to odwoływać się w nim do ICustomerProvider, który zawiera metody zwracające wyniki wszystkich zapytań/wykonujące wszystkie operacje potrzebne kontrolerowi? Czy może tworzyć te providery bardziej szczegółowe? Jeśli tak, to w jaki sposób?

1

@nobody01: ten post może Ci rozjaśni: Wzorzec repozytorium

1 użytkowników online, w tym zalogowanych: 0, gości: 1