Wiele tutoriali na temat DDD, które studiowałem, dotyczy głównie teorii. Wszystkie mają podstawowe przykłady kodu (Pluralsight i podobne).
W Internecie próbuje się również kilka osób, aby stworzyć samouczki dotyczące DDD z EF. Jeśli zaczniesz je studiować krótko - szybko zauważysz, że bardzo się od siebie różnią. Niektóre osoby zalecają, aby aplikacja była minimalna i unikała wprowadzania dodatkowych warstw, np. Repozytorium nad EF , inne zdecydowanie generują dodatkowe warstwy, często nawet naruszając SRP poprzez wstrzykiwanie DbContext
do Aggregate Roots.
Okropnie przepraszam, jeśli zadaję pytanie oparte na opiniach, ale ...
Jeśli chodzi o praktykę - Entity Framework jest jednym z najpotężniejszych i najczęściej używanych ORM. Niestety nie znajdziesz w nim kompleksowego kursu obejmującego DDD.
Ważne aspekty:
Entity Framework
DbSet
wyciąga UoW & Repository ( ) z pudełkaz EF twoje modele mają właściwości nawigacyjne
EF wszystkie modele są zawsze dostępne off
DbContext
(są one reprezentowane jakoDbSet
)
Pułapki:
nie możesz zagwarantować, że wpływ na twoje modele potomne będzie mieć tylko Zagregowane Korzenie - twoje modele mają właściwości nawigacyjne i można je modyfikować i wywoływać
dbContext.SaveChanges()
dzięki
DbContext
czemu możesz uzyskać dostęp do każdego modelu, omijając w ten sposób Korzeń zagregowanymożna ograniczyć dostęp dzieci głównego obiektu za pośrednictwem
ModelBuilder
wOnModelCreating
sposób oznaczając je jako pola - I nadal nie wierzę, że to właściwa droga o DDD plus to trudno ocenić, jaki rodzaj przygody może to doprowadzić w przyszłości ( dość sceptyczny )
Konflikty:
bez implementacji kolejnej warstwy repozytorium, która zwraca Agregat, nie jesteśmy nawet w stanie częściowo rozwiązać wyżej wspomnianych pułapek
wdrażając dodatkową warstwę repozytorium, ignorujemy wbudowane funkcje EF (każde
DbSet
jest już repozytorium) i nadmiernie komplikujemy aplikację
Mój wniosek:
Proszę o wybaczenie mojej ignorancji, ale w oparciu o powyższe informacje - albo Entity Framework nie jest odpowiedni do projektowania opartego na domenie, albo projektowanie oparte na domenie jest niedoskonałe i przestarzałe .
Podejrzewam, że każde z tych podejść ma swoje zalety, ale teraz jestem całkowicie zagubiony i nie mam najmniejszego pojęcia, jak pogodzić EF z DDD.
Jeśli się mylę - czy ktoś mógłby szczegółowo opisać prosty zestaw instrukcji (lub nawet podać porządny przykład kodu), jak postępować w sprawie DDD z EF, proszę?
Odpowiedzi:
DDD i EF nie mają ze sobą nic wspólnego.
DDD to koncepcja modelowania. Oznacza to przemyślenie Domeny, wymagań biznesowych i modelowanie ich. Zwłaszcza w kontekście orientacji obiektowej oznacza to stworzenie projektu odzwierciedlającego funkcje i możliwości biznesowe.
EF jest technologią trwałości. Dotyczy to głównie danych i rekordów bazy danych.
Ci dwaj są bardzo rozwiedzeni. Projekt DDD może wykorzystywać EF w jakiejś formie pod maską, ale te dwa nie powinny oddziaływać w żaden inny sposób.
Niektóre interpretacje projektowania opartego na domenach faktycznie popierają modelowanie danych i myślę, że o to właśnie chodzi w tym pytaniu. W tej interpretacji „jednostki” i „obiekty wartości” są zasadniczo tylko pozbawionymi funkcji posiadaczami danych, a projekt dotyczy samych właściwości, jakie one posiadają i jakie mają między sobą relacje. W tym kontekście mogą pojawić się DDD vs. EF.
Ta interpretacja jest jednak błędna i zdecydowanie zalecałbym jej całkowite zignorowanie.
Podsumowując : DDD i EF nie wykluczają się wzajemnie, w rzeczywistości są dla siebie nieistotne, o ile wykonujesz właściwe modelowanie obiektów, a nie modelowanie danych. Obiekty DDD nie powinny mieć żadnego kształtu ani formy jako artefakty EF. Podmioty DDD nie powinny być na przykład „podmiotami” EF. Wewnątrz niektórych funkcji związanych z biznesem projekt DDD może wykorzystywać EF z niektórymi powiązanymi obiektami danych, ale powinny one zawsze być ukryte pod odpowiednim dla biznesu interfejsem zorientowanym na zachowanie.
źródło
Traktuj EF za to, co to jest, tj. Biblioteka dostępu do danych, która jest tylko nieco mocniej napisana niż surowy ADO.NET. Nie zalecałbym modelowania domeny za pomocą klas encji EF, tak jak nie zalecałbym modelowania domeny za pomocą surowego DataSet lub DataTable.
Rozumiem, że EF jest sprzedawany jako skrót między dostępem do bazy danych a modelowaniem domen, jednak takie podejście jest wewnętrznie wadliwe, ponieważ rozwiązuje dwa zasadniczo niezwiązane ze sobą problemy. W .NET były inne próby zmuszenia klasy do wykonania pewnych całkowicie niezwiązanych rzeczy (np. .NET Remoting) i nie zakończyły się dobrze.
Wykonaj DDD za pomocą klas POCO i nie pozwól, aby schemat bazy danych sterował twoim projektem. Trzymaj EF w warstwie repozytorium / trwałości i nie pozwól, aby jednostki EF wyciekły na zewnątrz.
źródło
Nie.
Abstrakcje Entity Framework zostały zbudowane z myślą o ORM, a nie DDD.
DbSet
Abstrakcji w dowolnej wersji Entity Framework jest dalekie prostotą DDD Repository - nie wspominającDbContext
co naraża zillion rzeczy bardziej niż UnitOfWork.Oto niewyczerpująca lista elementów w streszczeniu EF Core 2.1
DbSet<TEntity>
, których nie potrzebujemy w DDD:Attach(TEntity)
i całe jego rodzeństwoFind(Object[])
Update(TEntity)
i całe jego rodzeństwoIQueryable
Oprócz przeciągania wraz z nimi niepotrzebnych zależności, przesłaniają one zamiar repozytorium, które normalnie ujawnia bardzo proste zachowanie kolekcji. Ponadto nieszczelne abstrakty są ciągłą pokusą dla programistów, aby zbyt mocno związać się z EF i stanowić zagrożenie dla separacji obaw.
Podsumowując: musisz zawinąć te tłuszcze w ładne, usprawnione koncepcje i zgadnij, co to oznacza wprowadzenie dodatkowych klas.
Względnie dobry przykład tego, co można zrobić z EF i DDD (chociaż niektóre wyrażone punkty widzenia są dyskusyjne): https://kalele.io/blog-posts/modeling-aggregates-with-ddd-and-entity-framework/
Naprawdę nie widzę związku między dwiema częściami tego zdania. Bez względu na podejście, w DDD jest coś o nazwie Usługa aplikacji i tam manipulujesz Jednostką Pracy / Repozytorium (lub
DbContext
). Nie w zagregowanych korzeniach.Chociaż byłoby to uzasadnione podejście, gdyby było wykształconym kompromisem, niedawny trend antyrepozytorium „minimalizm Entity Framework” jest urojeniowy. Obwinia wzorce DDD za tarcie występujące w Entity Framework, gdy tak naprawdę twórcy EF nie zrobili nic, aby ich szkielet był zgodny z najlepszymi praktykami od samego początku. Przez cały czas są one ściśle powiązane z tą samą strukturą, ze wszystkimi problemami związanymi z bezpieczeństwem kodu i łatwością konserwacji, które mogą wystąpić.
źródło
Zastosowałem podejście, w którym każde agregat otrzymuje swój własny DBContext, odwzorowując tylko to, co jest potrzebne do agregacji. Myślę, że opisała to także Julie Lerman.
To zadziałało bardzo dobrze, ale może nie wystarczyć dla bardziej interesujących modeli, w których nie chcesz łączyć swoich koncepcji ze swoimi bytami.
źródło
Chciałbym tylko podzielić się możliwym rozwiązaniem do rozważenia:
unikaj bezpośredniego odwoływania się do projektu EF w warstwie usług
utwórz dodatkową warstwę repozytorium (używa projektu EF i zwraca Korzeń agregacji)
odwołać się do projektu Repository Layer in Service Layer
Architektura :
Interfejs użytkownika
Warstwa kontrolera
Warstwa serwisowa
Warstwa repozytorium
Entity Framework
Projekt podstawowy (zawiera modele EF)
Pułapki, które widzę przy takim podejściu:
jeśli repozytorium zwraca korzeń agregujący nie jako drzewo modelu EF (np. zwracamy zmapowany obiekt) - tracimy zdolność EF do śledzenia zmian
jeśli Aggregate Root jest modelem EF - wszystkie jego właściwości nawigacyjne są nadal dostępne , nawet jeśli nie możemy sobie z tym poradzić
DbContext
(nie odwołujemy się do projektu EF w Warstwie usług)źródło