Dalam perdebatan model domain Rich vs Anemic, internet penuh dengan saran filosofis tetapi pendek pada contoh-contoh otoritatif. Tujuan dari pertanyaan ini adalah untuk menemukan pedoman definitif dan contoh nyata dari model Desain Berbasis Domain yang tepat. (Idealnya dalam C #.)
Sebagai contoh dunia nyata, implementasi DDD ini tampaknya salah:
Model domain WorkItem di bawah tidak lain adalah tas properti, yang digunakan oleh Entity Framework untuk database kode-pertama. Per Fowler, itu adalah anemia .
Lapisan WorkItemService tampaknya merupakan persepsi yang salah tentang Layanan Domain; ini berisi semua logika perilaku / bisnis untuk WorkItem. Per Yemelyanov dan lainnya, ini bersifat prosedural . (hal 6)
Jadi jika di bawah ini salah, bagaimana saya bisa memperbaikinya?
Perilaku, yaitu AddStatusUpdate atau Checkout , harus termasuk dalam kelas WorkItem yang benar?
Ketergantungan apa yang harus dimiliki oleh model WorkItem?
public class WorkItemService : IWorkItemService {
private IUnitOfWorkFactory _unitOfWorkFactory;
//using Unity for dependency injection
public WorkItemService(IUnitOfWorkFactory unitOfWorkFactory) {
_unitOfWorkFactory = unitOfWorkFactory;
}
public void AddStatusUpdate(int workItemId, int statusId) {
using (var unitOfWork = _unitOfWorkFactory.GetUnitOfWork<IWorkItemUnitOfWork>()) {
var workItemRepo = unitOfWork.WorkItemRepository;
var workItemStatusRepo = unitOfWork.WorkItemStatusRepository;
var workItem = workItemRepo.Read(wi => wi.Id == workItemId).FirstOrDefault();
if (workItem == null)
throw new ArgumentException(string.Format(@"The provided WorkItem Id '{0}' is not recognized", workItemId), "workItemId");
var status = workItemStatusRepo.Read(s => s.Id == statusId).FirstOrDefault();
if (status == null)
throw new ArgumentException(string.Format(@"The provided Status Id '{0}' is not recognized", statusId), "statusId");
workItem.StatusHistory.Add(status);
workItemRepo.Update(workItem);
unitOfWork.Save();
}
}
}
(Contoh ini disederhanakan agar lebih mudah dibaca. Kode ini jelas masih kikuk, karena ini merupakan upaya yang membingungkan, tetapi perilaku domainnya adalah: perbarui status dengan menambahkan status baru ke riwayat arsip. Pada akhirnya saya setuju dengan jawaban lain, ini hanya bisa ditangani oleh CRUD.)
Memperbarui
@AlexeyZimarev memberikan jawaban terbaik, video yang sempurna tentang subjek dalam C # oleh Jimmy Bogard, tetapi tampaknya dipindahkan ke komentar di bawah karena tidak memberikan informasi yang cukup di luar tautan. Saya memiliki konsep kasar catatan saya yang merangkum video dalam jawaban saya di bawah ini. Silakan mengomentari jawaban dengan koreksi apa pun. Video ini berdurasi satu jam tetapi sangat layak ditonton.
Perbarui - 2 Tahun Kemudian
Saya pikir itu adalah tanda kedewasaan DDD yang baru lahir bahwa bahkan setelah mempelajarinya selama 2 tahun, saya masih tidak bisa berjanji bahwa saya tahu "cara yang benar" untuk melakukannya. Bahasa di mana-mana, akar agregat, dan pendekatannya terhadap desain yang didorong perilaku adalah kontribusi berharga DDD untuk industri. Ketidaktahuan yang gigih dan sumber acara menyebabkan kebingungan, dan saya pikir filsafat seperti itu menahannya dari adopsi yang lebih luas. Tetapi jika saya harus melakukan kode ini lagi, dengan apa yang telah saya pelajari, saya pikir akan terlihat seperti ini:
Saya masih menyambut jawaban apa pun untuk pos ini (sangat aktif) yang memberikan kode praktik terbaik untuk model domain yang valid.
"I don't want to duplicate all my entities into DTOs simply because I don't need it and it violates DRY, and I also don't want my client application to take a dependency on EntityFramework.dll"
. "Entitas" dalam jargon Entity Framework tidak sama dengan "Entities" seperti pada "Domain Model"Jawaban:
Jawaban yang paling membantu diberikan oleh Alexey Zimarev dan mendapatkan setidaknya 7 upvotes sebelum moderator memindahkannya ke komentar di bawah pertanyaan awal saya ....
Jawabannya:
Saya membuat beberapa catatan untuk merangkum video tersebut untuk kepentingan tim saya dan untuk memberikan sedikit detail lebih cepat dalam posting ini. (Video ini berdurasi satu jam, tetapi benar-benar bernilai setiap menit jika Anda punya waktu. Jimmy Bogard layak mendapatkan banyak pujian untuk penjelasannya.)
Jangan ragu untuk berkomentar dengan poin lain yang menurut Anda harus dimasukkan, atau jika menurut Anda salah satu dari catatan ini tidak tepat sasaran. Mencoba mengutip secara langsung atau memparafrasekan sebanyak mungkin.
sumber
Pertanyaan Anda tidak dapat dijawab, karena contoh Anda salah. Khususnya, karena tidak ada perilaku. Paling tidak di area domain Anda. Contoh
AddStatusUpdate
metode bukan logika domain, tetapi logika yang menggunakan domain itu. Logika semacam itu masuk akal untuk berada di dalam semacam layanan, yang menangani permintaan dari luar.Misalnya, jika ada persyaratan bahwa item kerja tertentu hanya dapat memiliki status tertentu, atau hanya dapat memiliki status N, maka itu adalah logika domain dan harus menjadi bagian dari salah satu
WorkItem
atauStatusHistory
sebagai metode.Alasan kebingungan Anda adalah karena Anda mencoba menerapkan pedoman untuk kode yang tidak memerlukannya. Model domain hanya relevan jika Anda memiliki banyak logika domain yang kompleks. Misalnya. logika yang bekerja pada entitas itu sendiri dan berasal dari persyaratan. Jika kode adalah tentang memanipulasi entitas dari data luar, maka itu kemungkinan besar bukan logika domain. Tetapi saat Anda mendapatkan banyak
if
berdasarkan pada data dan entitas yang Anda kerjakan, maka itu adalah logika domain.Salah satu masalah pemodelan domain sejati adalah bahwa hal ini adalah tentang mengelola persyaratan yang kompleks. Dan dengan demikian kekuatan dan manfaatnya yang sesungguhnya tidak dapat ditampilkan dengan kode sederhana. Anda memerlukan banyak entitas dengan banyak persyaratan di sekitar mereka untuk benar-benar melihat manfaatnya. Sekali lagi, contoh Anda terlalu sederhana untuk model domain untuk benar-benar bersinar.
Akhirnya, beberapa hal OT yang akan saya sebutkan adalah bahwa model domain yang benar dengan desain OOP nyata akan sangat sulit untuk bertahan menggunakan Entity Framework. Sementara ORM dirancang dengan memetakan struktur OOP yang benar ke yang relasional, masih ada banyak masalah, dan model relasional akan sering bocor ke dalam model OOP. Bahkan dengan nHibernate, yang saya anggap jauh lebih kuat daripada EF, ini bisa menjadi masalah.
sumber
Asumsi Anda bahwa merangkum logika bisnis Anda yang terkait dengan WorkItem ke dalam "layanan gemuk" adalah anti-pola yang melekat yang saya berpendapat tidak harus.
Terlepas dari pemikiran Anda tentang model domain anemia, pola dan praktik standar yang khas dari aplikasi Lini Bisnis. NET mendorong pendekatan berlapis transaksional yang terdiri dari berbagai komponen. Mereka mendorong pemisahan logika bisnis dari model domain secara khusus untuk memfasilitasi komunikasi dari model domain umum di komponen .NET lainnya serta komponen pada tumpukan teknologi yang berbeda atau lintas tingkatan fisik.
Salah satu contohnya adalah layanan web SOAP berbasis NET yang berkomunikasi dengan aplikasi klien Silverlight yang kebetulan memiliki DLL yang berisi tipe data sederhana. Proyek entitas domain ini dapat dibangun menjadi rakitan .NET atau rakitan Silverlight, di mana komponen Silverlight yang tertarik yang memiliki DLL ini tidak akan terkena perilaku objek yang mungkin bergantung pada komponen yang hanya tersedia untuk layanan.
Terlepas dari sikap Anda pada debat ini, ini adalah pola yang diadopsi dan diterima yang diajukan oleh Microsoft dan menurut pendapat profesional saya ini bukan pendekatan yang salah, tetapi kemudian model objek yang mendefinisikan perilakunya sendiri tidak harus merupakan anti-pola juga. Jika Anda melangkah maju dengan desain ini, yang terbaik adalah menyadari dan memahami beberapa batasan dan titik sakit yang mungkin Anda temui jika Anda perlu berintegrasi dengan komponen lain yang perlu melihat model domain Anda. Dalam kasus tertentu mungkin Anda mungkin ingin memiliki Penerjemah mengubah model domain gaya berorientasi objek Anda menjadi objek data sederhana yang tidak memaparkan metode perilaku tertentu.
sumber
Saya menyadari pertanyaan ini sudah cukup tua sehingga jawaban ini untuk anak cucu. Saya ingin menjawab dengan contoh konkret alih-alih berdasarkan pada teori.
Meringkas "perubahan status item pekerjaan" di
WorkItem
kelas seperti:Sekarang
WorkItem
kelas Anda bertanggung jawab untuk mempertahankan diri dalam keadaan hukum. Namun implementasinya sangat lemah. Pemilik produk menginginkan riwayat semua pembaruan status yang dibuat untukWorkItem
.Kami mengubahnya menjadi seperti ini:
Implementasi telah berubah secara drastis tetapi penelepon
ChangeStatus
metode ini tidak mengetahui rincian implementasi yang mendasarinya dan tidak memiliki alasan untuk mengubahnya sendiri.Ini adalah contoh entitas model domain yang kaya, IMHO.
sumber