Perangkap Desain Berbasis Domain dengan Kerangka Entitas

12

Banyak tutorial tentang DDD yang saya pelajari kebanyakan membahas teori. Mereka semua memiliki contoh kode yang belum sempurna (Pluralsight dan sejenisnya).

Di web ada juga upaya oleh beberapa orang untuk membuat tutorial yang mencakup DDD dengan EF. Jika Anda mulai mempelajarinya secara singkat - Anda dengan cepat menyadari bahwa mereka sangat berbeda satu sama lain. Beberapa orang merekomendasikan untuk menjaga aplikasi minimal dan untuk menghindari memperkenalkan lapisan tambahan misalnya repositori di atas EF , yang lain jelas menghasilkan lapisan tambahan, sering bahkan melanggar SRP dengan menyuntikkan DbContextke Agregat Root.

Saya sangat minta maaf jika saya mengajukan pertanyaan berdasarkan opini, tapi ...

Ketika sampai pada praktik - Entity Framework adalah salah satu ORM yang paling kuat dan banyak digunakan. Sayangnya, Anda tidak akan menemukan kursus komprehensif yang mencakup DDD.


Aspek penting:

  • Entity Framework DbSetmengeluarkan UoW & Repository ( ) di luar kotak

  • dengan EF model Anda memiliki properti navigasi

  • dengan EF semua model yang selalu tersedia off DbContext(mereka diwakili sebagai DbSet)

Perangkap:

  • Anda tidak dapat menjamin model anak Anda hanya terpengaruh melalui Agregat Root - model Anda memiliki sifat navigasi dan dimungkinkan untuk memodifikasinya dan memanggildbContext.SaveChanges()

  • dengan DbContextAnda dapat mengakses setiap model Anda, sehingga menghindari Root Agregat

  • Anda dapat membatasi akses ke anak-anak akar objek melalui ModelBuilderdi OnModelCreatingmetode dengan menandai mereka sebagai ladang - Aku masih tidak percaya itu adalah cara yang tepat untuk pergi tentang DDD ditambah sulit untuk mengevaluasi apa jenis petualangan ini dapat menyebabkan di masa depan ( cukup skeptis )

Konflik:

  • tanpa menerapkan lapisan repositori lain yang mengembalikan Agregat, kita bahkan tidak dapat menyelesaikan sebagian perangkap yang disebutkan di atas

  • dengan menerapkan lapisan repositori tambahan, kami mengabaikan fitur bawaan EF (semuanya DbSetsudah menjadi repo) dan menyulitkan aplikasi


Kesimpulan saya:

Maafkan ketidaktahuan saya, tetapi berdasarkan info di atas - itu Entity Framework tidak memadai untuk Desain Berbasis Domain atau Desain Berbasis Domain adalah pendekatan yang tidak sempurna dan usang .

Saya menduga masing-masing pendekatan memiliki kelebihan, tetapi saya benar-benar tersesat sekarang dan tidak memiliki ide sedikit pun tentang bagaimana merekonsiliasi EF dengan DDD.


Jika saya salah - bisakah seseorang setidaknya merinci set instruksi sederhana (atau bahkan memberikan contoh kode yang layak) tentang bagaimana cara DDD dengan EF, tolong?

Alex Herman
sumber
Saya merinci langkah-langkah di sini sesuai dengan pemahaman saya tentang cara kerja EF. Namun langkah-langkah itu tidak menangani masalah mengakses anak-anak dengan nav. properti atau oleh DbSet off DbContext.
Alex Herman

Jawaban:

8

DDD dan EF tidak ada hubungannya sama sekali.

DDD adalah konsep pemodelan. Ini berarti memikirkan Domain, Persyaratan Bisnis, dan memodelkannya. Khususnya dalam konteks orientasi objek artinya menciptakan desain yang mencerminkan fungsi dan kemampuan bisnis.

EF adalah teknologi ketekunan. Ini terutama berkaitan dengan data dan catatan basis data.

Keduanya bercerai dengan tajam. Desain DDD dapat menggunakan EF dalam beberapa bentuk di bawah tenda, tetapi keduanya tidak boleh berinteraksi dengan cara lain.

Beberapa interpretasi Desain Berbasis Domain benar-benar menganjurkan pemodelan data, dan saya pikir inilah pertanyaan Anda. Dalam interpretasi ini, "Entitas" dan "Objek Nilai" pada dasarnya adalah pemegang data yang kurang berfungsi saja, dan desain itu sendiri berkenaan dengan properti apa yang dimiliki dan hubungan apa yang mereka miliki antara satu sama lain. Dalam konteks ini DDD vs. EF dapat muncul.

Namun interpretasi ini cacat, dan saya sangat merekomendasikan untuk mengabaikannya sama sekali.

Kesimpulannya : DDD dan EF tidak saling eksklusif, mereka sebenarnya tidak relevan satu sama lain, selama Anda melakukan pemodelan objek yang tepat dan bukan pemodelan data. Objek DDD tidak boleh dalam bentuk atau bentuk apa pun menjadi artefak EF. Entitas DDD seharusnya tidak menjadi "entitas" EF misalnya. Di dalam beberapa fungsi yang relevan dengan bisnis, desain DDD mungkin menggunakan EF dengan beberapa objek data terkait, tetapi yang harus selalu disembunyikan di bawah antarmuka berorientasi perilaku yang relevan dengan bisnis.

Robert Bräutigam
sumber
1
EF hanya menghemat waktu. Pelacakan perubahan dan kegigihan agregat adalah tempat EF telah banyak membantu. Sayangnya, saat ini tidak ada cara untuk menentukan bentuk agregat pada tingkat konfigurasi.
Pavel Voronin
6

Perlakukan EF untuk apa itu yaitu perpustakaan akses data yang hanya sedikit lebih kuat daripada ADO.NET mentah. Saya tidak akan merekomendasikan untuk memodelkan domain Anda menggunakan kelas entitas EF seperti saya tidak akan merekomendasikan untuk memodelkan domain menggunakan DataSet mentah atau DataTable.

Saya mengerti bahwa EF dijual sebagai jalan pintas antara akses basis data dan pemodelan domain namun pendekatan ini secara intrinsik cacat karena menangani dua masalah yang sebagian besar tidak berhubungan. Ada upaya lain di .NET untuk membuat kelas melakukan beberapa hal yang sama sekali tidak terkait (misalnya .NET Remoting) dan mereka tidak berakhir dengan baik.

Lakukan DDD menggunakan kelas POCO dan jangan biarkan skema basis data untuk mendorong desain Anda. Simpan EF di dalam repositori / lapisan persistensi dan jangan biarkan entitas EF bocor di luar.

Kola
sumber
5

Entity Framework mengeluarkan UoW & Repository (DbSet) di luar kotak

Tidak.

Abstraksi Kerangka Entitas dibangun dengan ORM, bukan DDD, dalam pikiran. The DbSetabstraksi dalam versi Entity Framework adalah tempat di dekat kesederhanaan dari DDD Repository - tidak menyebutkan DbContextyang mengekspos miliaran hal lebih dari UnitOfWork.

Berikut adalah daftar elemen yang tidak lengkap dalam abstrak EF Core 2.1 DbSet<TEntity>yang tidak kita butuhkan dalam DDD:

  • Attach(TEntity) dan semua saudara kandungnya
  • Find(Object[])
  • Update(TEntity) dan semua saudara kandungnya
  • Menerapkan IQueryable

Selain menyeret bersama dependensi yang tidak dibutuhkan dengan mereka, ini mengaburkan maksud Repositori yang biasanya memperlihatkan perilaku pengumpulan yang sangat sederhana. Ditambah abstraksi yang bocor adalah godaan terus-menerus bagi pengembang untuk terlalu banyak berpasangan dengan EF dan ancaman bagi Pemisahan Kekhawatiran.

Intinya: Anda harus membungkus lemak ini menjadi konsep yang bagus dan efisien dan coba tebak, itu berarti memperkenalkan kelas tambahan.

Contoh yang relatif baik tentang apa yang dapat Anda lakukan dengan EF dan DDD (meskipun beberapa sudut pandang yang diungkapkan masih bisa diperdebatkan): https://kalele.io/blog-posts/modeling-aggregates-with-ddd-and-entity-framework/

yang lain dengan jelas menghasilkan lapisan tambahan, bahkan sering melanggar SRP dengan menyuntikkan DbContext ke dalam Agregat Roots

Saya benar-benar tidak melihat hubungan antara dua bagian kalimat ini. Apa pun pendekatannya, ada sesuatu dalam DDD yang disebut Layanan Aplikasi dan di situlah Anda memanipulasi Unit Kerja / Repositori (atau DbContext). Tidak di Agregat Roots.

Meskipun itu bisa menjadi pendekatan yang valid jika itu merupakan tradeoff yang terdidik, tren anti-Repositori, "minimalisme Entity Framework" baru-baru ini adalah delusi. Ini menyalahkan pola DDD untuk gesekan yang terjadi dengan Entity Framework ketika benar-benar pencipta EF yang tidak melakukan apa pun untuk membuat kerangka mereka sesuai dengan praktik terbaik di luar kotak. Semua sementara mereka semakin erat dengan kerangka itu dengan semua masalah dalam hal keamanan kode dan rawatan yang dapat terjadi.

guillaume31
sumber
2

Konflik:

tanpa menerapkan lapisan repositori lain yang mengembalikan Agregat, kita bahkan tidak bisa menyelesaikan sebagian perangkap yang disebutkan di atas

dengan menerapkan lapisan repositori tambahan, kami mengabaikan fitur bawaan EF (setiap DbSet sudah merupakan repo) dan terlalu menyulitkan aplikasi

Saya telah menggunakan pendekatan di mana setiap Agregat mendapatkan DBConteksnya sendiri, memetakan apa yang dibutuhkan untuk Agregat. Saya pikir ini juga telah dijelaskan oleh Julie Lerman.

Ini bekerja dengan sangat baik, tetapi mungkin tidak cukup untuk model yang lebih menarik, di mana Anda tidak ingin menghubungkan konsep Anda dengan entitas Anda.

mvg
sumber
Terlihat juga video ini dddcommunity.org/ddd-contributors/...
Alex Herman
Apakah ada manfaat dari pendekatan DBContext Per Agregat? Apakah ini cara standar untuk menerapkan DDD dengan EF?
Alex Herman
Bukankah Julie Lerman berarti DbContext per Bounded context?
Mvision
0

Hanya ingin berbagi solusi yang memungkinkan untuk dipertimbangkan:

  1. hindari merujuk proyek EF di Lapisan Layanan secara langsung

  2. buat Layer Repositori tambahan (menggunakan proyek EF & mengembalikan Agregat Root)

  3. referensi Lapisan Repositori dalam proyek Lapisan Layanan

Arsitektur :

  • UI

  • Lapisan Pengontrol

  • Lapisan Layanan

  • Lapisan Repositori

  • Kerangka Entitas

  • Proyek Inti (berisi model EF)


Perangkap yang saya lihat dengan pendekatan ini:

  • jika Repositori mengembalikan Agregat Root bukan sebagai pohon model EF (mis. kami mengembalikan objek yang dipetakan) - kami kehilangan kemampuan EF untuk melacak perubahan

  • jika Agregat Root adalah model EF - semua properti navigasinya masih tersedia , meskipun kami tidak dapat mengatasinya DbContext(kami tidak merujuk proyek EF di Lapisan Layanan)

Alex Herman
sumber