Sedikit pengetahuan domain
Saya sedang menulis perangkat lunak POS (Point Of Sales) yang memungkinkan untuk membayar barang atau mengembalikannya. Saat membayar atau mengembalikan uang, orang perlu menentukan transfer uang mana yang digunakan: uang tunai, EFT (~ = kartu kredit), kartu loyalitas, voucher, dll.
Cara pengiriman uang ini adalah seperangkat nilai yang terbatas dan dikenal (semacam enum).
Bagian yang sulit adalah bahwa saya harus dapat menyimpan subset kustom cara ini untuk pembayaran dan pengembalian uang (dua set mungkin berbeda) di terminal POS.
Sebagai contoh:
- Pembayaran yang tersedia berarti: Tunai, EFT, kartu Loyalitas, Voucher
- Pengembalian dana yang tersedia berarti: Tunai, Voucher
Kondisi implementasi saat ini
Saya memilih untuk menerapkan konsep transfer uang sebagai berikut:
public abstract class MoneyTransferMean : AggregateRoot
{
public static readonly MoneyTransferMean Cash = new CashMoneyTransferMean();
public static readonly MoneyTransferMean EFT = new EFTMoneyTransferMean();
// and so on...
//abstract method
public class CashMoneyTransferMean : MoneyTransferMean
{
//impl of abstract method
}
public class EFTMoneyTransferMean : MoneyTransferMean
{
//impl of abstract method
}
//and so on...
}
Alasannya bukan "plain enum" adalah bahwa ada beberapa perilaku yang ada di dalam kelas-kelas ini. Saya juga harus mendeklarasikan kelas dalam publik (bukan privat) untuk merujuk mereka dalam pemetaan FluentNHibernate (lihat di bawah).
Bagaimana ini digunakan
Baik sarana pembayaran dan pengembalian dana selalu disimpan atau diambil di / dari DB sebagai set. Mereka benar-benar dua set yang berbeda meskipun beberapa nilai di dalam kedua set mungkin sama.
Use case 1: tentukan perangkat pembayaran / pengembalian uang yang baru
- Hapus semua pembayaran / pengembalian dana yang ada
- Masukkan yang baru
Use case 2: ambil semua sarana pembayaran / pengembalian dana
- Dapatkan koleksi semua pembayaran / pengembalian dana yang tersimpan
Masalah
Saya terjebak dengan desain saya saat ini pada aspek ketekunan. Saya menggunakan NHibernate (dengan FluentNHibernate untuk mendeklarasikan peta kelas) dan saya tidak dapat menemukan cara untuk memetakannya ke beberapa skema DB yang valid.
Saya menemukan bahwa dimungkinkan untuk memetakan kelas beberapa kali menggunakan entitas-nama namun saya tidak yakin bahwa itu mungkin dengan subclass.
Apa yang saya tidak siap lakukan adalah mengubah API publik MoneyTransferMean agar dapat bertahan (misalnya menambahkan bool isRefund
untuk membedakan antara keduanya). Namun menambahkan beberapa bidang diskriminator pribadi tidak masalah.
Pemetaan saya saat ini:
public sealed class MoneyTransferMeanMap : ClassMap<MoneyTransferMean>
{
public MoneyTransferMeanMap()
{
Id(Entity.Expressions<MoneyTransferMean>.Id);
DiscriminateSubClassesOnColumn("Type")
.Not.Nullable();
}
}
public sealed class CashMoneyTransferMeanMap : SubclassMap<MoneyTransferMean.CashMoneyTransferMean>
{
public CashMoneyTransferMeanMap()
{
DiscriminatorValue("Cash");
}
}
public sealed class EFTMoneyTransferMeanMap : SubclassMap<MoneyTransferMean.EFTMoneyTransferMean>
{
public EFTMoneyTransferMeanMap()
{
DiscriminatorValue("EFT");
}
}
//and so on...
Namun pemetaan ini mengkompilasi hanya menghasilkan 1 tabel dan saya tidak dapat membedakan antara pembayaran / pengembalian dana saat kueri tabel ini.
Saya mencoba untuk mendeklarasikan dua pemetaan yang merujuk MoneyTransferMean
pada tabel dan entitas-nama yang berbeda namun ini membuat saya terkecuali Duplicate class/entity mapping MoneyTransferMean+CashMoneyTransferMean
.
Saya juga mencoba untuk menduplikasi pemetaan subclass tapi saya tidak dapat menentukan "pemetaan orangtua" yang membawa saya ke pengecualian yang sama seperti di atas.
Pertanyaan
Apakah ada solusi untuk mempertahankan entitas domain saya saat ini?
Jika tidak, apa yang akan menjadi refactor terkecil yang perlu saya lakukan pada entitas saya untuk membuat mereka bertahan dengan NHibnernate?
What I'm not ready to do is to alter the MoneyTransferMean public API to be able to persist it (for example adding a bool isRefund to differentiate between the two).
: Kenapa tidak? Ini adalah perubahan yang sederhana dan manis yang harus menyelesaikan masalah Anda. Anda dapat membuat dengan tiga kemungkinan nilai (meskipun dua juga akan melakukan dengan catatan duplikat atauFlag
jenis):Payment
,Refund
,Both
. Jika dua nilai cocok untuk Anda,bool
properti itu bagus.