Podział warstwy logiki biznesowej z dostępu do danych.

0

Cześć,
Właśnie projektuję większy projekt, który będę realizował. Zastanawiam się nad jego architekturą - a dokładnie podziałem na warstwę dostępu do danych (encje i mapowanie na tabele) a logiką biznesową.
Załóżmy poniższe definicje (na cele tematu, nie wiem czy są poprawne) :
-model - klasa zawierająca logikę biznesową, jakiś obiekt ze świata rzeczywistego (np. Produkt, Samochód)
-encja - klasa którą ORM mapuje na tabele relacyjnej bazy danych.

Architektura aplikacji będzie zawierała klasy modelu z logiką biznesową i na tych klasach operowała. Dla każdej klasy modelu stworzę odpowiadającą klasę którą ORM będzie mapował. Aplikacja nie będzie w ogóle z nich więcej korzystała(jedynie w repozytoriach aby używać CRUD). Stworzę ponadto serwisy, które będą repozytoriami, i w nich także będzie odbywało się mapowanie z obiektu klasy modelu na klasę encji, aby ORM mógł przeprowadzić operację. Tylko te repozytoria będa korzystać z obiektów klas encji.

Co sądzicie o takiej architekturze?
PS. Przepraszam jeśli napisałem zbyt chaotycznie lub użyłem niepoprawnych pojęć.

0

Jeśli dobrze rozumiem masz "serwis" który operuje na obektach domenowych i on odpowiada za mapowanie tych obiektów domenowych na encje ORM?
Napisałes trochę nie zrozumiale, serwisy odpowiadają za persystencję czy za persystencję i logikę biznesową?

1

Rzeczywiście trochę to niespójne. Podejście z rozdzieleniem modelu, który realizuje logikę od encji bazodanowych brzmi spoko. Nie wiem natomiast dlaczego założyłeś a priori, że użyjesz ORM-a i będziesz implementował operacje typu CRUD. Zacząłbym od przeanalizowania, co będzie ten system robić i wtedy dopiero wybrał architekturę. Może rzeczywiście to jest CRUD i wtedy nawet obiekty domenowe i encje to jedno i to samo :)

0
scibi92 napisał(a):

Jeśli dobrze rozumiem masz "serwis" który operuje na obektach domenowych i on odpowiada za mapowanie tych obiektów domenowych na encje ORM?
Napisałes trochę nie zrozumiale, serwisy odpowiadają za persystencję czy za persystencję i logikę biznesową?

Oczywiście mapowanie będzie robił jakiś AutoMapper, tylko właśnie w tych moich "repozytoriach" będzie się to odbywało. Repozytoria będą odpowiadały ogólnie za komunikację z bazą danych. Aplikacja będzie korzystała z nich, aby coś pobrać lub dodać do bazy.
Repozytorium będzie posiadało metody typu:
List<Post> GetAllPostsFromThreadForUser(User user, Thread thread)>
Która z bazy np. będzie zwracała wszystkie posty w określonym wątku dla określonego usera

2

Może po prostu lepiej rozpisz jak to wygląda od warstwy API do warstwy bazy danych :D

2
Severus Snape napisał(a):

serwisy, które będą repozytoriami

Co Ty rozumiesz przez "serwis"?

Co sądzicie o takiej architekturze?

Zasadniczo sensowne jest oddzielenie modelu domeny (czyli tego, co Ty nazywasz modelami) od modelu składowania danych (czyli tego, co Ty nazywasz encjami) i to jest bardzo dobry pomysł.
Ale jak Ty chcesz robić CRUDa, i masz zamiar mapować te obiekty 1:1, to ja nie wiem czy ma sens wprowadzanie dodatkowej warstwy.
No i do robienia CRUDa, to w ogóle żadnych repozytoriów nie potrzebujesz. Polecam poczytać: http://commitandrun.pl/2016/05/11/Repozytorium_najbardziej_niepotrzebny_wzorzec_projektowy/

0

Serwisami nazywam klasy, które są dostarczane przez ServiceProvidera dla klas, które zadeklarowały że potrzebują instancji danego serwisu. Czyli dokładnie to co wstrzykujemy przez DI.
Model domeny nie będzie mapowany 1:1 w stosunku do modelu składowania danych. Dziękuję za bardzo interesujący artykuł związany z repozytoriami. Zapewne tak jak jest napisane, w moim projekcie ten wzorzec nie będzie dobrze użyty.
Miałbym w związku z tym pytania.
Jak sensownie "połączyć" warstwę dostępu do danych z warstwą domeny, nie używając repozytoriów? Chciałbym osiągnąć efekt, aby warstwa domeny nie wiedziała nic o sposobie składowania danych. W podlinkowanym artykule zostało to trochę zamiecione pod dywan.

1
Severus Snape napisał(a):

Serwisami nazywam klasy, które są dostarczane przez ServiceProvidera dla klas, które zadeklarowały że potrzebują instancji danego serwisu. Czyli dokładnie to co wstrzykujemy przez DI.

Ok, to w tym sensie, to powinieneś był raczej napisać, że repozytoria będą serwisami (w sensie microsoftowego kontenerka DI).

Jak sensownie "połączyć" warstwę dostępu do danych z warstwą domeny, nie używając repozytoriów? Chciałbym osiągnąć efekt, aby warstwa domeny nie wiedziała nic o sposobie składowania danych. W podlinkowanym artykule zostało to trochę zamiecione pod dywan.

Nie ująłbym tego w ten sposób, bo to by było dziwne, gdyby artykuł dotyczący błędnego użycia repozytoriów traktował o prawidłowym używaniu nie-repozytoriów.
Jeśli chcesz oddzielić, to wystarczy, że utworzysz jakieś Data Access Object bez udawania, że to repozytorium. Tylko jeśli nie chcesz mieć domeny 1:1 do składowania, to raczej powinieneś myśleć o "bogatszym" podejściu.

Ja generalnie widzę dwa rozsądne sposoby tworzenia aplikacji:

  1. Mutowalne klasy modelu, które służą jednocześnie do przechowywania danych jak i do realizacji logiki biznesowej przez np. skrypt transakcji. To się sprawdza przy prostej, CRUDowej domenie. Wtedy nie potrzeba żadnych repozytoriów, klasa realizująca transakcję (czy jak kto woli przypadek użycia) może korzystać z API ORMa (czy innej warstwy dostępu do danych bezpośrednio.)
  2. Poprawny "bogaty" model domenowy, z encjami ukrywającymi dostęp do swoich wewnętrznych danych i wystawiającymi metody do zmiany swojego stanu, i wtedy takie encje (nie wszystkie oczywiście, tylko te będące centrum agregatu) posiadają repozytoria.

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