Wykorzystanie orm takich jak efcore/nhibernate przy oddzielnych modelach bazodanowych i domenowych

0

Od kilku tygodni w wolnym czasie hobbistycznie pracuję nad modelem domenowym mojego projektu. Jestem już na etapie kiedy powoli zaczynam myśleć nad jakąś formą zapisu danych. Zastanawiam się czy jest sens używania ormów takich jak nhibernate/efcore w sytuacji gdy będę miał oddzielny model mapujący na relacje w bazie danych? Myślę tu głównie nad takimi funkcjami, jak np. śledzenie zmian, które będą bezużyteczne przy założeniu ze model domenowy będzie całkowicie odseparowany.

2

Ja bym się składania w kierunku mikroORM'a jeżeli faktycznie to będzie czysty CRUD na jakichś tam DTOsach. W podejściu:

// Za siedmioma górami, za siedmioma lasami w repo:
void save(Aggregate aggreagate) {
   var dbModel = aggregate.toDBModel()
   session.upsert(dbModel);
}

Aggergate read(AggregateId id) {
   var dbModel = session.findOne(id);
   return Aggregate.fromDBModel(dbModel);
}

Z reguły uda się tutaj zrobić tak że DTO będą czyste (a więc nie nastąpi wyciek abstrakcji, jak mogło by to mieć miejsce w podejściach z ORM'ami np. wymagania żeby metoda była wirtualna).

Niestety to podejście nie jest wolne od wad. Po pierwsze 99% agregatów zawiera co najwyżej jeden poziom zagnieżdżenia (posiadają List encji), ale z tym pozostałym 1% będzie jazda. Z mirkoORM'em ty jesteś odpowiedzialny za zarządzanie taką listą encji. Proste podejście usuń stare encje z listy, dodaj nowe nie sprawdzi się jeżeli DB ma podefiniowane klucze obce które do encji z listy się odwołują (tak nie powinno być w DDD, odowłanie może być tylko do aggregatu ale mówimy tu o życiu a nie o tym jak powinno być). Nie wspomnę już o problemie z usuwaniem elementów z takiej listy. Musiał byś sobie jakiś Util dopisać w stylu syncList(list) na tyle inteligentny by zrobić create/update/delete w jednym.
Mimo wszystko dlaczego polecam to podejście? Bo jest proste jak drut, żadnej magi z proxy, niczego poza SQLem nie musisz znać (microORMy są proste z reguły).

Opcja druga to po prostu zapis danych do NoSQL, czy będzie to MongołDB czy inne stworzenie - nie jest to istotne. W tym wypadku o nic się nie musisz martwić po stronie agregatów, problem będzie po stronie query - nie ma kluczy obcych, join'a na 10 tabel nie zrobisz. Też źle, po prostu praca przeniesie się na stronę query - z drugiej strony dopóki projekt się nie rozbuja i nie wyświetlasz skomplikowanych tabel powinno być OK.

Opcja z ORM'em - plus że automatycznie będzie zarządzał kolekcjami oraz że możesz go użyć potem na stronie read/query do odczytu. Wada jest taka że pewnie w jakiś sposób twój model domenowy się od niego uzależni - no chyba że dasz jeszcze jeden poziom mapowania aggregate <-> persistanceDTO <-> DBModel. Przygotuj się na długie godziny czytania dokumentacji i pytanie siebie: dlaczego to ku*** nie działa ;) W zależności jak sprytnie zrobisz mapowanie problem z usuniętą encją nadal może pozostać (wydaje się w tym wypadku że najlepiej przy zapisie do bazy zrobić tak że mapujesz na świeżo wyciągnięto z bazy encje, tak żeby ORM miał szansę ztrackować zmiany).

Bogiem architektury nie jestem, ale junior architektem też nie. Mam nadzieje że mogłem pomóc.

2

@Kokoniłaj: odpowiedz sobie na pytanie, czy chcesz generować bazę ręcznie, czy nie, jeśli nie, to ORM może się przydać.

0

Zastanawiam się jak podejść do mapowania agregatu A, który wewnątrz wykorzystuje inny agregat B tylko wyłącznie w celu sprawdzenia poprawności danych. Do odtworzenia obiektu z ADto potrzebuje wewnątrz tego dto także BDto. Myślałem o hierarchi dto lub flagach. Dzięki temu podczas zapisywania Agregatu A zapiszą z Agregatu B wyłącznie Id, bez potrzeby wywoływania ToPersistenceDto na agregacie B, który jakiś swój "ciężar" też posiada. Przy zastosowaniu tego podejścia można się spodziewać czegoś takiego:

var a = new A(new B(...), ...);
var dtoA = a.ToPersistenceDto();
A a2 = A.FromPersistenceDto(dtoA); // wyjątek

Jakie jest Wasze zdanie na ten temat?

1

No ja się spodziewam, że kilka takich kombinacji alpejskich, i w ogóle nie będzie szło dojść do tego, co kiedy tak naprawdę jest aktualizowane, a co tylko przypadkiem.

Czemu serwis nie może przeprowadzić tej walidacji między agregatami? Od tego chyba są serwisy?

0
somekind napisał(a):

Czemu serwis nie może przeprowadzić tej walidacji między agregatami? Od tego chyba są serwisy?

Chciałem do tego podejść w taki sposób, w którym moje encje zawsze są w poprawnym stanie. Teraz się zastanawiam czy zawsze ma to sens.

e: Wydaję mi się, że jednak ten agregat B jest zbędny. Wykorzystam serwis tak jak napisałeś.

0
Kokoniłaj napisał(a):

Chciałem do tego podejść w taki sposób, w którym moje encje zawsze są w poprawnym stanie. Teraz się zastanawiam czy zawsze ma to sens.

Myślę, że ogólnie to ma zawsze sens. Tylko trzeba dobrze przemyśleć jak to wykonać, bo jakaś ifologia w repozytoriach nie brzmi na dobry pomysł. ;)

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