Saya telah mengadaptasi desain berbasis domain selama sekitar 8 tahun sekarang dan bahkan setelah bertahun-tahun, masih ada satu hal, yang telah mengganggu saya. Itu memeriksa catatan unik dalam penyimpanan data terhadap objek domain.
Pada September 2013 Martin Fowler menyebutkan prinsip TellDon'tAsk , yang, jika mungkin, harus diterapkan ke semua objek domain, yang kemudian harus mengembalikan pesan, bagaimana operasi berjalan (dalam desain berorientasi objek ini sebagian besar dilakukan melalui pengecualian, ketika operasi tidak berhasil).
Proyek saya biasanya dibagi menjadi banyak bagian, di mana dua di antaranya adalah Domain (berisi aturan bisnis dan tidak ada yang lain, domain tersebut benar-benar tidak peduli) dan Layanan. Layanan yang mengetahui tentang lapisan repositori yang digunakan untuk data CRUD.
Karena keunikan atribut yang dimiliki suatu objek adalah aturan domain / bisnis, itu harus panjang untuk modul domain, jadi aturannya persis di tempat seharusnya.
Untuk dapat memeriksa keunikan catatan, Anda perlu meminta dataset saat ini, biasanya database, untuk mencari tahu, apakah catatan lain dengan katakanlah Name
sudah ada.
Mempertimbangkan lapisan domain adalah kegigihan dan tidak tahu bagaimana cara mengambil data tetapi hanya bagaimana melakukan operasi pada mereka, itu tidak dapat benar-benar menyentuh repositori itu sendiri.
Desain yang saya adaptasi terlihat seperti ini:
class ProductRepository
{
// throws Repository.RecordNotFoundException
public Product GetBySKU(string sku);
}
class ProductCrudService
{
private ProductRepository pr;
public ProductCrudService(ProductRepository repository)
{
pr = repository;
}
public void SaveProduct(Domain.Product product)
{
try {
pr.GetBySKU(product.SKU);
throw Service.ProductWithSKUAlreadyExistsException("msg");
} catch (Repository.RecordNotFoundException e) {
// suppress/log exception
}
pr.MarkFresh(product);
pr.ProcessChanges();
}
}
Hal ini menyebabkan layanan menentukan aturan domain daripada lapisan domain itu sendiri dan Anda memiliki aturan yang tersebar di beberapa bagian kode Anda.
Saya menyebutkan prinsip TellDon'tAsk, karena seperti yang Anda lihat dengan jelas, layanan ini menawarkan tindakan (baik menyimpan Product
atau melempar pengecualian), tetapi di dalam metode ini Anda mengoperasikan objek dengan menggunakan pendekatan prosedural.
Solusi yang jelas adalah membuat Domain.ProductCollection
kelas dengan Add(Domain.Product)
metode melempar ProductWithSKUAlreadyExistsException
, tetapi kurang dalam kinerja banyak, karena Anda akan perlu mendapatkan semua Produk dari penyimpanan data untuk mengetahui dalam kode, apakah suatu Produk sudah memiliki SKU yang sama sebagai Produk yang ingin Anda tambahkan.
Bagaimana kalian memecahkan masalah khusus ini? Ini bukan masalah sebenarnya, saya telah memiliki lapisan layanan yang mewakili aturan domain tertentu selama bertahun-tahun. Lapisan layanan biasanya juga melayani operasi domain yang lebih kompleks, saya hanya ingin tahu apakah Anda telah menemukan solusi yang lebih baik, lebih terpusat, selama karir Anda.