Jak zrozumiec warstwy w aplikacji?

0

Jak zrozumieć wartstwy w aplikacji i to, co się ma dziać w której? W
Załóżmy ze mam w aplikacji projekty (odpowiadajace warstwom)

  • Core
  • Application
  • Infrastructure
  • UI

Już na samym początku pojawiły mi sie wątpliwości, bo np w projekcie Core definiuije sobie klase
public class Employee

{
 public string Name{get;set;}
 public int Age {get;set;}
}

Chciałbym to zapisać do bazy. Do tego bedzie uzyty projekt Infrastructure, który w referencji ma projekt Core. Jako ORM używam EF Core. No ale pytanie, gdzie się ma odbyć ten zapis? W Core czy w Infrastructure, no i jak to ma wyglądać?
Według tego co czytałem, nie moge przekazać do projketu Core referencji do Infrastructure (bo to Infrastructure ma mieć referencje do projketu Core). Myślałem nad zrobieniem i korzystaniem w projekcie Core interfejsu:

public interface IWorkDbContext
{
 DbSet<Employee> Employees{get;set;}
 Task<int> SaveChangesAsync(CancellationToken cancellationToken);
}

i wtedy ten interfejs implementowałby też mój DbContext w projekcie Infrastructure

public class WorkDbContext : DbContext, IWorkDbContext
{
 //...
}

no, ale chciałem zrobić projekt database first i w bazie kolumny mają inne nazwy niż w encji Employee (i chce zeby tak zostało).
Jak to wsyzstko dobrze poustawić? Może nakierujecie mnie na jakiś przykładowy projekt.
Chciałem pisać aplikacje WPF ale wszsytkie przykłady jakie znajduje sa dla web i nie mogę tego przełożyć na swój problem.

5

Według tego co czytałem, nie moge przekazać do projketu Core referencji do Infrastructure (bo to Infrastructure ma mieć referencje do projketu Core). Myślałem nad zrobieniem i korzystaniem w projekcie Core interfejsu:

Dlatego masz jakiś interface. W Core masz interface w stylu EmployeeRepository a w infrastrukturze robisz EmployeePostgresRepository i tą implementacje wstrzykujesz do jakiegoś UseCase'a z warstwy domeny.

1

Jak tworzę solucje to robię jak w tym pdfie https://github.com/jasontaylordev/NorthwindTraders/blob/master/Docs/Slides.pdf

Jest tam krótko wyszczególnione co w której warstwie. Jeśli wchodzę w projekt istniejący to robię analogicznie to istniejącej implementacji.
Btw:
dla mnie ten interface dla dbContextu to trochę nieporozumienie bo jest on uzależniony od EF (db sety).

3

@AdamWox:

Ja nigdy tego nie rozumiałem. Uważam to za kompletną stratę czasu. Durne doktoryzowanie się nad - "jak to powinno być", bo jakiś pacan wymyślił argumentując, że "tak jest dobrze" i 3/4 firm programistycznych w to idzie. Czy twoim zdaniem jest sens to drążyć? Czy skoro nie jest to takie oczywiste dla ciebie "gdzie, co i jak" to nie szkoda ci czasu? Czy ten "sposób" jest narzucany przez firmę, w której pracujesz? Masz możliwość stworzyć swój "sposób"?

Wiesz, no chyba na tym polega cały trik

Wyjdźmy w ogóle od definicji:

Inżynieria – działalność polegająca na projektowaniu, konstrukcji, modyfikacji i **utrzymaniu efektywnych kosztowo rozwiązań dla praktycznych problemów**, z wykorzystaniem wiedzy naukowej oraz technicznej.

Co ja rozumiem jako - mierzyć siły na zamiary

Jasne, jeżeli masz prostą appkę 5 podstronek, 10 tabelek w bazce z czego 5 jakichś słowników, to może faktycznie nie ma sensu robić tego state of art

Zrobisz sobie jeden projekt, viewmodele tylko do jakichś critical rzeczy typu uniknąć wysłania user password, czy jak najdzie cię fanciness to podepniesz mediatra zrobisz 5 query, 5 command i wszystko będzie chodzić i nadal będzie proste w ogarnięciu

Ale te wszystkie rzeczy od podziału na projekty, dtosy/viewmodele czy nawet accessibility modifiers chronią od fuckupów, może nie twoich, ale kolejnych devów, którzy nie będą znali projektu, a będą musieli coś w nim zmienić.

Nawet jeżeli ta "architektura" nie jest perfekcyjna, to i tak chyba lepsze są standardy i konwencje niż company's_framework, albo właściwie pytanie jaki jest kompromis?

2
kalimata napisał(a):

Według tego co czytałem, nie moge przekazać do projketu Core referencji do Infrastructure (bo to Infrastructure ma mieć referencje do projketu Core). Myślałem nad zrobieniem i korzystaniem w projekcie Core interfejsu:

public interface IWorkDbContext
...

i wtedy ten interfejs implementowałby też mój DbContext w projekcie Infrastructure

public class WorkDbContext : DbContext, IWorkDbContext
...

Idziesz w dobrym kierunku. Z odpowiedzią przychodzi onion architecture i to że zgodnie z myślą takiej architektury warstwy znajdujące się najbardziej w środku (w Twoim przypadku Core) operują na abstrakcjach, a implementacje tych abstrakcji dostarczają warstwy zewnętrzne (w Twoim przypadku Infrastructure). Jedyne co bym radził to usunąć z warstwy Core wszelkie detale implementacje, a więc w Twoim przypadku IWorkDbContext wystawiające DbContext powinno być wymienione na jakieś repozytorium lub coś podobnego. Wtedy implementacja tego repozytorium (w Infrastructure) może korzystać bezpośrednio z EF czy czegokolwiek innego, ale dla warstwy Core będzie to transparentne.

no, ale chciałem zrobić projekt database first i w bazie kolumny mają inne nazwy niż w encji Employee (i chce zeby tak zostało).

To już jest oddzielny problem dotyczący ORMa. Dla czego chcesz aby modele w warstwie Core odpowiadały temu co wypluwa EF skoro powoduje to problemy? Warstwa Core nie powinna być "skażona" narzutem powodowanym przez jakiekolwiek frameworki. Zawsze możesz mapować z modelu bazy danych na model domenowy (Core).

Jak to wsyzstko dobrze poustawić? Może nakierujecie mnie na jakiś przykładowy projekt.

Tak jak napisałem, odpowiedzią jest onion architecature. Z przykładowym projektem najlepiej skorzystać z tego co oferuje Microsoft, a mianowicie ich (darmowa) książka i wspierający ją kod.

Chciałem pisać aplikacje WPF ale wszsytkie przykłady jakie znajduje sa dla web i nie mogę tego przełożyć na swój problem.

Problemy architektoniczne zazwyczaj są uniwersalne. WPF to przede wszystkim technologi frontendu. Backend możesz mieć oddzielny. Front napisany WPF traktuj tak jak front w przypadku aplikacji webowych. Różnica jest tylko w tym że front zamiast korzystać z protokołu HTTP do komunikacji, będzie korzystał z jakiejś abstrakcji przekazującej polecenia do właściwej warstwy biznesowej. Polecam do tego wzorzec mediator.

WeiXiao napisał(a):

@AdamWox:

Wiesz, no chyba na tym polega cały trik
...
Co ja rozumiem jako - mierzyć siły na zamiary

Dokładnie. Wszystko ładnie i pięknie dopóki nie przychodzi utrzymywać większego systemu. Nagle braki w odpowiedniej architekturze doprowadzają wydawało by się drobne przeszkody do absurdalnych rozmiarów.

2

Taki trochę sanity check możesz sobie zrobić odpowiadając na pytanie:

Masz napisaną aplikacje webową (np. liczenie czegoś lub cokolwiek innego dającego się zrobić po stronie klienta) i nagle klient chciałby również desktopa i mobilkę.
Ile musisz pozmieniać w kodzie od czysto logiki biznesowej?

albo po prostu

Jak łatwo idzie ci pisanie testów?

Jeżeli dużo/ciężko, to prawdopodobnie za dużo rzeczy tam się dzieje, co również pewnie utrudnia testowanie.

Ja wierzę, że pewnie do takiej sytuacji nie dojdzie, ale jak duży jest ten narzut? to już musisz sam sobie odpowiedzieć

0
kalimata napisał(a):

Jak zrozumieć wartstwy w aplikacji i to, co się ma dziać w której? W

Załóżmy ze mam w aplikacji projekty (odpowiadajace warstwom)

  • Core
  • Application
  • Infrastructure
  • UI

Powinieneś do tego dodać jeszcze trochę...

  • Models - to projekt z Twoimi modelami biznesowymi (np. Employee)
  • DAL (DataAccessLayer) - projekt, w którym masz obsługę bazodanową. Czy to w postaci repozytoriów, czy ORMa, czy ADO.NET. Nie łącz mi ORMa z repozytorium (chyba, że używasz Dappera)

I ja to widzę tak:

  • UI - no to wiadomo. Twój klient, całe UI (ale nie tylko widoki, również ViewModele itd)
  • Infrastructure - tutaj ładowałbym wszystkie interfejsy
  • Application/Core - no to w zależności od potrzeb. Generalnie tu powinny być konkretne klasy implementujące interfejsy z Infrastructure.

I teraz ważne - Models - nie powinno mieć referencji do żadnej innej warstwy przy takim układzie.

  • Infrastructure może korzystać raczej tylko z Models
4

Infrastructure to raczej miejsce na implementacje, np. repozytoriów czy klientów zewnętrznych serwisów jeśli działamy zgodnie z clean architecture, albo różnych pomocniczych rzeczy, jeśli piszemy po swojemu. Interfejsy do tych implementacji to raczej w jakiejś domenie ewentualnie aplikacji siedzą.

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