Architektura aplikacji .Net Core Api

6

Obecnie czekam na książkę PoEAA ale, żeby mieć co robić zanim ją dostanę sporo czytałem o tym jak powinna wyglądać architektura projektu, głównie w .net core. W internecie jest pełno sprzecznych informacji, jeśli chodzi o repository pattern, podejście ddd itp. W tutorialach mieniących się nagłówkami: clean architecture, controllery są grube jak świnki, wykonują logikę, często nawet skomplikowaną itp. Przewertowałem również sporo wątków na tym forum, odnośnie dobrych praktyk itp. i doszedłem do czegoś takiego (schemat niżej), jeśli się mylę proszę poprawcie mnie ewentualnie nakierujcie co powinienem zmienić.

przykład nr 1. - bardzo uproszczona wypożyczalnia sklepu Web Api

Wypożyczalnia.Api

  • Controllers -> do controllera wstrzykujemy implementacje serwisów - I___Services
    • FilmController -> IFilmServices
    • UseController -> IUserServices

Wypożyczalnia.Core

  • Domain -> (domain classes, anemic-classes?), proste klasy z właściwościami, które zmapujemy na tabele i kolumny w bazie danych. Dodajemy adnotacje pomagające przy walidacji.
    • Film -> public int Id { get; private set; } [Required]
    • User
  • Services -> logika aplikacji np. stworzenie konta, dodanie filmu, filtrowanie w tym przypadku to chyba prosty CRUD
    • IFilmServices -> GetById(int id), ...
    • IUserServices -> Create(UserDto user) vs Create(UserViewModel)?

Wypożyczalnia.Infrastructure

  • DAL -> konfiguracja EF, NHibernate lub innego ORM'a
    • AppDbContext
    • MigrationHistory
    • EntityConfigurations -> klasy z ustawieniami, nadpisanie domyślnych ustawień mapowania za pomocą EF Fluent Api
  • Services -> implementujemy interfaces z Core
    • FilmServices -> private readonly AppDbContext _context i bezpośrednio korzystamy z ORM'a bez tworzenia dodatkowej warstwy abstrakcji
    • UserServices -> zwracamy np. UserDto, mapowanie odbywa się w services, żeby controller dostał Dto, nasz uproszczony model, bez zbędnych z punktu widzenia użytkownika właściwości

Wypożyczalnia.Tests

  • UnitTests -> reference to Core
  • E2ETests -> reference to Infrastructer
  1. Czy to jest dobrze rozplanowana architektura prostej aplikacji?
  2. Controller wysyła tylko żądanie do services i tam wykonujemy logikę a następnie otrzymujemy przetworzone dane, przez co metoda w controllerze ma zwykle 1 czasami do 3 linijek a sam controller o niczym nie wie, czy to jest dobre podejście i powinienem się go trzymać?
  3. W przypadku Api zwracamy Dto czy viewmodel czy to zależy od operacji? np. GetUser(id) zwróci UserDto po odpytaniu przez HTTP GET bo z tego co wiem nie powinienem przekazywać User, żeby nie ujawniać wewnętrznej implementacji, ale gdybym chciał pobrać listę użytkowników i ich filmów wtedy, muszę skorzystać z dwóch serwisów i ich wyniki - dwa Dtosy połączyć i to się chyba nazywa viewmodelem, czy w podejsciu z wykorzystaniem Api powinienem jakiś nowy Dto stworzyć zbudowany z 2 innych, mam nadzieję, że wiecie o co mi chodzi
  4. Czy konfigurację np. AutoMappera, Autofaca powinienem trzymać w Infrastructure?
  5. Jeśli np. chcę szyfrować hasła, to IEncrypter powinien być w Core i implementacja w Infrastructure czy interface i implementacja razem trzymane w Infrastructure?
  6. Podobne pytanie do powyższego np. Logger i inne usługi jeśli bym chciał dodać do projektu to ich interfaces mam w Core trzymać czy w Infrastructure razem z implementacją? Myśląc o tym chyba do drugiego rozwiązania bym się skłaniał bo Logger nie jest w żaden sposób powiązany z moją domeną to jest coś z zewnątrz dostarczane ale chcę zapytać bardziej doświadczonych.
  7. Odnośnie modelu i anemic-classes jak to ma wyglądać. Przykładowo User ma kolekcję wypożyczonych filmów i teraz trzymając się powyższej implementacji mam:
    • zrobić anemic classes a w services dodać możliwości dodania filmu do list bądź usunięcia
    • w klasie User stworzyć metody pozwalające na dodanie, usunięcie filmów włącznie z walidacją np. czy film który chcę usunąć jest wypożyczony itp.
      Które podejście jest lepsze w zwykłym CURDzie? Druga opcja nie idzie w kierunku metodyki DDD?
  8. Walidacja np. czy są filmy na stanie w celu wypożyczenia? powinienem w services robić czy klasa powinna być wyposażona w odpowiednie metody?
  9. Jakie jest wasze podejście do walidacji w modelu (chodzi mi np. walidację formularza który zostanie wypełniony przez użytkownika)? Pisać metody czy korzystać z adnotacji?
  10. @somekind w którymś wątku pisałeś, żeby we własnych projektach zrezygnować z interfaces dla każdej klasy bo to nie ma sensu, w powyższym przykładzie powinienem, gdzieś z nich zrezygnować? Tworzę np. IEncrypter potem jego implementację z której korzysta poprzez DI jakiś serwis. Powinienem tak robić czy lepiej bez interfejsu?

Odnośnie pierwszego przykładu chyba już nie mam pytań. Drugie podejście, przykład będzie się tyczył DDD, jak będę miał chwilkę to zamieszczę na forum bo muszę jeszcze parę spraw odnośnie architektury i podejścia przemyśleć.
Mam nadzieję, że ktoś to wypracowanie przeczyta i będzie w stanie udzielić odpowiedzi :0
Od razu z góry dziękuję za pomoc i poświęcony czas.

0
Aenyatia napisał(a):
  1. Czy to jest dobrze rozplanowana architektura prostej aplikacji?

Prawie, zauważ że Twoje serwisy robią dwie różne rzeczy : pobierają dane ze źródła jak i mają logikę domenową i oba implementujesz w infrastrukturze...
Mamy wiele rodzajów serwisów:

  • serwisy aplikacyjne (tak się zwą w DDD i The Onion Architecture) - zwane Fasadami w środowisku javowym, zwane Service Layer u Fowlera, zwane Use Case Interactor u Uncle Bob, służą one do orkiestracji operacji dokonywanych na domenie u Ciebie ich nie ma, ale da się bez nich żyć skoro to prosta architektura,
  • serwisy do pobierania danych ze źródła danych, które zwą się DAO, czy też Table Data Gateway u Fowlera, czy też niepoprawnie Repozytoriami i to ich interfejsy powinny być w core a implementacja w infrastrukturze
  • serwisy domenowe, zawierające logikę domenową która nie pasuje do żadnej z encji, biorąc pod uwagę że robisz anemiczny model domenowy to w nich będzie cała logika domenowa, i finalnie bliżej im będzie do Transaction Script u Fowlera, niż serwisom z DDD, no i one jak i cała logika nie wyciekają poza Core

także podziel serwisy i będzie git

0

@neves

Core

  • Dao
    • IUserDao
    • IMovieDao
  • Services (serwisy domenowe) - walidacja, CreateUser, AddMovie
    • IUserServices, UserServices -> wstrzykujemy Dao
    • IMovieServices, MovieServices

Infrastructure

  • Dao (serwisy do pobierania danych) -> implementacja Dao z core
    • UserDao
    • MovieDao
  • Services (serwisy aplikacyjne) - tą są jakby zewnętrzne usługi?
    • np. IEncrypter, Encrypter
    • IJwtServices, JwtServices
    • IEmailSender EmailSender

Czy coś takiego miałeś na myśli?

0

Ja projektując nowe api trafiłem na coś w tym stlu i w zasadzie skłądniam się ku architekturze tego typu (hexagonal architecture)
title
Sądzę że można zrobić bardzo czystą i uporządkowaną aplikację .

Dążę do tego żeby projekt ASP.NET był tylko kontenerem i entry pointem dla aplikacji, Same kontrolery powinny być w osobncyh projektach ,ładowane w trakcie startu apliacji.
Warstwę "mediacji" początkowo planowałem zrobić jako serwisy. Ale chyba skłaniam się bardziej by cała logika biznesowa korzystała z bibliotrki w stylu Mediatr(wzorzec mediatora) zamiast serwisów.

Nie porównuję twojego rozwiązania. Po prostu więszkośc projektów dotychczas robiłem w ten sposób jak Ty opisaleś i chciałbym coś zrobić "inaczej" :-)

EDIT: Znaleziony ciekawy przykład : https://github.com/ivanpaulovich/hexagonal-architecture-acerola

0

Czytam Fowlera i mamy tam 3 podejścia do logiki dziedziny:
[1] Transaction Script
[2] Table Module
[3] Domain Model
DM polega na współpracy obiektów między sobą (można powiedzieć dobre praktyki OOP) i jest to zalecane podejście gdzie logika jest złożona, skomplikowana. Stąd pytanie co to znaczy, że mamy skomplikowaną logikę, kiedy warto iść w DM a kiedy zostać przy TM albo TS? Czy warto we własnych projektach (powiedzmy do max 4-5 osób) korzystać z DM czy to będzie na ogół overengineering i niepotrzebna komplikacja? Jak to wygląda obecnie w firmach?

0

E2ETests -> reference to Infrastructer

Nie, E2E to testy czarnej skrzynki. Najlepiej przez http

1

Nie :|

3

Pobierasz Dto. W Web możesz go udekorować innym obiektem np UserRest, UserResource, UserHateasResult i tp

4

W tej paczce, której dotyczy.

Konfiguracje Automappera, możesz tworzyć dynamicznie pod request

5

Tak , to jest właśnie dependency Inversion, albo port/adapter

6

Żadnych interfejsów, to ma mieć zasięg globalny.

7

Dowiedz się co to jest persistence.

8

A to zależy. :|

9

Adnotacje, po to je mamy, zawsze możesz swój atrybut zaimplementować.

10

@somekind Prawdopodobnie miał na myśli używanie interface jak kontraktu. Interface służy głównie do manipulowania zależnościami, tworzenie interfejsu tylko dlatego, że jakiś Pan M powiedział, że depenecy injection wymaga interfejsów jest bez sensu.

0
._. napisał(a):

1

Nie :|

Czy mógłbyś swoją wypowiedź rozwinąć? Według ciebie wszystko jest złe i inaczej powinno się do tego podejść czy wystarczy coś poprawić i będzie ok?

1
Aenyatia napisał(a):

Obecnie czekam na książkę PoEAA

Jest 30 stopni w cieniu, a Ty chcesz w piecu palić?

Wypożyczalnia.Api

  • Controllers -> do controllera wstrzykujemy implementacje serwisów - I___Services
    • FilmController -> IFilmServices
    • UseController -> IUserServices

Ale to nie są implementacje, to są jakieś interfejsy serwisów. Albo się przejęzyczyłeś, albo miałeś coś innego na myśli.

Wypożyczalnia.Core

  • Domain -> (domain classes, anemic-classes?), proste klasy z właściwościami, które zmapujemy na tabele i kolumny w bazie danych. Dodajemy adnotacje pomagające przy walidacji.
    • Film -> public int Id { get; private set; } [Required]
    • User

Ale jak przy walidacji? Waliduje się dane przychodzące od uzytkownika. Moment zapisu do bazy to za późno na walidację.

  1. Controller wysyła tylko żądanie do services i tam wykonujemy logikę a następnie otrzymujemy przetworzone dane, przez co metoda w controllerze ma zwykle 1 czasami do 3 linijek a sam controller o niczym nie wie, czy to jest dobre podejście i powinienem się go trzymać?

Ja się takiego trzymam, wad nie widzę. Kontroler dla mnie to tylko taki entry point.

  1. W przypadku Api zwracamy Dto czy viewmodel czy to zależy od operacji? np. GetUser(id) zwróci UserDto po odpytaniu przez HTTP GET bo z tego co wiem nie powinienem przekazywać User, żeby nie ujawniać wewnętrznej implementacji, ale gdybym chciał pobrać listę użytkowników i ich filmów wtedy, muszę skorzystać z dwóch serwisów i ich wyniki - dwa Dtosy połączyć i to się chyba nazywa viewmodelem, czy w podejsciu z wykorzystaniem Api powinienem jakiś nowy Dto stworzyć zbudowany z 2 innych, mam nadzieję, że wiecie o co mi chodzi

No viewmodel implikuje, że masz w aplikacji jakieś widoki, więc jeśli GUI jest częścią tej samej aplikacji, to nazwałbym to właśnie tak. A DTO w sytuacji, gdy piszesz jakieś API.

  1. Czy konfigurację np. AutoMappera, Autofaca powinienem trzymać w Infrastructure?

AutoMapper musi być w miejscu, które zna obie strony i jest dostępny tam, gdzie potrzebujesz mapować, może to być Infrastructure.
A Autofaca moim zdaniem lepiej dzielić na moduły, i niech każde assembly rejestruje tylko te typy, które w nim występują.

  1. Odnośnie modelu i anemic-classes jak to ma wyglądać. Przykładowo User ma kolekcję wypożyczonych filmów i teraz trzymając się powyższej implementacji mam:
    • zrobić anemic classes a w services dodać możliwości dodania filmu do list bądź usunięcia
    • w klasie User stworzyć metody pozwalające na dodanie, usunięcie filmów włącznie z walidacją np. czy film który chcę usunąć jest wypożyczony itp.
      Które podejście jest lepsze w zwykłym CURDzie? Druga opcja nie idzie w kierunku metodyki DDD?

W prostym przypadku wybrałbym pierwszą opcję. Jeśli logika się skomplikuje, to zawsze można DDD wprowadzić, o ile oczywiście nie zepsuło się architektury na początku.

  1. Jakie jest wasze podejście do walidacji w modelu (chodzi mi np. walidację formularza który zostanie wypełniony przez użytkownika)? Pisać metody czy korzystać z adnotacji?

Użyć FluentValidation, ewentualnie adnotacji jeśli wystarczają. Byle na viewmodelach, a nie na obiektach, które idą do bazy.

  1. @somekind w którymś wątku pisałeś, żeby we własnych projektach zrezygnować z interfaces dla każdej klasy bo to nie ma sensu, w powyższym przykładzie powinienem, gdzieś z nich zrezygnować? Tworzę np. IEncrypter potem jego implementację z której korzysta poprzez DI jakiś serwis. Powinienem tak robić czy lepiej bez interfejsu?

Ja raczej pisałem, żeby nie tworzyć interfejsów bez powodu. Ty masz tutaj chyba same takie.
Interfejsy mają sens tylko, gdy mają mieć kilka implementacji. W praktyce występuje to tylko jako np. element jakiegoś wzorca projektowego w rodzaju strategii albo jeśli mamy jakąś zewnętrzną zależność (baza danych, system plików, inny webserwis), bo w takim wypadku potrzebujemy ją mockować w testach.

Aenyatia napisał(a):

Core

  • Dao
    • IUserDao
    • IMovieDao
  • Services (serwisy domenowe) - walidacja, CreateUser, AddMovie
    • IUserServices, UserServices -> wstrzykujemy Dao
    • IMovieServices, MovieServices

Ja tu widzę już 4 zbędne interfejsy.

Infrastructure

  • Dao (serwisy do pobierania danych) -> implementacja Dao z core
    • UserDao
    • MovieDao

I co wniosą te klasy DAO do projektu? To będą co najwyżej wrappery na ORMa, które tylko utrudnią korzystanie z niego.

  • Services (serwisy aplikacyjne) - tą są jakby zewnętrzne usługi?
    • np. IEncrypter, Encrypter
    • IJwtServices, JwtServices
    • IEmailSender EmailSender

O - i IEmailSender to jest np. sensowny interfejs, bo zapewnia separację od świata zewnętrznego.

0

I co wniosą te klasy DAO do projektu? To będą co najwyżej wrappery na ORMa, które tylko utrudnią korzystanie z niego.

A co z Port/Adapter i traktowaniu ORM/PersistenceModel jako zewnętrznej biblioteki/bazy danych?

Korzystasz z ORM i persistence w warstwie Aplikacji?

0

Wypożyczalnia.Api

  • Controllers -> do controllera wstrzykujemy implementacje serwisów - I___Services
    • FilmController -> IFilmServices
    • UseController -> IUserServices

Ale to nie są implementacje, to są jakieś interfejsy serwisów. Albo się przejęzyczyłeś, albo miałeś coś innego na myśli.

chodziło mi o coś takiego, waliduję MovieForCreation a klasa Movie jest "czysta"

private readonly IMovieServices _movieServices;

public MovieController(IMovieServices movieServices)
{
   _movieServices = movieServices;
}

[HttpGet]
public async Task<IActionResult> Get(int movieId)
{
   var movieDto = await _movieServices.GetMovieById(movieId);
   if (movieDto == null)
      return NotFound();

   return Ok(movieDto);
}

[HttpPost]
public async Task<IActionResult> Post([FromBody] MovieForCreation movieForCreation)
{
   if (!ModelState.IsValid)
      return BadRequest(ModelState);
   
   await _movieServices.AddMovieAsync(movieForCreation);
   return Created(URI);
}
  1. @somekind w którymś wątku pisałeś, żeby we własnych projektach zrezygnować z interfaces dla każdej klasy bo to nie ma sensu, w powyższym przykładzie powinienem, gdzieś z nich zrezygnować? Tworzę np. IEncrypter potem jego implementację z której korzysta poprzez DI jakiś serwis. Powinienem tak robić czy lepiej bez interfejsu?

Ja raczej pisałem, żeby nie tworzyć interfejsów bez powodu. Ty masz tutaj chyba same takie.
Interfejsy mają sens tylko, gdy mają mieć kilka implementacji. W praktyce występuje to tylko jako np. element jakiegoś wzorca projektowego w rodzaju strategii albo jeśli mamy jakąś zewnętrzną zależność (baza danych, system plików, inny webserwis), bo w takim wypadku potrzebujemy ją mockować w testach.

Aenyatia napisał(a):

Core

  • Dao
    • IUserDao
    • IMovieDao
  • Services (serwisy domenowe) - walidacja, CreateUser, AddMovie
    • IUserServices, UserServices -> wstrzykujemy Dao
    • IMovieServices, MovieServices

Ja tu widzę już 4 zbędne interfejsy.

private readonly MovieServices _movieServices;
public MovieController(MovieServices movieServices)
{
   _movieServices = movieServices;
}

Startup.cs

public void ConfigureServices(IServiceCollection services)
{
    services.AddTransient<MovieServices>();
}

czy to miałeś na myśli? wywalamy niepotrzebne interfejsy, nadal korzystając z DI

Infrastructure

  • Dao (serwisy do pobierania danych) -> implementacja Dao z core
    • UserDao
    • MovieDao

I co wniosą te klasy DAO do projektu? To będą co najwyżej wrappery na ORMa, które tylko utrudnią korzystanie z niego.

czyli usunąć całkowicie te klasy DAO z projektu a w serwisach bezpośrednio z dbContext korzystać?

0

Raczej lepiej jest używać services.AddScope<MovieServices>

*Scoped lifetime services are created once per request within the scope. It is equivalent to Singleton in the current scope. eg. in MVC it creates 1 instance per each http request but uses the same instance in the other calls within the same web request.
Transient lifetime services are created each time they are requested. *

2
._. napisał(a):

A co z Port/Adapter i traktowaniu ORM/PersistenceModel jako zewnętrznej biblioteki/bazy danych?

W sensie wiemy, że te klasy nic nie wnoszą, ale użyjmy ich, bo tak piszą w grubych książkach? Potem pewnie trzeba użyć kolejnej grubej książki o refaktoryzacji i jeszcze kolejnej grubej książki o odchudzaniu projektu ze zbędnego kodu.

Korzystasz z ORM i persistence w warstwie Aplikacji?

W orkiestratorze operacji CRUDowych owszem. Wpychanie dodatkowej warstwy jednolijkowych wrapperów to tylko dodatkowy kod do utrzymania. Jeśli kiedykolwiek ktoś wpadnie na pomysł odpięcia aplikacji od bazy danych, to używanie ISession w warstwie aplikacji będzie najmniejszym z problemów do rozwiązania. A na 90% i tak takie przedsięwzięcie skończy się po prostu stworzeniem nowej wersji aplikacji.

Aenyatia napisał(a):

chodziło mi o coś takiego, waliduję MovieForCreation a klasa Movie jest "czysta"

private readonly IMovieServices _movieServices;

Nie wiem jaki to ma związek z moją odpowiedzią, po prostu nie wiem po co ten interfejs tutaj. To IMovieService to jakiś zewnętrzny serwis, którego nie jesteś autorem, i nie masz wpływu na jego implementację?

czy to miałeś na myśli? wywalamy niepotrzebne interfejsy, nadal korzystając z DI

Owszem, ja w ogóle nie widzę żadnego związku interfejsów z DI.

czyli usunąć całkowicie te klasy DAO z projektu a w serwisach bezpośrednio z dbContext korzystać?

W aplikacji, która jest w > 50% CRUDowa tak bym zrobił - serwis aplikacyjny orkiestruje działania: pobranie danych, oddelegowanie operacji na tych danych do miejsca realizującego jakiś tam flow biznesowy, a potem zapis tychże danych.
Jeśli logika jest naprawdę skomplikowana, i warto się pchać w DDD, to wtedy taki serwis pod spodem może uruchomić operacje na serwisach domenowych, pobrać encje z repozytoriów, itd.
Z zewnątrz taka refaktoryzacja będzie niewidoczna, dlatego właśnie uważam, że warto mieć warstwę serwisów aplikacyjnych, a komplikować rozwiązanie dopiero, gdy tego biznes wymaga.

0

W orkiestratorze operacji CRUDowych owszem. Wpychanie dodatkowej warstwy jednolijkowych wrapperów to tylko dodatkowy kod do utrzymania. Jeśli kiedykolwiek ktoś wpadnie na pomysł odpięcia aplikacji od bazy danych, to używanie ISession w warstwie aplikacji będzie najmniejszym z problemów do rozwiązania. A na 90% i tak takie przedsięwzięcie skończy się po prostu stworzeniem nowej wersji aplikacji.

Tak też można tylko, że to jest architektura, w której warstwa aplikacji patrzy na infrastrukturę. Ja preferuje odcięcie tej warstwy od infrastruktury i nie zachęcam do tworzenia wrapów, tylko do implementowania serwisu, który pobiera wyłącznie strukturę danych w infrastrukturze. W większości przypadków wystarczy generyczny serwis, który w nagłym przypadku można rozszerzać nawet o generyczny filter, który będzie przyjmował konfiguracje pod request z warstwy aplikacji. Dlaczego taki serwis ma przeszkadzać? Mnie on pomaga ja mu tylko podaje strukturę, jaką ma wyciągnąć i konfiguracje filtra projekcje/aliasy a on generuje całe zapytanie łącznie z mapowanie na obiekt zwrotny. Jeśli dalej chcesz wykonywać jakieś projekcje np. tworzenie dto z metadanymi, do których i tak musisz wykonać drugie zapytanie, to tworzysz drugi serwis aplikacyjny, który zarządza dostępem do bazy. Raczej jestem za unikaniem robienia ceremonii typu UserDAO, CatDAO, PageDAO albo UserService, CatService, PageService lub jak kto woli UserRepository, CatRepository, PageRepository

W sensie wiemy, że te klasy nic nie wnoszą, ale użyjmy ich, bo tak piszą w grubych książkach? Potem pewnie trzeba użyć kolejnej grubej książki o refaktoryzacji i jeszcze kolejnej grubej książki o odchudzaniu projektu ze zbędnego kodu.

To nie ty pisałeś coś ostatni o paleniu książek ? :|

A tak na serio to co byś polecił z odchudzania kodu ?

0
error91 napisał(a):

@W2K: tutaj ciekawa alternatywa dla tej architektury https://jimmybogard.com/vertical-slice-architecture/?utm_source=feedburner&utm_medium=feed&utm_campaign=Feed%3A+GrabBagOfT+%28Jimmy+Bogard%29

w środowisku javowym taka architektura się zwie "Package by feature" i pod tym hasłem można znaleźć znacznie więcej materiałów niż pod "Vertical slice":

Package by feature, not layer
Package by component and architecturally-aligned testing

no ale to raczej opcja dla minimum średniej wielkości projektów.

1

patrzę i podziwiam jak prostą aplikację obsługującą wypożyczalnię można skomplikować. Na mój gust to strzelanie z armaty do wróbli. W samej bazie będą raptem trzy podstawowe tabele: filmy, użytkownicy i wypożyczenia (łączy użykownika z filmem). Może dojdą do tego jakieś tabele pomocnicze typu rezerwacja, kategorie, logi itp., ale ogólnie prosta aplikacjia. Rozumiem jakby Kolega rozbudował jeszcze aplikację o moduł fakturujący,raportujacy, płatności elektroniczne, pobieranie opisów filmów z baz dystrybutorów, obługa wielu języków i do tego dodał wymóg dużej wydajności to wtedy można się zastanawiać, dzielić na serwisy czy moduły jak zwał tak zwał, ale teraz to aplikacja prosta jak cep.

1

Skomplikować jak skomplikować, ale tradycyjnie jest masa bullshitingu w tekście zamiast jakoś to ładnie rozrysować, przedstawić swoje argumenty i czekać na podobną odpowiedź a tutaj niestety to wygląda na takie "odszczekiwanie" do autora, że zrobił źle :/

0

@Aenytia czyli usunąć całkowicie te klasy DAO z projektu a w serwisach bezpośrednio z dbContext korzystać?

Tak, to może być dobry pomysł, dodawanie DAO, czy repository może być uważane jako nadmiarowe, można działać wprost na dbContext. Argumenty za niekorzystaniem z repository pattern jakie słyszałem to zmniejszenie warstwy abstrakcji, rzadka zmiana systemu bazy danych, przy przejściu na nierelacyjną bazę danych, nie zrobimy tego po prostu podmieniając implementacje, więc nakład pracy nie ulegnie zmianie.
Jednak to nie znaczy, że nie powinieneś z tego korzystać, to dobry wzorzec, ale trzeba go w prawidłowy sposób używać. Wskazówek szukaj w internecie.

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